分享

stm32f407之DMA(操作寄存器)

 戴维图书馆 2014-04-08

八、DMA

       直接内存访问(DMA)是用来以提供外设和内存、内存和内存之间的高速数据传输的。数据可以在没有任何CPU干预下通过的DMA进行传输。这使得CPU资源更倾重与其他操作。

       DMA控制器基于一个复杂的总线矩阵架构,结合了功能强大的双AHB主总线架构与独立的FIFO,以优化系统带宽。

        两个DMA控制器共有16个数据流(stream),每个数据流可以编程与规定的通道中的一个搭配。

 


DMA的工作模式

1.  单次传输

2. 多次传输(burst):把数据分成多次传输

 

 

DMA的工作模式

 

1. 循环模式:循环模式是可用来处理循环缓冲区和连续的数据流(如ADC扫描模式)。启此功能可以设置DMA_SxCR寄存器的CIRC位启用。

 

在循环模式,在burst方式下,它必须遵循下面的规则

DMA_SxNDTR 等于 ((Mburst beat) × (Msize)/(Psize))的整数倍。

 

2.     双缓冲模式:双缓冲模式通过设置在DMA_SxCR寄存器的DBM位启用。

双缓冲模式与单缓冲模式的区别在于它有两个地址,当栓缓冲模式被使能,循环模式会被自动使能,每次传输完成,内存地址将会被交换。当一个内存区域被DMA控制器使用时,另一个可供程序使用。

 

如果需要改变内存地址,需要遵循以下规则:

DMA_SxCR 寄存器的CT 位为 0时,DMA_SxM1AR寄存器可以被改变

DMA_SxCR 寄存器的CT 位为 1时,DMA_SxM0AR寄存器可以被改变

 

 


    设置步骤:

1.     使能相关时钟。

2.     如果数据流已启用,通过重置在DMA_SxCR寄存器的EN位禁用它,然后读取该位,以确认有没有持续的数据流操作。向该位写0不会立即生效,因为它实际上是在全部转移完成时才被清除的。当EN位读为0,这意味着数据流是准备好,可以进行配置了。因此,任何数据流配置之前,有必要等待EN位被清除。在数据流重新启动前,前一次DMA传输中的状态寄存器(DMA_LISR and DMA_HISR)所有数据流专用的位应该被清除。

3.      在DMA_SxPAR寄存器中设置外设端口寄存器的地址。

4.     在DMA_SxMA0R寄存器中设置内存的地址(在双缓冲模式的情况下,还需在DMA_SxMA1R寄存器中设置内存的地址)。

5.     在DMA_SxNDTR寄存器中设置传输的数据总数,每个外设的事件或每次burst传输之后,这个值是将会递减。

6.      在DMA_SxCR寄存器使用CHSEL[2:0] 选择DMA通道。

7.      如果外设为流量控制器,它支持此功能,设置DMA_SxCR寄存器中PFCTRL的位。

8.      在DMA_SxCR寄存器的PL[1:0]位配置数据流优先级。

9.     配置FIFO(启用或禁用,发送和接收的阀值)。

10.  在DMA_SxCR寄存器中配置数据传输的方向,外设和内存递增/固定的模式,单个或burst传输,外设和存储器的数据宽度,循环模式,双缓冲模式和完成几分之几后中断。

11.   激活设置数据流在DMA_SxCR寄存器的EN位。

12.  使能相关外设寄存器的DMA模式位,启动传输。

 

 

程序:

  1. /*********************************************  
  2.     标题:操作DMA的练习  
  3.     软件平台:IAR for ARM6.21  
  4.     硬件平台:stm32f4-discovery  
  5.     主频:168M  
  6.       
  7.     描述:从其他设备接收数据,再把数据发送出去  
  8.           USART3接收中断,发射用DMA  
  9.     author:小船  
  10.     data:2012-02-03  
  11. **********************************************/  
  12.   
  13. #include <stm32f4xx.h>   
  14.   
  15. u8 USART_DMA_Completed;  
  16. u8 Rx_Completed;  
  17. u8 Rx_data_counter;  
  18. u8 usart3_buffer[100];  
  19.   
  20. void USART3_DMA_config(void);  
  21. void USART3_config(void);  
  22.   
  23. void main ()  
  24. {   
  25.     
  26.   SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  
  27.     
  28.   RCC->AHB1ENR |= ( (1<<3) | (1<<21) ); //使能GPIOD时钟,使能DMA1时钟  
  29.   RCC->APB1ENR |= (1<<18);  //使能usart3时钟  
  30.     
  31.   USART3_DMA_config();  
  32.   USART3_config();  
  33.     
  34.   USART_DMA_Completed = 1;  
  35.     
  36.   while(1)  
  37.   {    
  38.     if(USART_DMA_Completed & Rx_Completed)  //之前数据已经发送完成,接收到新的数据  
  39.     {    
  40.       DMA1_Stream3->CR &= 0xFFFFFFFE; //除能DMA1_Stream3  
  41.       while(DMA1_Stream3->CR & 0x00000001);//确保DMA可以被设置       
  42.       DMA1->LIFCR |= 0x0f800000;//传送前清空DMA1_Stream3所有中断标志        
  43.       DMA1_Stream3->NDTR = Rx_data_counter; //设置dma传输数据的数量  
  44.       if((USART3->SR & (1<<7))) //发送数据寄存器空  
  45.       {  
  46.         USART3->CR3 &= ~(1<<7);//除能usartdma发送  
  47.         USART_DMA_Completed = 0;  
  48.         DMA1_Stream3->NDTR = Rx_data_counter; //设置dma传输数据的数量  
  49.         DMA1_Stream3->CR |= 1;//使能dma  
  50.         USART3->CR3 |= (1<<7);//使能usartdma发送  
  51.         Rx_Completed = 0;  
  52.         Rx_data_counter = 0;  
  53.       }  
  54.     }  
  55.   }  
  56. }  
  57.   
  58. /****************************************  
  59.   函数名:USART3_DMA_config  
  60.   参数:无  
  61.   返回值:无  
  62.   功能:DMA1数据流3与usart3关联的相关配置  
  63. ****************************************/  
  64. void USART3_DMA_config(void)  
  65. {  
  66.   DMA1_Stream3->CR &= 0xFFFFFFFE; //除能DMA1_Stream3  
  67.   while(DMA1_Stream3->CR & 0x00000001);//确保DMA可以被设置  
  68.     
  69.   DMA1->LIFCR |= 0x0f800000;//传送前清空DMA1_Stream3所有中断标志  
  70.     
  71.   DMA1_Stream3->PAR = (uint32_t)&USART3->DR;//设置外设地址USART3->DR地址0x40004804  
  72.   DMA1_Stream3->M0AR = (uint32_t)usart3_buffer; //设置内存地址  
  73.   DMA1_Stream3->NDTR = Rx_data_counter; //设置dma传输数据的数量  
  74.   //DMA1_Stream3->FCR |= 0x00000007;//设置fifo  
  75.   /*  
  76.     设置dma通道4,即usart3tx  
  77.     优先级Medium  
  78.     传输方向内存到外设  
  79.     内存递增模式  
  80.     传输完成中断使能  
  81.   */  
  82.   DMA1_Stream3->CR |= ( 0x08000000 |0x00010000 | (1<<6)  
  83.                         | (1<<10) | (1<<4) );   
  84.   
  85.   USART3->CR3 &= ~(1<<7);//usart3 dma发送模式除能  
  86.     
  87.   NVIC->IP[14] = 0xA0;  
  88.   NVIC->ISER[0] |= (1<<14);  
  89.     
  90. }  
  91.   
  92. /**************************  
  93.   函数名:USART3_config  
  94.   参数:无  
  95.   返回值:无  
  96.   功能:配置usart3  
  97. ************************/  
  98. void USART3_config(void)  
  99. {  
  100.   USART3->BRR = 0x0000016C;   //波特率115200  
  101.   /*  
  102.    使能usart3  
  103.   usart3发送使能  
  104.   usart3接收使能  
  105.   接收缓冲区非空中断使能  
  106.   8bit  
  107.   一位停止位  
  108.   无校验  
  109.   */  
  110.   USART3->CR1 |= (( 1<<13 ) | ( 1<<3 ) | ( 1<<2 ) | ( 1<<5 ));   
  111.     
  112.   GPIOD->AFR[1] |= 0x00000077;//选择PD8,9复用功能   
  113.     
  114.   GPIOD->MODER &= 0xFFF0FFFF; //设置PD8,9,复用模式  
  115.   GPIOD->MODER |= 0x000A0000;   
  116.     
  117. //  GPIOD->OTYPER &= 0xFFFFDFFF; //设置PD9推挽输出  
  118.     
  119.   GPIOD->OSPEEDR &= 0xFFFCFFFF; //PD8速度50m  
  120.   GPIOD->OSPEEDR |= 0x00020000;  
  121.     
  122.   GPIOD->PUPDR &= 0xFFFCFFFF; //PD8  
  123.   GPIOD->PUPDR |= 0x00010000;  
  124.     
  125.   NVIC->IP[39] = 0xf0; //最低抢占优先级,最低响应优先级1111  
  126.   NVIC->ISER[1] |= (1<<(39-32)); //使能中断线39,也就是usart3中断  
  127. }  
  128.   
  129.   
  130. void USART3_IRQHandler(void)  
  131. {  
  132.   if(USART3->SR & (1<<5)) //接收数据寄存器非空  
  133.   {  
  134.     usart3_buffer[Rx_data_counter] = USART3->DR;  
  135.     Rx_data_counter++;  
  136.     if(usart3_buffer[Rx_data_counter - 1] == '\r')  
  137.     {  
  138.       USART3->CR1 &= ~(1<<5); //除能接收中断  
  139.       Rx_Completed = 1;  
  140.     }  
  141.    }   
  142. }  
  143.   
  144. void DMA1_Stream3_IRQHandler(void)  
  145. {  
  146.   if(DMA1->LISR & 0x08000000)//DMA传输完成  
  147.   {  
  148.     USART_DMA_Completed = 1;  
  149.     USART3->CR1 |= 1<<5;  //使能usart3接收中断  
  150.     DMA1->LIFCR |= 0x08000000;//清除中断标志  
  151.   }  
  152. }  

运行结果:






更多 0

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多