stm32上DMA的学习笔记

来源:互联网 发布:新理念网络测试答案 编辑:程序博客网 时间:2024/05/29 16:41

第一个问题:DMA是什么?

        DMA,Directmemory access,顾名思义,不通过CPU,直接访问内存,实现内存和外围模块之间数据的高速传输,且它是一个独立的模块,类似于ADC、PWM的存在。主要功能就是将所有外设映射的寄存器“连接”起来。

         第二个问题,这样做有什么好处呢?

         既然不涉及CPU的参与,那么CPU就可以有更多时间来处理其他问题,大大提高了CPU的运行效率。

        

在一般的STM32上,有两个DMA(DMA1和DMA2),分别有7个和5个通道。每个通道专门用来管理一个或多个外设对储存器的访问请求,即开辟了一条RAM和I/O设备的“直通车”

DMA的操作也是很简单的,你需要做的,就是提供一个载有传送数据的buff地址、I/O的地址以及传送数据的大小,即可完成简单的DMA实验,在这一切配置好以后,CPU就可以完全不用管I/O设备和RAM之间的“勾当”了。

DMA一共有 6个寄存器:

1、  DMA_ISR,从名字就可以看出来,这个寄存器,是掌管中断开关的寄存器,例如当传送完成以后,我们需要查询TCIFx这个位来关闭DMA,要注意的是,这个寄存器是只读的。

 

2、  DMA_IFCR,这个寄存器,是用来给楼上扫战场的,因为楼上具有只读这一特性,所以,我们需要一个“清道夫”来清除DMA_ISR的对应位。也就是话说,在DMA_ISR被置位后,我们必须通过想该寄存器对应的位写入来清除。

 

3、  DMA_CCRx,这个寄存器掌管通道的配置,你到底要用几通道?买通我再说!

 

4、  DMA_CNDTRx,这个寄存器掌管第X通道每次传输的数据量,范围为0~65535,值得一提的是,这个值会随着传输的进行而减少,这样我们就可以计算出数据剩余量了。

 

5、  DMA_CPARx,这个寄存器掌管外设(I/O设备)的地址。(我要给你东西,总要知道你在哪里不是?)

 

6、  DMA_CMARx,这里存放了储存器的地址。(淘宝卖家给你寄东西,也要填上它自己的名字不是?)

 

OK!有了这些寄存器,我想你应该知道如何使用DMA了。下面,有一些细节,你可能要注意一下。



这张图上写明了不同外设所对应的通道,就是说,不是任意外设都是使用任意DMA的,毕竟,我们国家也是要讲一夫一妻制度的不是?



         看!这个就是DMA的配置函数,没骗你吧,你所需要提供的,就只有通道号,I/O地址和BUFFER地址以及数据量大小提供出来就行了,这个就不用多说了吧。

         有了上面的工作,现在,你需要的,只需要调用DMACmd函数来使能DMA,紧跟着来一记MYDMA_Enable(),OK,大功告成,以后你每次调用MYDMA_Enable(),DMA就完成一次传送,就是这么简单。

         最后,附上一个可以运行的STM32代码,实现的功能为,按下key1以后,LCD显示。

int main(void)

{

 

         u16 i;

         u8 t=0;

         u8 j,mask=0;

         uint16_t pro=0;//½ø¶È

         float a;

         uint8_t LogoStr[] = "PressKEY1:";

         uint8_t Logoma[] ="Transimit...";

 

        

    SZ_STM32_LEDInit(LED1);

    SZ_STM32_LEDInit(LED2);

    SZ_STM32_LEDInit(LED3);

    SZ_STM32_LEDInit(LED4);

 

    SZ_STM32_SysTickInit(1000);

         SZ_STM32_KEYInit(KEY1,BUTTON_MODE_GPIO);

         NVIC_Configuration();                                                                                            

SZ_STM32_COMInit(COM2, 2400);

    SZ_STM32_LCDInit();      

         MYDMA_Config(DMA1_Channel7,(u32)&USART2->DR,(u32)SendBuff,5168);

                 

         j=sizeof(TEXT_TO_SEND);          

         for(i=0;i<5168;i++)

    {

                   if(t>=j)//¼ÓÈë»»Ðзû

                   {

                            if(mask)

                            {

                                     SendBuff[i]=0x0a;

                                     t=0;

                            }else

                            {

                                     SendBuff[i]=0x0d;

                                     mask++;

                            }       

                   }

                   else

                   {

                            mask=0;

                            SendBuff[i]=TEXT_TO_SEND[t];

                            t++;

                   }      

    }                

 

         while(1)

         {

                    if(SZ_STM32_KEYGetState(KEY1) == 0)

        {   

                            USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);

                            MYDMA_Enable(DMA1_Channel7);//¿ªÊ¼Ò»´ÎDMA´«Ê䣡   

                     

                       while(1)

                       {

                                     if(DMA_GetFlagStatus(DMA1_FLAG_TC7)!=RESET)       //ÅжÏͨµÀ7´«ÊäÍê³É

                                     {

                                               DMA_ClearFlag(DMA1_FLAG_TC7);                                             break;

                           }

                                     pro=DMA_GetCurrDataCounter(DMA1_Channel7);                                  LCD_DisplayStringLine(LCD_LINE_1, (uint8_t *)LogoStr);

                                     LCD_DisplayStringLine(LCD_LINE_2,(uint8_t *)Logoma);

 

                                     a= 1-(float)pro/5168;

                                     a*=100;    

                                     pro=a;

                                     LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 1, (0x30 + (pro/10)%10));

                                     LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 2, (0x30 + (pro%10)));

                                     LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 3, '%');

                            }

                            LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 0, (0x30 + 1));

                            LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 1, (0x30 + 0));

                            LCD_DisplayChar(LINE(3),LCD_Currentfonts->Width * 2, (0x30 + 0));

 

                     }                      

         }

}

0 0
原创粉丝点击