本文主要阐述, 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个字节都接收完成。
下一篇文章将探索一下,不按套路发送数据时,会发生什么。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)