(注)Dji的遥控器是每隔7ms返回一帧数据,每一帧数据有18个字节。本文的讲解注重快速使用上手,故细节部分会在后面依次改进,添加。
首先需要讲讲DMA(Derict memory access),翻译过来就是一条直接可以到存储器的通路。直接到存储器是什么意思呢?stm32有许多外设,如串口,当串口收到数据以后。会把数据存在DR寄存器里面,此时若打开了串口中断,则进入中断函数后,我们就可以存储数据。但这种办法的坏处则是每次都会触发中断,很浪费CPU的使用效率。而如果我们用了DMA,就可以不用进入中断了。举个例子:串口收18个数据。串口中断和DMA接收如下:
串口中断数据的存储过程=进入中断+变量赋值为串口DR的值(CPU进入中断18次,第18次处理此帧数据)
串口DMA存储数据过程=把DR收到的数据直接搬运到设置好的变量里面,当收到18个字节的数据则进入中断一次,处理收到的数据(CPU进入中断一次)
总而言之,DMA减轻了CPU负担。相当银行的vip通道,快速便捷,有专门的人为之服务。银行这一套正常的服务大众的系统,不会受到vip客人的影响。
DMA与外设的关系对应(stm32F1为例):DMA把所有的外设分类到各个通道,比如要用USART2_RX的数据则我们需要配置DMA1--channel6,中断服务子函数为DMA1_Channel6_IRQHandler();
所谓空闲中断即串口没收到数据的时间超过一个字节的时间,则进入中断函数。
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