<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 搞嵌入式,不懂DMA?笑死人

搞嵌入式,不懂DMA?笑死人

作者: 時(shí)間:2024-04-08 來(lái)源:嵌入式Linux 收藏

,全稱(chēng)Direct Memory Access,即直接訪(fǎng)問(wèn)。

本文引用地址:http://dyxdggzs.com/article/202404/457231.htm

傳輸將數據從一個(gè)地址空間復制到另一個(gè)地址空間,提供在外設和之間或者和存儲器之間的高速數據傳輸。

我們知道有轉移數據、計算、控制程序轉移等很多功能,系統運作的核心就是.

無(wú)時(shí)不刻的在處理著(zhù)大量的事務(wù),但有些事情卻沒(méi)有那么重要,比方說(shuō)數據的復制和存儲數據,如果我們把這部分的CPU資源拿出來(lái),讓CPU去處理其他的復雜計算事務(wù),是不是能夠更好的利用CPU的資源呢?

因此:轉移數據(尤其是轉移大量數據)是可以不需要CPU參與。比如希望外設A的數據拷貝到外設B,只要給兩種外設提供一條數據通路,直接讓數據由A拷貝到B 不經(jīng)過(guò)CPU的處理,


 就是基于以上設想設計的,它的作用就是解決大量數據轉移過(guò)度消耗CPU資源的問(wèn)題。有了DMA使CPU更專(zhuān)注于更加實(shí)用的操作–計算、控制等。

DMA定義:

DMA用來(lái)提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無(wú)須CPU的干預,通過(guò)DMA數據可以快速地移動(dòng)。這就節省了CPU的資源來(lái)做其他操作。

DMA傳輸方式

DMA的作用就是實(shí)現數據的直接傳輸,而去掉了傳統數據傳輸需要CPU寄存器參與的環(huán)節,主要涉及四種情況的數據傳輸,但本質(zhì)上是一樣的,都是從內存的某一區域傳輸到內存的另一區域(外設的數據寄存器本質(zhì)上就是內存的一個(gè)存儲單元)。四種情況的數據傳輸如下:

  • 外設到內存

  • 內存到外設

  • 內存到內存

  • 外設到外設

DMA傳輸參數

我們知道,數據傳輸,首先需要的是1 數據的源地址 2 數據傳輸位置的目標地址 ,3 傳遞數據多少的數據傳輸量 ,4 進(jìn)行多少次傳輸的傳輸模式 DMA所需要的核心參數,便是這四個(gè)

當用戶(hù)將參數設置好,主要涉及源地址、目標地址、傳輸數據量這三個(gè),DMA控制器就會(huì )啟動(dòng)數據傳輸,當剩余傳輸數據量為0時(shí) 達到傳輸終點(diǎn),結束DMA傳輸 ,當然,DMA 還有循環(huán)傳輸模式 當到達傳輸終點(diǎn)時(shí)會(huì )重新啟動(dòng)DMA傳輸?! ?也就是說(shuō)只要剩余傳輸數據量不是0,而且DMA是啟動(dòng)狀態(tài),那么就會(huì )發(fā)生數據傳輸?! ?/span>


DMA的主要特征

每個(gè)通道都直接連接專(zhuān)用的硬件DMA請求,每個(gè)通道都同樣支持軟件觸發(fā)。這些功能通過(guò)軟件來(lái)配置;

  • 在同一個(gè)DMA模塊上,多個(gè)請求間的優(yōu)先權可以通過(guò)軟件編程設置(共有四級:很高、高、中等和低),優(yōu)先權設置相等時(shí)由硬件決定(請求0優(yōu)先于請求1,依此類(lèi)推);

  • 獨立數據源和目標數據區的傳輸寬度(字節、半字、全字),模擬打包和拆包的過(guò)程。源和目標地址必須按數據傳輸寬度對齊;

  • 支持循環(huán)的緩沖器管理;

  • 每個(gè)通道都有3個(gè)事件標志(DMA半傳輸、DMA傳輸完成和DMA傳輸出錯),這3個(gè)事件標志邏輯或成為一個(gè)單獨的中斷請求;

  • 存儲器和存儲器間的傳輸、外設和存儲器、存儲器和外設之間的傳輸;

  • 閃存、SRAM、外設的SRAM、APB1、APB2和AHB外設均可作為訪(fǎng)問(wèn)的源和目標;

  • 可編程的數據傳輸數目:最大為65535。

STM32少個(gè)DMA資源?

對于大容量的STM32芯片有2個(gè)DMA控制器 兩個(gè)DMA控制器,DMA1有7個(gè)通道,DMA2有5個(gè)通道。每個(gè)通道都可以配置一些外設的地址。

①DMA1 controller

從外設(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])產(chǎn)生的7個(gè)DMA請求,通過(guò)邏輯或輸入到DMA1控制器 其中每個(gè)通道都對應著(zhù)具體的外設:



② DMA2 controller

從外設(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)產(chǎn)生的5個(gè)請求,經(jīng)邏輯或輸入到DMA2控制器,其中每個(gè)通道都對應著(zhù)具體的外設:



這些在下方系統框圖中也可以清晰地看到

DMA工作系統框圖


上方的框圖,我們可以看到STM32內核,存儲器,外設及DMA的連接,這些硬件最終通過(guò)各種各樣的線(xiàn)連接到總線(xiàn)矩陣中,硬件結構之間的數據轉移都經(jīng)過(guò)總線(xiàn)矩陣的協(xié)調,使各個(gè)外設和諧的使用總線(xiàn)來(lái)傳輸數據。我們對他來(lái)進(jìn)行一點(diǎn)一點(diǎn)的分析:

下面看有與沒(méi)有DMA的情況下,ADC采集的數據是怎樣存放到SRAM中的?

沒(méi)有DMA

1.如果沒(méi)有DMA,CPU傳輸數據還要以?xún)群俗鳛橹修D站,比如要將ADC采集的數據轉移到到SRAM中,這個(gè)過(guò)程是這樣的:

內核通過(guò)DCode經(jīng)過(guò)總線(xiàn)矩陣協(xié)調,從獲取AHB存儲的外設ADC采集的數據,

然后內核再通過(guò)DCode經(jīng)過(guò)總線(xiàn)矩陣協(xié)調把數據存放到內存SRAM中。


在這里插入圖片描述

有DMA傳輸

有DMA的話(huà),

  1. DMA傳輸時(shí)外設對DMA控制器發(fā)出請求。

  2. DMA控制器收到請求,觸發(fā)DMA工作。

  3. DMA控制器從AHB外設獲取ADC采集的數據,存儲到DMA通道中

  4. DMA控制器的DMA總線(xiàn)與總線(xiàn)矩陣協(xié)調,使用AHB把外設ADC采集的數據經(jīng)由DMA通道存放到SRAM中,這個(gè)數據的傳輸過(guò)程中,完全不需要內核的參與,也就是不需要CPU的參與,


在這里插入圖片描述

我們把上面的步驟專(zhuān)業(yè)一點(diǎn)介紹:

在發(fā)生一個(gè)事件后,外設向DMA控制器發(fā)送一個(gè)請求信號。DMA控制器根據通道的優(yōu)先權處理請求。當DMA控制器開(kāi)始訪(fǎng)問(wèn)發(fā)出請求的外設時(shí),DMA控制器立即發(fā)送給它一個(gè)應答信號。當從DMA控制器得到應答信號時(shí),外設立即釋放它的請求。一旦外設釋放了這個(gè)請求,DMA控制器同時(shí)撤銷(xiāo)應答信號。DMA傳輸結束,如果有更多的請求時(shí),外設可以啟動(dòng)下一個(gè)周期。

總之,每次DMA傳送由3個(gè)操作組成:

  • 從外設數據寄存器或者從當前外設/存儲器地址寄存器指示的存儲器地址取數據,第一次傳輸時(shí)的開(kāi)始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;

  • 存數據到外設數據寄存器或者當前外設/存儲器地址寄存器指示的存儲器地址,第一次傳輸時(shí)的開(kāi)始地址是DMA_CPARx或DMA_CMARx寄存器指定的外設基地址或存儲器單元;

  • 執行一次DMA_CNDTRx寄存器的遞減操作,該寄存器包含未完成的操作數目。

DMA傳輸方式

方法1:DMA_Mode_Normal,正常模式,

當一次DMA數據傳輸完后,停止DMA傳送 ,也就是只傳輸一次    方法2:DMA_Mode_Circular ,循環(huán)傳輸模式

當傳輸結束時(shí),硬件自動(dòng)會(huì )將傳輸數據量寄存器進(jìn)行重裝,進(jìn)行下一輪的數據傳輸。也就是多次傳輸模式

仲裁器


仲裁器的作用是確定各個(gè)DMA傳輸的優(yōu)先級

仲裁器根據通道請求的優(yōu)先級來(lái)啟動(dòng)外設/存儲器的訪(fǎng)問(wèn)。

優(yōu)先權管理分2個(gè)階段:

軟件:每個(gè)通道的優(yōu)先權可以在DMA_CCRx寄存器中設置,有4個(gè)等級

  • 最高優(yōu)先級

  • 高優(yōu)先級

  • 中等優(yōu)先級

  • 低優(yōu)先級;

硬件:如果2個(gè)請求有相同的軟件優(yōu)先級,則較低編號的通道比較高編號的通道有較高的優(yōu)先權。比如:如果軟件優(yōu)先級相同,通道2優(yōu)先于通道4。

注意:在大容量產(chǎn)品和互聯(lián)型產(chǎn)品中,DMA1控制器擁有高于DMA2控制器的優(yōu)先級。

DMA數據流(僅存在于STM32F4 /M4 內核上)

在設置了DMA的通道之后,還要選擇通道對應外設的數據流

8 個(gè) DMA 控制器數據流都能夠提供源和目標之間的單向傳輸鏈路。每個(gè)數據流配置后都可以執行:● 常規類(lèi)型事務(wù):存儲器到外設、外設到存儲器或存儲器到存儲器的傳輸?!?雙緩沖區類(lèi)型事務(wù):使用存儲器的兩個(gè)存儲器指針的雙緩沖區傳輸(當 DMA 正在進(jìn)行自/至緩沖區的讀/寫(xiě)操作時(shí),應用程序可以進(jìn)行至/自其它緩沖區的寫(xiě)/讀操作)。要傳輸的數據量(多達 65535)可以編程,并與連接到外設 AHB 端口的外設(請求 DMA 傳輸)的源寬度相關(guān)。每個(gè)事務(wù)完成后,包含要傳輸的數據項總量的寄存器都會(huì )遞減。

DMA_SxCR 寄存器控制數據流到底使用哪一個(gè)通道,每個(gè)數據流有 8 個(gè)通道可 供選擇,每次只能選擇其中一個(gè)通道進(jìn)行 DMA 傳輸。接下來(lái),我們看看 DMA2 的各數據流通 道映射表,如表 28.1.1 所示:


DMA 傳輸通道

每個(gè)通道都可以在有固定地址的外設寄存器和存儲器地址之間執行DMA傳輸。DMA傳輸的數據 量是可編程的,大達到65535。包含要傳輸的數據項數量的寄存器,在每次傳輸后遞減。

可編程的數據量:外設和存儲器的傳輸數據量可以通過(guò)DMA_CCRx寄存器中的PSIZE和MSIZE位編程。

指針遞增模式

根據 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態(tài),外設和存儲器指針在每次傳輸后可以自動(dòng)向后遞增或保持常量。當設置為增量模式時(shí),下一個(gè)要傳輸的地址將是前一個(gè)地址加上增量值

通過(guò)單個(gè)寄存器訪(fǎng)問(wèn)外設源或目標數據時(shí),禁止遞增模式十分有用。

如果使能了遞增模式,則根據在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中編程的數據寬度,下一次傳輸的地址將是前一次傳輸的地址遞增 1個(gè)數據寬度、2個(gè)數據寬度或 4個(gè)數據寬度。

存儲器到存儲器模式

DMA通道的操作可以在沒(méi)有外設請求的情況下進(jìn)行,這種操作就是存儲器到存儲器模式。

當設置了DMA_CCRx寄存器中的MEM2MEM位之后,在軟件設置了DMA_CCRx寄存器中的EN位啟動(dòng)DMA通道時(shí),DMA傳輸將馬上開(kāi)始。當DMA_CNDTRx寄存器變?yōu)?時(shí),DMA傳輸結束。存儲器到存儲器模式不能與循環(huán)模式同時(shí)使用。

這里要注意僅 DMA2 的外設接口可以訪(fǎng)問(wèn)存儲器,所以?xún)H DMA2 控制器支持存儲器到存儲器的傳輸,DMA1 不支持。

存儲器到存儲器模式不能與循環(huán)模式同時(shí)使用。

DMA中斷

每個(gè)DMA通道都可以在DMA傳輸過(guò)半、傳輸完成和傳輸錯誤時(shí)產(chǎn)生中斷。為應用的靈活性考慮,通過(guò)設置寄存器的不同位來(lái)打開(kāi)這些中斷。


使沒(méi)開(kāi)啟,我們也可以通過(guò)查詢(xún)這些位來(lái)獲得當前 DMA 傳輸的狀態(tài)。這里我們常用的是 TCIFx位,即數據流 x 的 DMA 傳輸完成與否標志。

可編程的數據傳輸寬度、對齊方式和數據大小端 當PSIZE和MSIZE不相同時(shí),DMA模塊按照下圖進(jìn)行數據對齊。

注意:在大容量產(chǎn)品中, DMA2 通道 4 和 DMA2 通道 5 的中斷被映射在同一個(gè)中斷向量上。在互聯(lián)型產(chǎn)品 中, DMA2 通道 4 和 DMA2 通道 5 的中斷分別有獨立的中斷向量。所有其他的 DMA 通道都有自己的 中斷向量

DMA的內存占用

在STM32控制器中,芯片采用Cortex-MX架構,總線(xiàn)結構有了很大的優(yōu)化,DMA占用另外的地址總線(xiàn),并不會(huì )與CPU的系統總線(xiàn)發(fā)生沖突。也就是說(shuō),DMA的使用不會(huì )影響CPU的運行速度

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

DMA配置部分

此部分我們分為DMA寄存器和DMA庫函數分別介紹:

DMA寄存器

DMA配置參數包括:通道地址、優(yōu)先級、數據傳輸方向、存儲器/外設數據寬度、存儲器/外設地址是否增量、循環(huán)模式、數據傳輸量。

DMA中斷狀態(tài)寄存器(DMA_ISR)


我們如果開(kāi)啟了 DMA_ISR 中這些中斷,在達到條件后就會(huì )跳到中斷服務(wù)函數里面去,即使 沒(méi)開(kāi)啟,我們也可以通過(guò)查詢(xún)這些位來(lái)獲得當前 DMA 傳輸的狀態(tài)。這里我們常用的是 TCIFx, 即通道 DMA 傳輸完成與否的標志。

注意此寄存器為只讀寄存器,所以在這些位被置位之后,只 能通過(guò)其他的操作來(lái)清除。

DMA中斷標志清除寄存器(DMA_IFCR)


DMA_IFCR 的各位就是用來(lái)清除 DMA_ISR 的對應位的,通過(guò)寫(xiě) 0 清除。在 DMA_ISR 被置位后, 我們必須通過(guò)向該位寄存器對應的位寫(xiě)入 0 來(lái)清除。

DMA通道x配置寄存器(DMA_CCRx)


該寄存器控制著(zhù) DMA 的很多相關(guān) 信息,包括數據寬度、外設及存儲器的寬度、通道優(yōu)先級、增量模式、傳輸方向、中斷允許、 使能等都是通過(guò)該寄存器來(lái)設置的。所以 DMA_CCRx 是 DMA 傳輸的核心控制寄存器

DMA通道x傳輸數量寄存器(DMA_CNDTRx)(x = 1…7)


這個(gè)寄存器控制 DMA 通道 x 的每次 傳輸所要傳輸的數據量。其設置范圍為 0~65535。并且該寄存器的值會(huì )隨著(zhù)傳輸的進(jìn)行而減少, 當該寄存器的值為 0 的時(shí)候就代表此次數據傳輸已經(jīng)全部發(fā)送完成了。所以可以通過(guò)這個(gè)寄存 器的值來(lái)知道當前 DMA 傳輸的進(jìn)度

DMA通道x外設地址寄存器(DMA_CPARx)(x = 1…7)


該寄存器用來(lái)存儲 STM32 外設的地 址,比如我們使用串口 1,那么該寄存器必須寫(xiě)入 0x40013804(其實(shí)就是&USART1_DR)。如果使 用其他外設,就修改成相應外設的地址就行了。

DMA通道x配置寄存器(DMA_CMARx)


,該寄存器和 DMA_CPARx 差不多, 但是是用來(lái)放存儲器的地址的。比如我們使用 SendBuf[5200]數組來(lái)做存儲器,那么我們在 DMA_CMARx 中寫(xiě)入&SendBuff 就可以了。

DMA寄存器配置流程

通道配置過(guò)程 下面是配置DMA通道x的過(guò)程(x代表通道號):

  1. 在DMA_CPARx寄存器中設置外設寄存器的地址。發(fā)生外設數據傳輸請求時(shí),這個(gè)地址將 是數據傳輸的源或目標。

  2. 在DMA_CMARx寄存器中設置數據存儲器的地址。發(fā)生外設數據傳輸請求時(shí),傳輸的數 據將從這個(gè)地址讀出或寫(xiě)入這個(gè)地址。

  3. 在DMA_CNDTRx寄存器中設置要傳輸的數據量。在每個(gè)數據傳輸后,這個(gè)數值遞減。

  4. 在DMA_CCRx寄存器的PL[1:0]位中設置通道的優(yōu)先級。

  5. 在DMA_CCRx寄存器中設置數據傳輸的方向、循環(huán)模式、外設和存儲器的增量模式、外 設和存儲器的數據寬度、傳輸一半產(chǎn)生中斷或傳輸完成產(chǎn)生中斷。

  6. 設置DMA_CCRx寄存器的ENABLE位,啟動(dòng)該通道。

一旦啟動(dòng)了DMA通道,它既可響應連到該通道上的外設的DMA請求。當傳輸一半的數據后,半傳輸標志(HTIF)被置1,當設置了允許半傳輸中斷位(HTIE)時(shí),將產(chǎn)生 一個(gè)中斷請求。在數據傳輸結束后,傳輸完成標志(TCIF)被置1,當設置了允許傳輸完成中斷位 (TCIE)時(shí),將產(chǎn)生一個(gè)中斷請求。

DMA庫函數

1.DMA初始化函數

 DMA_DeInit(DMAX_ChannelX);

功能:將DMAyChannelx寄存器的初始化為其默認值

注釋?zhuān)篟CC_ResetCmd中對DMA無(wú)定義,因此采用的直接操縱DMA寄存器的方式

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,  DMA_InitTypeDef* DMA_InitStruct)

功能:設置要開(kāi)啟的通道,還有一些參數,包括外設基地址,存儲器基地址,傳輸的數據量,增量模式,數據寬度等。

具體看下方結構體代碼介紹:

typedef struct {  
 uint32_t DMA_PeripheralBaseAddr;   
 /*設置DMA源地址*/
 uint32_t DMA_MemoryBaseAddr;       
 /*設置DMA目的地址*/
 uint32_t DMA_DIR; 
 /* 設置數據傳輸方向,決定是從外設讀取數據到內存還送從內存讀取數 據發(fā)送到外設,也就是外設是源地還是目的地
 */                       
 uint32_t DMA_BufferSize;      
 /*設置傳輸大小*/    
 uint32_t DMA_PeripheralInc;       
 /*設置ReceiveBuff地址是否自增*/      
 uint32_t DMA_MemoryInc; 
 /*設置傳輸數據時(shí)候內存地址是否遞,需要開(kāi)啟*/       
 uint32_t DMA_PeripheralDataSize;   
 /*外設的數據長(cháng)度是為字節傳輸(8bits),半 字傳輸(16bits) 還是字傳輸(32bits) */    
 uint32_t DMA_MemoryDataSize;    
   /*設置內存的數據長(cháng)度*/
 uint32_t DMA_Mode;      
 /*設置DMA的模式,正常模式/循環(huán)模式  是否循環(huán)發(fā)送*/        
 uint32_t DMA_Priority; 
  /*設置 DMA 通道的優(yōu)先級,有低,中,高,超高四種模式*/        
 uint32_t DMA_M2M;    
  /*設置是否是存儲器到存儲器模式傳輸,*/       }
 DMA_InitTypeDef;

2.DMA使能函數

void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState  NewState);

功能:使能或者失能DMA外設

例如:DMA_Cmd(DMA1_Channel1 , ENABLE);  3.DMA中斷使能函數

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT,  FunctionalState NewState);1

功能:配置指定的DMAy通道x的中斷

注釋?zhuān)篋MA_IT_TC:傳輸完成 DMA_IT_HT:傳輸一半 DMA_IT_TE:傳輸錯誤

例如:DMA_ITConfig(DMA1_Channel1 , DMA_IT_TC , ENABLE);

4.設置CNDTRx和讀CNDTRx函數 (通道傳輸數據量)

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t  DataNumber); uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);12

作用:前者設置DMA通道的傳輸數據量(DMA處于關(guān)閉狀態(tài));后者獲取當前DMA通道傳輸剩余數據量(DMA處于開(kāi)啟狀態(tài))。

DMA庫函數配置過(guò)程:

  • 使能DMA時(shí)鐘:RCC_AHBPeriphClockCmd();

  • 初始化DMA通道:DMA_Init();

    • //設置通道;傳輸地址;傳輸方向;傳輸數據的數目;傳輸數據寬度;傳輸模式;優(yōu)先級;是否開(kāi)啟存儲器到存儲器。

  • 使能外設DMA;

    • 以串口為例:使能串口DMA發(fā)送,串口DMA使能函數。調用函數:USART_DMACmd();

  • 使能DMA通道傳輸;函數:DMA_Cmd();

  • 查詢(xún)DMA傳輸狀態(tài)。函數:DMA_GetFlagStatus();

  • 獲取當前剩余數據量大小 函數:DMA_GetCurrDataCounter(DMA1_Channel4);

UART DMA傳輸

DMA就是一個(gè)搬運工,可以將數據從一個(gè)位置搬運到另一個(gè)位置。以UART為例,如果要接收數據,會(huì )觸發(fā)UART中斷,然后CPU介入,在中斷中通過(guò)CPU將UART輸入寄存器的值讀出來(lái),存放到內存中;而DMA方式,產(chǎn)生UART中斷后,DMA直接參與,把UART輸入寄存器的值搬運到內存中,CPU只需要在去檢查內存的值就好了,這樣提高了CPU的效率。

DMA代碼配置

① DMA初始化配置

void dma_init(){
 
  DMA_InitTypeDef DMA_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);  /*DMA配置*/

  DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//串口數據寄存器地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //內存地址(要傳輸的變量的指針)
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(從內存到外設)
  DMA_InitStructure.DMA_BufferSize = 500; //傳輸內容的大小
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址不增
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址自增
  DMA_InitStructure.DMA_PeripheralDataSize =
  DMA_PeripheralDataSize_Byte ; //外設數據單位
  DMA_InitStructure.DMA_MemoryDataSize =
  DMA_MemoryDataSize_Byte ; //內存數據單位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次傳輸,循環(huán)
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium ; //優(yōu)先級:高
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止內存到內存的傳輸

  DMA_Init(DMA1_Channel4, &DMA_InitStructure); //配置DMA1的4通道
  DMA_Cmd(DMA1_Channel4,ENABLE);
  DMA_SetCurrDataCounter(DMA_CH4,DMA1_MEM_LEN);//DMA通道的DMA緩存的大小
  DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//配置DMA發(fā)送完成后產(chǎn)生中斷
 }

DMA中斷

void DMA1_Channel4_IRQHandler(void){ if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)
 {
 
  DMA_ClearFlag(DMA1_FLAG_TC4);
 }
}

main函數

#define SEND_BUF_SIZE 500 //發(fā)送數據長(cháng)度,最好等于sizeof(TEXT_TO_SEND)+2的整數倍.
 u8 SendBuff[SEND_BUF_SIZE]; //發(fā)送數據緩沖區const u8 TEXT_TO_SEND[]={"STM32F1 DMA 串口實(shí)驗"}; uint16_t i;int main(void){    
 uart_init(115200);   //串口初始化為115200
  
 for(i=0;i<500;i++)
 {
 SendBuff[i] =0xaf;
 } 
 USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口dma傳輸 
 
 while(1);
}

來(lái)源:嵌入式Linux

原文來(lái)源于:程序喵大人版權歸原作者或平臺所有,僅供學(xué)習參考與學(xué)術(shù)研究,如有侵權,麻煩聯(lián)系刪除~感謝




關(guān)鍵詞: DMA CPU 存儲器

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>