【STM32 HAL库实战】串口DMA + 空闲中断 实现不定长数据接收

在STM32的应用开发中,经常需要通过串口接收不定长的数据。使用DMA(直接内存访问)可以提高数据传输的效率,而空闲中断则可以在数据接收完成后立即进行处理,无需轮询检查。本文将详细介绍如何使用STM32的串口DMA和空闲中断来实现不定长数据的接收。

1. 硬件准备

  • STM32F103C8T6开发板
  • 连接到串口的外部设备(如另一块单片机或串口调试助手)

2. 软件配置

使用STM32CubeMX配置串口和DMA:

  1. 配置串口:选择相应的串口(例如USART1),配置波特率、字长、停止位和奇偶校验位。
  2. 配置DMA:选择DMA通道和请求源,设置为循环模式,以便连续接收数据。
  3. 配置NVIC:设置DMA中断和串口空闲中断的优先级,并使能。

3. 代码实现

3.1 初始化串口和DMA
c 复制代码
#include "stm32f1xx_hal.h"

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();

    uint8_t rxBuffer[256]; // DMA接收缓冲区
    HAL_UART_Receive_DMA(&huart1, rxBuffer, sizeof(rxBuffer));
    
    while (1) {
        // 主循环中的其他任务
    }
}

static void MX_USART1_UART_Init(void) {
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart1);
}

static void MX_DMA_Init(void) {
    __HAL_RCC_DMA1_CLK_ENABLE();
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma_usart1_rx);
    __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx);
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if (uartHandle->Instance == USART1) {
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
}
3.2 配置空闲中断
c 复制代码
void MX_USART1_UART_Init(void) {
    // ... 省略其他初始化代码 ...
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
}
3.3 中断服务函数
c 复制代码
void USART1_IRQHandler(void) {
    HAL_UART_IRQHandler(&huart1);
}

void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 处理接收到的数据
        HAL_UART_DMAStop(&huart1);
        // 处理rxBuffer中的数据
        // 重新启动DMA接收
        HAL_UART_Receive_DMA(&huart1, rxBuffer, sizeof(rxBuffer));
    }
}

4. 注意事项

  • 确保DMA缓冲区足够大,能够存储接收到的数据。
  • 在空闲中断回调函数中,重新启动DMA接收,以便连续接收数据。
  • 使用空闲中断可以减少CPU的轮询检查,提高系统的效率。

通过上述步骤,我们可以在STM32F103C8T6上使用HAL库成功配置串口DMA和空闲中断,实现不定长数据的接收。这为开发需要高速数据传输和实时处理的嵌入式系统提供了基础。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

相关推荐
碧海银沙音频科技研究院5 小时前
基于炬芯ATS308X 设计的上位机usb 串口音乐EQ调节工具
stm32·单片机·嵌入式硬件
三佛科技-134163842129 小时前
过认证72W碳化硅方案(12V6A)主控HN1562+HN36228V 典型应用电路、变压器参数分享
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
Brilliantwxx10 小时前
【STM32】 内部 Flash 详解:寄存器逐位拆解 + 工作流程顺序全讲 + EEPROM再实现
stm32·单片机·嵌入式硬件·1024程序员节
木子单片机10 小时前
基于单片机的DS18B20温度传感器测温系统设计
单片机·嵌入式硬件·51单片机·keil
华清远见IT开放实验室10 小时前
实验室建设案例 | 安徽三联学院物联网实验室
stm32·单片机·嵌入式硬件·物联网·华清远见
Zw-awa11 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
stm32
深圳光特通信豆子12 小时前
TTL 光模块在工业控制与串口通信中的应用指南(10M BIDI 单模系列)
单片机·嵌入式硬件
桀人12 小时前
SPI概念引入
stm32·单片机·嵌入式硬件
离凌寒13 小时前
一、基于stm32+freertos下LD2410D和R60ADB1两款雷达的使用效果
stm32·单片机·嵌入式硬件
国科安芯13 小时前
商业光学遥感载荷焦平面供电链的低噪声稳压器研究综述——以国科安芯ASP7A84AS型3A低压差线性稳压器为器件级参照
大数据·网络·嵌入式硬件·平面·卫星·商业航天·抗辐射