在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            STM32之DMA

            作者: 時間:2016-11-13 來源:網(wǎng)絡(luò) 收藏
            DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA傳輸方式無需CPU 直接控制傳輸,也沒有中斷處理方式那樣保留現(xiàn)場和恢復現(xiàn)場的過程,通過硬件為RAM 與I/O設(shè)備開辟一條直接傳送數(shù)據(jù)的通路,能使CPU 的效率大為提高。
            STM32中 DMA1有7個通道,DMA2有5個通道(DMA2 僅存在大容量產(chǎn)品中)。DMA掛載的時鐘為AHB總線,其時鐘為72Mhz,所以可以實現(xiàn)高速數(shù)據(jù)搬運。
            STM32F103RBT6 只有1 個DMA控制器,DMA1 ,下面我們就針對DMA1 進行介紹。
            從外設(shè)(TIMx、ADC、SPIx 、I2Cx 和USARTx )產(chǎn)生的DMA請求,通過邏輯或輸入到DMA控制器,這就意味著同時只能有一個請求有效。外設(shè)的DMA請求,可以通過設(shè)置相應的外設(shè)寄存器中的控制位,被獨立地開啟或關(guān)閉。
            DMA1各通道一覽:
            這里我們要使用的是串口 1 的 DMA 傳送,也就是要用到通道 4。
            DMA1通道4的配置方法如下:
            dma.c主要代碼:
            [cpp]view plaincopy
            1. u16DMA1_MEM_LEN;//保存DMA每次數(shù)據(jù)傳送的長度
            2. //DMA1的各通道配置
            3. //這里的傳輸形式是固定的,這點要根據(jù)不同的情況來修改
            4. //從存儲器->外設(shè)模式/8位數(shù)據(jù)寬度/存儲器增量模式
            5. //DMA_CHx:DMA通道CHx
            6. //cpar:外設(shè)地址
            7. //cmar:存儲器地址
            8. //cndtr:數(shù)據(jù)傳輸量
            9. voidMYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32cpar,u32cmar,u16cndtr)
            10. {
            11. RCC->AHBENR|=1<<0;//開啟DMA1時鐘
            12. delay_ms(1);//等待DMA時鐘穩(wěn)定
            13. DMA_CHx->CPAR=cpar;//DMA1外設(shè)地址
            14. DMA_CHx->CMAR=(u32)cmar;//DMA1,存儲器地址
            15. DMA1_MEM_LEN=cndtr;//保存DMA傳輸數(shù)據(jù)量
            16. DMA_CHx->CNDTR=cndtr;//DMA1,傳輸數(shù)據(jù)量
            17. DMA_CHx->CCR=0X00000000;//復位
            18. DMA_CHx->CCR|=1<<4;//從存儲器讀
            19. DMA_CHx->CCR|=0<<5;//普通模式
            20. DMA_CHx->CCR|=0<<6;//外設(shè)地址非增量模式
            21. DMA_CHx->CCR|=1<<7;//存儲器增量模式
            22. DMA_CHx->CCR|=0<<8;//外設(shè)數(shù)據(jù)寬度為8位
            23. DMA_CHx->CCR|=0<<10;//存儲器數(shù)據(jù)寬度8位
            24. DMA_CHx->CCR|=1<<12;//中等優(yōu)先級
            25. DMA_CHx->CCR|=0<<14;//非存儲器到存儲器模式
            26. }
            27. //開啟一次DMA傳輸
            28. voidMYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
            29. {
            30. DMA_CHx->CCR&=~(1<<0);//關(guān)閉DMA傳輸
            31. DMA_CHx->CNDTR=DMA1_MEM_LEN;//DMA1,傳輸數(shù)據(jù)量
            32. DMA_CHx->CCR|=1<<0;//開啟DMA傳輸
            33. }
            }
            在主函數(shù)里主要有這幾個語句完成DMA傳輸:
            1.首先配置DMA1通道4相關(guān)參數(shù)
            MYDMA_Config(DMA1_Channel4,(u32)&USART1->DR,(u32)SendBuff,5200);//DMA1通道4,外設(shè)為串口1,存儲器為SendBuff,長度5200.
            2.然后將待發(fā)送內(nèi)容裝入存儲器
            SendBuff[i]=TEXT_TO_SEND[t];
            3.然后開啟一次DMA傳輸
            MYDMA_Enable(DMA1_Channel4);//開始一次DMA傳輸!
            4.監(jiān)控傳送進度。
            pro=DMA1_Channel4->CNDTR;//得到當前還剩余多少個數(shù)據(jù)

            DMA可以傳遞多少數(shù)據(jù)?

            本文引用地址:http://www.biyoush.com/article/201611/316160.htm

            傳統(tǒng)的DMA的概念是用于大批量數(shù)據(jù)的傳輸,但是我理解,在STM32中,它的概念被擴展了,也許更多的時候快速是其應用的重點。數(shù)據(jù)可以從1~65535個。

            直接存儲器存取(Direct Memory Access,DMA)是計算機科學中的一種內(nèi)存訪問技術(shù)。它允許某些電腦內(nèi)部的硬體子系統(tǒng)(電腦外設(shè)),可以獨立地直接讀寫系統(tǒng)存儲器,而不需繞道 CPU。在同等程度的CPU負擔下,DMA是一種快速的數(shù)據(jù)傳送方式。它允許不同速度的硬件裝置來溝通,而不需要依于 CPU的大量中斷請求?!菊訵ikipedia】

            現(xiàn)在越來越多的單片機采用DMA技術(shù),提供外設(shè)和存儲器之間或者存儲器之間的高速數(shù)據(jù)傳輸。當 CPU 初始化這個傳輸動作,傳輸動作本身是由DMA 控制器來實行和完成。STM32就有一個DMA控制器,它有7個通道,每個通道專門用來管理一個或多個外設(shè)對存儲器訪問的請求,還有一個仲裁器來協(xié)調(diào)各個DMA請求的優(yōu)先權(quán)。

            DMA 控制器和Cortex-M3核共享系統(tǒng)數(shù)據(jù)總線執(zhí)行直接存儲器數(shù)據(jù)傳輸。當CPU和DMA同時訪問相同的目標(RAM或外設(shè))時,DMA請求可能會停止 CPU訪問系統(tǒng)總線達若干個周期,總線仲裁器執(zhí)行循環(huán)調(diào)度,以保證CPU至少可以得到一半的系統(tǒng)總線(存儲器或外設(shè))帶寬。

            在發(fā)生一個事件后,外設(shè)發(fā)送一個請求信號到DMA控制器。DMA控制器根據(jù)通道的優(yōu)先權(quán)處理請求。當DMA控制器開始訪問外設(shè)的時候,DMA控制器立即發(fā)送給外設(shè)一個應答信號。當從DMA控制器得到應答信號時,外設(shè)立即釋放它的請求。一旦外設(shè)釋放了這個請求,DMA控制器同時撤銷應答信號。如果發(fā)生更多的請求時,外設(shè)可以啟動下次處理。

            總之,每個DMA傳送由3個操作組成:

            1. 從外設(shè)數(shù)據(jù)寄存器或者從DMA_CMARx寄存器指定地址的存儲器單元執(zhí)行加載操作。

            2. 存數(shù)據(jù)到外設(shè)數(shù)據(jù)寄存器或者存數(shù)據(jù)到DMA_CMARx寄存器指定地址的存儲器單元。

            3. 執(zhí)行一次DMA_CNDTRx寄存器的遞減操作。該寄存器包含未完成的操作數(shù)目。

            仲裁器根據(jù)通道請求的優(yōu)先級來啟動外設(shè)/存儲器的訪問。優(yōu)先級分為兩個等級:軟件(4個等級:最高、高、中等、低)、硬件(有較低編號的通道比擁有較高編號的通道有較高的優(yōu)先權(quán))。

            可以在DMA傳輸過半、傳輸完成和傳輸錯誤時產(chǎn)生中斷。

            STM32中DMA的不同中斷(傳輸完成、半傳輸、傳輸完成)通過“線或”方式連接至NVIC,需要在中斷例程中進行判斷。

            進行DMA配置前,不要忘了在RCC設(shè)置中使能DMA時鐘。STM32的DMA控制器掛在AHB總線上。

            DMA總共有7個通道,各個通道的DMA映射關(guān)系如下:

            外設(shè)的事件連接至相應DMA通道,每個通道均可以通過軟件觸發(fā)實現(xiàn)存儲器內(nèi)部的DMA數(shù)據(jù)傳輸(M2M模式)

            Tips:庫2.0中函數(shù)RCC_AHBPeriphClockCmd的參數(shù)由“RCC_AHBPeriph_DMA”改成“RCC_AHBPeriph_DMA1”(如果是DMA1控制器的話)。

            DMA的傳輸標志位(CHTIFx、CTCIFx、CGIFx)由硬件設(shè)置為“1”,但需要軟件清零,在中斷服務程序中清除。當CGIFx(全局中斷標志位)清零后,CHTIFx 和 CTCIFx均清零。

            過程:怎樣啟用DMA?首先,眾所周知的是初始化,任何設(shè)備啟用前都要對其進行初始化,要對模塊初始化,還要先了解該模塊相應的結(jié)構(gòu)及其函數(shù),以便正確的設(shè)置;由于DMA較為復雜,我就只談談DMA的基本結(jié)構(gòu)和和常用函數(shù),這些都是ST公司提供在庫函數(shù)中的。

            1、 下面代碼是一個標準DMA設(shè)置,當然實際應用中可根據(jù)實際情況進行裁減:

            DMA_DeInit(DMA_Channel1);

            上面這句是給DMA配置通道,根據(jù)ST提供的資料,STM3210Fx中DMA包含7個通道(CH1~CH7),也就是說可以為外設(shè)或memory提供7座“橋梁”(請允許我使用橋梁一詞,我覺得更容易理解,哈哈,別“拍磚”呀?。?;

            DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

            上面語句中的DMA_InitStructure是一個DMA結(jié)構(gòu)體,在庫中有聲明了,當然使用時就要先定義 了;DMA_PeripheralBaseAddr是該結(jié)構(gòu)體中一個數(shù)據(jù)成員,給DMA一個起始地址,好比是一個buffer起始地址,數(shù)據(jù)流程是:外設(shè) 寄存器à DMA_PeripheralBaseAddàmemory中變量空間(或flash中數(shù)據(jù)空間等),ADC1_DR_Address是我定義的一個地址 變量;

            DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

            上面這句很顯然是DMA要連接在Memory中變量的地址,ADC_ConvertedValue是我自己在memory中定義的一個變量;

            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

            上面的這句是設(shè)置DMA的傳輸方向,就如前面我所說的,DMA可以雙向傳輸,也可以單向傳輸,這里設(shè)置的是單向傳輸,如果需要雙向傳輸:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。

            DMA_InitStructure.DMA_BufferSize = 2;

            上面的這句是設(shè)置DMA在傳輸時緩沖區(qū)的長度,前面有定義過了buffer的起始地址:ADC1_DR_Address ,為了安全性和可靠性,一般需要給buffer定義一個儲存片區(qū),這個參數(shù)的單位有三種類型:Byte、HalfWord、word,我設(shè)置的2個 half-word(見下面的設(shè)置);32位的MCU中1個half-word占16 bits。

            DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

            上面的這句是設(shè)置DMA的外設(shè)遞增模式,如果DMA選用的通道(CHx)有多個外設(shè)連接,需要使用外設(shè)遞增模式:DMA_PeripheralInc_Enable;我的例子里DMA只與ADC1建立了聯(lián)系,所以選用DMA_PeripheralInc_Disable

            DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

            上面的這句是設(shè)置DMA的內(nèi)存遞增模式,DMA訪問多個內(nèi)存參數(shù)時,需要使用DMA_MemoryInc_Enable,當DMA只訪問一個內(nèi)存參數(shù)時,可設(shè)置成:DMA_MemoryInc_Disable。

            DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

            上面的這句是設(shè)置DMA在訪問時每次操作的數(shù)據(jù)長度。有三種數(shù)據(jù)長度類型,前面已經(jīng)講過了,這里不在敘述。

            DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

            與上面雷同。在此不再說明。

            DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

            上面的這句是設(shè)置DMA的傳輸模式:連續(xù)不斷的循環(huán)模式,若只想訪問一次后就不要訪問了(或按指令操作來反問,也就是想要它訪問的時候就訪問,不要它訪問的時候就停止),可以設(shè)置成通用模式:DMA_Mode_Normal

            DMA_InitStructure.DMA_Priority = DMA_Priority_High;

            上面的這句是設(shè)置DMA的優(yōu)先級別:可以分為4級:VeryHigh,High,Medium,Low.

            DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

            上面的這句是設(shè)置DMA的2個memory中的變量互相訪問的

            DMA_Init(DMA_Channel1,&DMA_InitStructure);

            前面那些都是對DMA結(jié)構(gòu)體成員的設(shè)置,在次再統(tǒng)一對DMA整個模塊做一次初始化,使得DMA各成員與上面的參數(shù)一致。

            DMA_Cmd(DMA_Channel1,ENABLE);

            哈哈哈!這一句我想我就不羅嗦了,大家一看就明白。

            至此,整個DMA總算設(shè)置好了,但是,DMA通道又是怎樣與外設(shè)聯(lián)系在一起的呢?哈哈,這也是我當初最想知道的一個事情,別急!容我想喝口茶~~~~~~哈哈哈!

            要使DMA與外設(shè)建立有效連接,這不是DMA自身的事情,是各個外設(shè)的事情,每個外設(shè)都有 一個xxx_DMACmd(XXXx,Enable )函數(shù),如果使DMA與ADC建立有效聯(lián)系,就使用ADC_DMACmd(ADC1,Enable); (這里我啟用了ADC中的ADC1模塊)。

            一個簡單的例子 transfera word data buffer from FLASH memory to embedded SRAM memory.
            在V3.1.2庫的位置
            STM32F10x_StdPeriph_Lib_V3.1.2ProjectSTM32F10x_StdPeriph_ExamplesDMAFLASH_RAM


            DMA_DeInit(DMA1_Channel6);
            //peripheral base address
            DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;
            //memory base address
            DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_Buffer;
            //數(shù)據(jù)傳輸方向Peripheral is source
            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
            //緩沖區(qū)大小 Number of data to be transferred (0 up to 65535).數(shù)據(jù)傳輸數(shù)目
            DMA_InitStructure.DMA_BufferSize = BufferSize;
            // the Peripheral address register is incremented
            DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
            //the memory address register is incremented
            DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
            //the Peripheral data width
            DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
            DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
            DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
            DMA_InitStructure.DMA_Priority = DMA_Priority_High;
            //the DMAy Channelx will be used in memory-to-memory transfer
            //DMA通道的操作可以在沒有外設(shè)請求的情況下進行,這種操作就是存儲器到存儲器模式。
            DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
            DMA_Init(DMA1_Channel6, &DMA_InitStructure);


            DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);



            DMA_Cmd(DMA1_Channel6, ENABLE);
            =======================================================================

            外設(shè)的DMA請求映像


            要使DMA與外設(shè)建立有效連接,這不是DMA自身的事情,是各個外設(shè)的事情,每個外設(shè)都有 一個

            xxx_DMACmd(XXXx,Enable )函數(shù),如果使DMA與ADC建立有效聯(lián)系,就使用 ADC_DMACmd

            (ADC1,Enable); (這里我啟用了ADC中的ADC1模塊)。


            DMA_DeInit(DMA1_Channel1);
            DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
            DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value;
            //u16AD_Value[2];不加&應該也可以數(shù)組名 代表地址
            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
            DMA_InitStructure.DMA_BufferSize = 2;//############## 改了
            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_Circular;
            DMA_InitStructure.DMA_Priority = DMA_Priority_High;
            DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
            DMA_Init(DMA1_Channel1, &DMA_InitStructure);


            DMA_Cmd(DMA1_Channel1, ENABLE);


            ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
            ADC_InitStructure.ADC_ScanConvMode = ENABLE;
            ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
            ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
            ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
            ADC_InitStructure.ADC_NbrOfChannel = 2;//##############改了
            ADC_Init(ADC1, &ADC_InitStructure);
            //內(nèi)部溫度傳感器添加這一句

            ADC_TempSensorVrefintCmd(ENABLE);
            //##############改了

            //################ Channel 10(電位器)
            ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);
            //###### 內(nèi)部溫度傳感器Channel 16 ###################
            ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_55Cycles5);

            使能ADC1的DMA請求映像
            ADC_DMACmd(ADC1, ENABLE);


            ADC_Cmd(ADC1, ENABLE);

            //使用之前一定要校準
            ADC_ResetCalibration(ADC1);

            while(ADC_GetResetCalibrationStatus(ADC1));


            ADC_StartCalibration(ADC1);

            while(ADC_GetCalibrationStatus(ADC1));

            ADC_SoftwareStartConvCmd(ADC1, ENABLE);



            關(guān)鍵詞: STM32DM

            評論


            技術(shù)專區(qū)

            關(guān)閉