美文网首页
4. 关于DMA问题

4. 关于DMA问题

作者: 郑行_aover | 来源:发表于2019-05-09 10:33 被阅读0次

1. 问题:

  • 1、空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断;
  • 2、空闲中断是接收到一个数据以后,接收停顿超过一字节时间 认为桢收完,总线空闲中断是在检测到在接收数据后,数据总线上一个字节的时间内,没有再接到数据后发生。也就是RXNE位被置位之后,才开始检测,只被置位一次,除非再次检测到RXNE位被置位,然后才开始检测下一次的总线空闲。一次RXNE位被置位只进行一次。

2. 实现思路:

  • 确定串口,并配置成空闲中断模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。
  • 那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候(RXNE位被置位)并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后(接收停顿超过一字节时间)串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
  • 就是在串口空闲中断中使用 Usart1RecLen = DMARecLen-DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本帧数据长度 = DMA缓存的大小 - 剩余 DMA缓存大小

3. 配置时候注意:

    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启空闲中断
    DMA_InitStructure.DMA_BufferSize = DMA_Rec_Len;  //DMA通道的DMA缓存的大小

4. 乒乓缓存(DMA常常搭配乒乓缓存进行)

优势:

    1. 乒乓操作常常应用于流水线式算法,完成数据的无缝缓冲与处理。
    1. 节省缓冲区空间
    1. 可以使用低速模块处理高速数据

附:DMA部分示意代码

串口之DMA初始化步骤:(在代码中对比着看,加深理解)     
RXEN = 1:移位寄存器中的内容已经转移到RDR     
RXNEIE =1:产生中断  
串口使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激活。只要TXE位被置起,就从配置成使用DMA外设的SRAM区装载数据到USART_DR寄存器。为 USART的发送分配一个DMA通道的步骤如下(x表示通道号):  
1.  在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事件后,数据将被传送到这个地址。  
2.  在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,数据将从此存储器区传送到USART_DR寄存器。  
3.  在DMA控制寄存器中配置要传输的总的字节数。  
4.  在DMA寄存器上配置通道优先级。  
5.  根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。  
6.  在DMA寄存器上激活该通道。  
7.  当DMA控制器中指定的数据量传输完成时,DMA控制器在该DMA通道的中断向量上产生一中断。在中断服务程序里,软件应将USART_CR3寄存器的DMA位清零。  \

注意:  如果DMA被用于发送,不要使能TXEIE位。

串口使用DMA进行接收,可以通过设置USART_CR3寄存器的DMAR位激活。只要接收到一个字节,数据就从USART_DR寄存器放到配置成使用DMA的SRAM区(参考DMA技术说明)。为USART的接收分配一个DMA通道步骤如下(x表示通道号):  
1.  通过DMA控制寄存器把USART_DR寄存器地址配置成传输的源地址。在每个RXNE事件后此地址上的数据将传输到存储器。  
2.  通过DMA控制寄存器把存储器地址配置成传输的目的地址。在每个RXNE事件后,数据将从USART_DR传输到此存储器区。  
3.  在DMA控制寄存器中配置要传输的总的字节数。  
4.  在DMA寄存器上配置通道优先级。  
5.  根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。  
6.  在DMA控制寄存器上激活该通道。通用同步异步收发器(USART)   
7.  当DMA控制器中指定的传输数据量接收完成时,DMA控制器在该DMA通道的中断矢量上产生一中断。在中断程序里, USART_CR3寄存器的DMAR位应该被软件清零。  
注意:  如果DMA被用来接收,不要使能RXNEIE位。 

四.程序设计     这里摘取了部分代码讲解,完整代码及工程见附件下载哦。

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;   //外设作源头 
DMA_InitStructure.DMA_BufferSize = dma_len;        //BUF大小  
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增  这两项的配置还是很好理解的,比如在这里我们是要将内存里边的东西发到USART1中去,每次发送8位,那么外设地址当然不能改变,而每一次发送内容都是不一样的,而且数组在内存中的存放就是递增的,所以内存地址寄存器要递增。   

下边是设置数据宽度:

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位 
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //正常缓存模式(非连续传输)   一些基本定义:  
#define dma_len 100  //定义串口DMA传输数据长度
//(如果串口一次接收数据没有达到dma_len个byte,则不会发生DMA中断)   
extern u8 USART1_DMA_Buf1[dma_len]; 
//BUF1 extern u8 USART1_DMA_Buf2[dma_len]; 
//BUF2 typedef enum {BUF_NO1=0,BUF_NO2=1}BUF_NO; 
extern BUF_NO Free_Buf_Now; 
extern bool Buf_Ok;   

乒乓思想在这里体现:  
void DMA1_Channel5_IRQHandler(void) 
{  
        if(DMA_GetITStatus(DMA1_IT_TC5))   
        {      
                //DataCounter = DMA_GetCurrDataCounter(DMA1_Channel5);  //获取剩余长度,一般都为0,调试用                         
                DMA_ClearITPendingBit(DMA1_IT_GL5); //清除全部中断标志                 
               //转换可操作BUF   
                if(Free_Buf_Now==BUF_NO1) //如果BUF1空闲,将DMA接收数据赋值给BUF1   
                {     
                      DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf1;    
                      DMA_Init(DMA1_Channel5, &DMA_InitStructure);    
                      Free_Buf_Now=BUF_NO2;   
                }else  //如果BUF2空闲,将DMA接收数据赋值给BUF2   
                {    
                        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf2;    
                        DMA_Init(DMA1_Channel5, &DMA_InitStructure);    
                        Free_Buf_Now=BUF_NO1;   
                }   
                Buf_Ok=TRUE;   
          } 
}  

 这是主函数: 
void main() 
{  
        Delay_Init(72); //系统延时函数初始化  
        LED_Init();     //初始化与LED连接的硬件接口  
        KEY_Init();     //初始化与按键连接的硬件接口  
        USART_Config( USART1,115200);  
        // USART_Config( USART2,115200); //com2与led1,led2 接口复用  
        USART_Config( USART3,115200);  //com3
        DMA_UARTToMemConfig();//串口DMA配置   
        NVIC_Config();  //      
        while (1)   
        {   
            //////////////////////////////////////////////////////////////////////////////////////        
            if(Buf_Ok==TRUE)//BUF可用  (在dma中断中置位)   
            {    
                    Buf_Ok=FALSE;      
                    x1=0;    
                    x2=0;    
                    if(Free_Buf_Now==BUF_NO1)//如果BUF1空闲    
                    {     
                          while(x1<dma_len)     
                          {      
                                USART_PutChar(USART1,USART1_DMA_Buf1[x1++]);       //用串口1将BUF1中数据发送出去     
                          }     
                    } else //如果BUF2空闲    
                    {     
                            while(x2<dma_len)     
                            {      
                                    USART_PutChar(USART1,USART1_DMA_Buf2[x2++]);       //用串口1将BUF2中数据发送出去     
                            }    
                     }    
          }

相关文章

  • 4. 关于DMA问题

    1. 问题: 1、空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断; 2、空闲...

  • DMA详解

    这篇文章是对DMA基本概念、工作原理、常见问题做一个总结。 DMA概述 DMA的英文拼写是“Direct Memo...

  • 2018-01-26课后总结

    今天主要学习了DMA,DMA包括DMA1、DMA2,每一个DMA下面包括8个stream,每个stream包括8个...

  • STM32 DMA

    STM32 DMA 1 什么是DMA? DMA(Direct memory access)意为直接内存访问,主要优...

  • DMA

    DMA:Data Memory Access,直接存储器访问Ⅰ、DMA请求 Ⅱ、DMA通道 (通道1-7) 3.仲...

  • 带你玩转基于SkyEye的TLE987 DMA控制器实现

    01.DMA 介绍 DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一...

  • 2021-03-04 USART DMA模式2个使能

    -使能相应的DMA通道:LL_DMA_EnableChannel-使能USART的DMA模式(RX和TX有单独开关...

  • 10月 17日

    今天讲的DMA DMA 全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个...

  • 2021-03-02 G0系列DMA,DMAMUX的外设Requ

    LL方式,G0系列,DMA功能配置DMA功能除了DMA控制器外,加入了DMAMUX功能.DMAMUX相当于在外设(...

  • MDA指标

    什么是DMA指标? 所谓DMA指标,也就是平行线差指标,是用来判断目前买卖能量大小以及未来价格的趋势.在DMA指标...

网友评论

      本文标题:4. 关于DMA问题

      本文链接:https://www.haomeiwen.com/subject/jgpioqtx.html