基于HAL库的串口空闲中断+DMA接受
文章目录
一、问题引入
在STM32 HAL库中,我们经常用到串口的接受与发送。在串口发送时,我们一般是主动发送,即固定字长HAL_UART_Transmit(&huart1,(uint8_t *)&ch,length,0xffff)
,这种很好实现。
在串口接受数据时,我们有很多方法:
1、轮询方式
:一直在占CPU资源,虽然简单,但很鸡肋。
2、中断方式
: 在HAL库中必须接受到指定的字长大小才会进入中断,对于接 受不定长的数据,没办法每次都能进中断,也不好用。
3、空闲中断
:一旦有数据到来就马上接受,当检测到大于一个字节的接受时间都没有数据时,说明处于空闲状态,自动进入中断处理
综上所述
:空闲中断是处理不定长数据接受的最佳办法
二、CubeMX配置
说明:此文章基于STM32F103C8T6配置,其他单片机大同小异
1、配置RCC
2、配置串口
说明:一般与电脑串口通信的是UART1(PA9 PA10),所以这里配置UART1
注意
:一定要打开中断开关
3、配置DMA接受
4、配置时钟及其他
说明:这里不再赘述
三、代码添加
1、变量的定义
uint8_t DMA_REbuffer[RECEIVE_SIZE];//定义DMA接受数组
uint8_t RE_length=0; //定义DMA接受的字节长度变量
2、初始化
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启串口1 空闲接受中断
HAL_UART_Receive_DMA(&huart1,(uint8_t *)&DMA_REbuffer,RECEIVE_SIZE);//使能串口1 DMA接受
3、在中断服务函数中添加代码
说明:在stm32f1xx_it.c文件中(专门处理中断函数的c文件)
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==SET)
{
uint16_t temp=0;
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除空闲中断接受标志位
HAL_UART_DMAStop(&huart1);//关闭DMA接受
temp = hdma_usart1_rx.Instance->CNDTR;//获取DMA未占用的字节
RE_length = RECEIVE_SIZE-temp-2;//计算出接受到的字节数
printf("进入了UART1空闲中断1\r\n");//打印信息
printf("接受的长度为:%d字节\r\n",RE_length);//打印信息
printf("接受的内容为:%s\r\n",DMA_REbuffer);//打印信息
memset(DMA_REbuffer,0x00,sizeof(DMA_REbuffer));//清除数组接受到的数据
}
HAL_UART_Receive_DMA(&huart1,(uint8_t *)&DMA_REbuffer,RECEIVE_SIZE);//重新使能DMA接受,继续下一轮接受
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
四.验证代码
发送“验证一下”,串口接受到数据后,计算字节长度并返回数据内容
总结
总结就是好好学习
附上源码文件:基于HAL库的串口空闲中断+DMA接受