空闲中断+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接收数据_第1张图片

 

空闲中断+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 
 

你可能感兴趣的:(单片机)