空闲中断+DMA接收数据
目的:使用串口+DMA来接收DJI遥控器的数据帧。
(注)Dji的遥控器是每隔7ms返回一帧数据,每一帧数据有18个字节。本文的讲解注重快速使用上手,故细节部分会在后面依次改进,添加。
1.DMA的理解
首先需要讲讲DMA(Derict memory access),翻译过来就是一条直接可以到存储器的通路。直接到存储器是什么意思呢?stm32有许多外设,如串口,当串口收到数据以后。会把数据存在DR寄存器里面,此时若打开了串口中断,则进入中断函数后,我们就可以存储数据。但这种办法的坏处则是每次都会触发中断,很浪费CPU的使用效率。而如果我们用了DMA,就可以不用进入中断了。举个例子:串口收18个数据。串口中断和DMA接收如下:
串口中断数据的存储过程=进入中断+变量赋值为串口DR的值(CPU进入中断18次,第18次处理此帧数据)
串口DMA存储数据过程=把DR收到的数据直接搬运到设置好的变量里面,当收到18个字节的数据则进入中断一次,处理收到的数据(CPU进入中断一次)
总而言之,DMA减轻了CPU负担。相当银行的vip通道,快速便捷,有专门的人为之服务。银行这一套正常的服务大众的系统,不会受到vip客人的影响。
2.DMA的通道选择
DMA与外设的关系对应(stm32F1为例):DMA把所有的外设分类到各个通道,比如要用USART2_RX的数据则我们需要配置DMA1--channel6,中断服务子函数为DMA1_Channel6_IRQHandler();
空闲中断+DMA的配置初始化如下(具体代码见后面的附录)
usart2_init(); //串口的初始化配置 DMA_Config(DMA1_Channel6,(uint32_t)&(USART2->DR),(uint32_t)rxdata,18);//DMA通道配置 USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);//打开串口DMA中断
方法一:通过DMA中断来接收数据。
// 每接收18个数据则进入中断
void DMA1_Channel6_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC6)==SET)
{
DMA_ClearFlag(DMA1_FLAG_TC6); //清除DMA挂起位
DMA_ClearITPendingBit(DMA1_IT_TC6); //清除中断标志位
/*写自己接收到18个字节的数据要做的事情*/
}
}
方法二:空闲中断来接收数据
所谓空闲中断即串口没收到数据的时间超过一个字节的时间,则进入中断函数。
void USART2_IRQHandler(void)
{
char clear=clear;
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //中断源为空闲中断
{
clear = USART2->SR;
clear = USART2->DR; //读这两个寄存器来清除空闲中断标志位
/*写自己接收到18个字节的数据要做的事情*/
DMA_Cmd(DMA1_Channel6,DISABLE); //DMA只有DISABLE时,DMA_SetCurrDataCounter函数才有效。
DMA_SetCurrDataCounter(DMA1_Channel6,20);//接收18个数据为1帧,20个则一直打开DMA接收
DMA_Cmd(DMA1_Channel6,ENABLE);//打开DMA的此通道
}
}
具体代码如下:
链接:https://pan.baidu.com/s/1kB-P0TP9VZ9L8H5dFfl55g 提取码:d2rd
