新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > stm32之DMA徹底研究(2)

        stm32之DMA徹底研究(2)

        作者: 時間:2016-11-19 來源:網絡 收藏
        AD轉換之DMA

        1、DMA的配置

        本文引用地址:http://www.104case.com/article/201611/318278.htm

        //DMA的配置
        void DMA_Configuration(void)
        {

        /* 允許 DMA1 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        /* DMA通道1*/
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)( &(ADC1->DR)); //ADC1數據寄存器
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCCov; //獲取ADC的數組
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //片內外設作源頭
        DMA_InitStructure.DMA_BufferSize = 16; //每次DMA16個數據
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址不增加
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址增加
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //半字
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //普通模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High; //高優先級
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非內存到內存
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);

        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //DMA通道1傳輸完成中斷

        /* Enable DMA1 channel1 */
        DMA_Cmd(DMA1_Channel1, ENABLE);
        }

        要配置的內容有:

        (1)DMA1的AHB時鐘使能

        (2)DMA的源端和目的端的配置以及傳輸方向的配置

        (3)每次DMA的數據長度、地址是否增加、模式、優先級等等

        (4)使能DMA中斷

        (5)使能DMA1的通道1(通道選擇)

        本例程中DMA中斷的操作如下:

        /*******************************************************************************
        * Function Name : DMAChannel1_IRQHandler
        * Description : This function handles DMA Stream 1 interrupt request.
        * Input : None
        * Output : None
        * Return : None
        *******************************************************************************/
        extern volatile bool ADC_Ok;
        void DMA1_Channel1_IRQHandler(void)
        {
        if(DMA_GetITStatus(DMA1_IT_TC1))
        {
        DMA_ClearITPendingBit(DMA1_IT_GL1); //清除全部中斷標志
        ADC_Ok=TRUE;
        }
        }

        在DMA1的1通道的中斷程序中,清楚中斷標志,并且將AD標志位置位。

        重新允許DMA

        void DMAReConfig(void)
        {
        DMA_DeInit(DMA1_Channel1);
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
        DMA_Cmd(DMA1_Channel1, ENABLE);
        }

        下面是主程序中,對AD和DMA的使用操作:

        int main(void)
        {
        u16 adc;
        u8 a,b,c,d;

        ChipHalInit(); //片內硬件初始化
        ChipOutHalInit(); //片外硬件初始化

        for(;;)
        {
        if(ADC_Ok==TRUE)
        {
        ADC_Ok=FALSE;
        adc=DigitFilter(ADCCov,16); //濾波

        DMAReConfig();//重新啟動DMA

        adc=(1.42 - adc*3.3/4096)*1000/4.35 + 25;

        //轉換為溫度值,實際應用中,可考慮用毫伏為單位,避免浮點運算

        a = adc/1000;
        b = (adc - a*1000)/100;
        c = (adc - a*1000 - b*100)/10;
        d = adc - a*1000 - b*100 - c*10;

        USART1_Puts("當前溫度是:");
        USART1_Putc(a+0);
        USART1_Putc(b+0);
        USART1_Putc(c+0);
        USART1_Putc(d+0);
        USART1_Puts("C rn");
        }
        }
        }

        這段程序所完成的操作有:

        (1)當一次DMA傳輸完成后,主程序根據標志量,計算轉換出來的ad值。

        (2)重新啟動DMA

        (3)將ad值計算成溫度,然后將溫度值通過串口發送出去。

        (4)等待下一個DMA傳輸完成的到來,進行下一個周期的轉換和計算。

        還有一點比較重要的就是NVIC的配置,任何stm32的中斷程序都需要配置NVIC,有的時候有一忽視掉。

        //設置所有的中斷允許

        void NVIC_Configuration(void)
        {
        NVIC_InitTypeDef NVIC_InitStructure;

        /* Configure one bit for preemption priority */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        /* Enable DMA channel1 IRQ Channel */
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        }

        另外,在配置DMA中斷的時候,也可以配置成傳輸一半產生中斷的方式。

        我們可以做如下實驗:

        將DMA中斷設置成傳輸一半產生中斷,如下:

        DMA_ITConfig(DMA1_Channel4, DMA_IT_HT, ENABLE);

        當數據傳送到一半的時候發現進入到中斷:

        void DMA1_Channel4_IRQHandler(void)
        {
        if(DMA_GetITStatus(DMA1_IT_HT4))
        {
        DMA_ClearITPendingBit(DMA1_IT_HT4);

        }
        }

        在此中斷中設置斷點,當產生中斷后,發現DMA傳送并沒有結束。

        只是cpu“停止”了。

        DMA仍然將剩下的一半數據傳送完。



        關鍵詞: STM32DM

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 福清市| 宜城市| 周口市| 靖州| 治县。| 阿拉善右旗| 道孚县| 灵丘县| 广德县| 商河县| 常山县| 福建省| 牡丹江市| 湖口县| 永吉县| 阿拉尔市| 合阳县| 剑河县| 丰城市| 徐州市| 镇雄县| 长岛县| 镇安县| 渑池县| 新平| 镇平县| 明星| 海安县| 甘德县| 呼伦贝尔市| 奎屯市| 赣榆县| 民县| 荥经县| 二手房| 涿鹿县| 婺源县| 莱阳市| 漠河县| 白山市| 大安市|