本文主要阐述, STM32芯片使用HAL库,如何用DMA的方式,来实现串口接收功能。(接收的数据长度是固定的)

STM32CubeMX的配置这里就不赘述了。上俩图吧

代码分为两处:

第一处:

main.c  (主要注意 “// ▲”注释)
#include "usermain.h" #include "AngelaSTM32/AngelaDecode.h" // ▲
我们串口接收用到的变量,函数,都在这里面 ... void main(){ MX_GPIO_Init(); MX_DMA_Init();
MX_USART1_UART_Init(); MX_TIM3_Init(); MX_TIM2_Init();
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); // ▲ 使能串口空闲中断
HAL_UART_Receive_DMA(&huart1, value,16); // ▲ 开启串口DMA接收 while (1); }
注意:AngelaDecode.h是main.c #include
的一个.h文件,里面是变量和函数的【声明】,其【定义】是在AngelaDecode.c中的。
// AngelaDecode.h #ifndef __USERPROGRAM_ANGELADECODE_H #define
__USERPROGRAM_ANGELADECODE_H extern unsigned char value[16]; extern unsigned
char AngelaRx[128]; extern short AngelaRxCNT; void AngelaCmdDecode(void); void
AngelaCmdExecute(void); #endif
第二处:

stm32f4xx_it.c
#include "AngelaSTM32/AngelaDecode.h" ... void USART1_IRQHandler(void){ int i;
HAL_UART_IRQHandler(&huart1); if( __HAL_UART_GET_FLAG(&huart1,
UART_FLAG_IDLE)!=RESET ){ // ▲ 判断是否为空闲中断 __HAL_UART_CLEAR_IDLEFLAG(&huart1); //
▲ 如果是空闲中断清除空闲中断标志 HAL_UART_DMAStop(&huart1); // ▲ 关闭串口的DMA接收
if(__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)==0){ // ▲ 注意:发送端是每次发送16字节的 for( i =
0; i < 16; i++){ AngelaRx[AngelaRxCNT+i] = value[i]; } AngelaRxCNT =
AngelaRxCNT + 16; } HAL_UART_Receive_DMA(&huart1, value, 16); // ▲ 再开启接收
if(AngelaRxCNT==128){ // ▲ 命令数据包的总长是128字节 AngelaCmdDecode(); AngelaRxCNT = 0; }
} }

如何理解空闲中断?

在串口无数据接收的情况下,不会产生空闲中断,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一旦接收的数据断流,没有接收到数据,即产生IDLE中断。

举例: 比如你每8个字节发一次串口数据过来,间隔1ms。那STM32这个接到8个字节后,短时间内没有接到数据,就产生了数据断流,这时候就会产生IDLE中断。

当然,如果你断断续续地发送数据,数据量是随机的而非固定的长度,同样可以产生IDLE中断。但这样的操作真的没有必要。

__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)作用是获取
当前DMA流传输中剩余数据单元的数量,产生空闲中断时,未必就是DMA已接收到16个字节,字节数也可能是1-15中任意一个数。只有当
__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)==0时,才代表16个字节都接收完成。

下一篇文章将探索一下,不按套路发送数据时,会发生什么。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信