stm32 HAL库下 阻塞 中断(it) DMA 三种模式下的串口通讯函数逻辑梳理(不一定正确)
本文根据课程和ai梳理的,不保证正确
-
总结:
函数 | 触发的回调函数 | 触发条件 |
---|---|---|
HAL_UART_Receive_IT/DMA() |
仅 HAL_UART_RxCpltCallback |
缓冲区严格填满预设长度时触发(固定长度)。 |
HAL_UARTEx_ReceiveToIdle_DMA() |
可能触发 RxEventCallback 或 RxCpltCallback |
- 空闲中断触发 → RxEventCallback (动态长度)- 缓冲区满触发 → RxCpltCallback (固定长度) |
- 推荐使用ReceiveToIdle_(it/dma)来开启串口接收
- RxEventCallback来进行后的处理
- 顺带一提无论是用EventCallback还是CpltCallback,都要重新启用Receive或ReceiveToIdle,不然只会接收1次
-
基础的发送接收
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size) HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
-
参数
除了阻塞的串口 发送,读取 多一个超时uint32_t Timeout
参数,剩下的参数都一样UART_HandleTypeDef *huart
指定串口,例如&huart1
uint8_t *pData
指定缓冲区,通常是一个char数组,uart1_rx_buffer[128]
这种,作为参数的时候填入指针也就是uart1_rx_buffer
就行uint16_t Size
指定读取的最大长度,别超过缓冲区就行
Transmit
运行就会发送
Receive
仅仅是开启接受,什么时候接收完是另一回事
-
接收回调函数
基础的receive只有一种回调函数,HAL_UART_RxCpltCallback
(以及报错HAL_UARTEx_RxEventCallback
发生传输错误(如DMA溢出、噪声错误等)
然鹅HAL_UART_RxCpltCallback
触发的方式只有缓冲区满,所以不能直接做到不定长信息接收
所以用这个的话我可能会把缓冲区大小设置为1,然后每次接收到扔另一个大的缓冲区里,用个定时器负责管理大缓冲区清除,一段时间没有收到信息就清除,然后你看你是每次收到1字节就处理一下还是定时器准备清除前处理一下大缓冲区数据,总的来说很麻烦,
-
-
可检测空闲的接收
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,uint32_t Timeout)//这个用不上 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
-
参数
*huart
串口指针*pData
缓冲区指针Size
缓冲区大小
-
回调函数
-
缓冲区满了会触发
HAL_UART_RxCpltCallback
-
检测到空闲(有一帧没信息了)会触发
HAL_UARTEx_RxEventCallback
-
以及报错
HAL_UARTEx_RxEventCallback
发生传输错误(如DMA溢出、噪声错误等)
-
-
ps
- dma的串口有个独有特性叫“传输过半中断”,接收到的数据量到达设置的缓存区大小一半 就和空闲中断一样 也会执行一次eventcallback
若不处理此特性,遇到某个信息比较长 就有可能当成空闲中断 错误的截断信息 - 需要在每次运行(包括EventCallback里开启下次接受和第一次调用)
HAL_UARTEx_ReceiveToIdle_DMA
后都要运行一次__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
- 如果cubemx里选择了为每个外设生成单独的.c.h文件,在按照视频关闭dma半传输中断时会报错,在代码的开头加上
extern DMA_HandleTypeDef hdma_usart1_rx;
(根据你用的串口号)
可以解决
- dma的串口有个独有特性叫“传输过半中断”,接收到的数据量到达设置的缓存区大小一半 就和空闲中断一样 也会执行一次eventcallback
-