stm32如何用dma搬運(yùn)數(shù)據(jù)

  1.0 DMA的簡(jiǎn)介

stm32 如何用DMA搬運(yùn)數(shù)據(jù)

  1) DMA:直接存儲(chǔ)器存取(direct memory1090492304

access)。作用:主要是實(shí)現(xiàn)數(shù)據(jù)的高速搬運(yùn),為CPU完成簡(jiǎn)單性重復(fù)性數(shù)據(jù)搬運(yùn)工作。這個(gè)過(guò)程無(wú)需CPU干預(yù)。當(dāng)數(shù)據(jù)搬運(yùn)完成后,會(huì)有相應(yīng)的狀態(tài)標(biāo)識(shí)位來(lái)告知CPU。

  2) 特性:

  雙AHB 主總線架構(gòu),一個(gè)用于存儲(chǔ)器訪問(wèn),另一個(gè)用于外設(shè)訪問(wèn);

  STM32F4共有兩個(gè)DMA,兩個(gè)DMA 控制器總共有16 個(gè)數(shù)據(jù)流(每個(gè)控制器8 個(gè));

  每個(gè)數(shù)據(jù)流有單獨(dú)的四級(jí)32 位先進(jìn)先出存儲(chǔ)器緩沖區(qū)(FIFO);

  DMA 流控制器:要傳輸?shù)臄?shù)據(jù)項(xiàng)的數(shù)目是1 到65535,可用軟件編程;

  DMA數(shù)據(jù)搬運(yùn)方向可以靈活設(shè)置,可以實(shí)現(xiàn)三種數(shù)據(jù)搬運(yùn):

  從芯片內(nèi)部搬運(yùn)到→芯片外部

  從芯片外部搬運(yùn)到→芯片內(nèi)部

  從芯片內(nèi)部搬到芯片內(nèi)部

  注意:芯片內(nèi)部:指STM32內(nèi)部存儲(chǔ)器.    芯片外部:指STM32片上外設(shè),如串口。

  3) 弊端:如果需要接收大量的數(shù)據(jù)時(shí),需要頻繁觸發(fā)中斷,而且這個(gè)過(guò)程需要CPU參與。

  1.1 DMA框圖

  1.2 DMA請(qǐng)求通道映射表

  1.3 DMA數(shù)據(jù)流的配置編程步驟

  1) 使能外設(shè)的DMA功能。舉例:使能串口1的DMA發(fā)送或者DMA接收。

  2) 使能DMA時(shí)鐘

  3) DMA_SxCR 寄存器中的 EN 位清零,禁止DMA數(shù)據(jù)流

  4) 阻塞判斷EN位是否置0了。

  5) 在 DMA_SxPAR 寄存器中設(shè)置外設(shè)寄存器地址

  6) 在 DMA_SxM0AR 寄存器中設(shè)置存儲(chǔ)器地址。

  7) 在 DMA_SxNDTR 寄存器中配置要傳輸?shù)臄?shù)據(jù)個(gè)數(shù)的總數(shù)

  8) 使用 DMA_SxCR 寄存器中的 CHSEL[2:0] 選擇 DMA 通道

  9) 使用 DMA_SxCR 寄存器中的 PL[1:0] 位配置數(shù)據(jù)流優(yōu)先級(jí)

  10) 禁止FIFO

  11) 配置數(shù)據(jù)流傳輸方向

  12) 設(shè)置外設(shè)地址是增量模式還是固定模式

  13) 設(shè)置存儲(chǔ)器地址是增量模式還是固定模式

  14) 設(shè)置外設(shè)數(shù)據(jù)寬度

  15) 設(shè)置存儲(chǔ)器數(shù)據(jù)寬度

  16) 通過(guò)將 DMA_SxCR 寄存器中的 EN 位置 1 激活數(shù)據(jù)流。

  注意:只有“禁止了數(shù)據(jù)流”,才可以更改寄存器的配置。

  1.4 源和目標(biāo)的地址設(shè)置

  1.5 DMA控制器相關(guān)寄存器

  1.5.0 DMA 數(shù)據(jù)流 x 配置寄存器 (DMA_SxCR) (x = 0..7)

  每個(gè)數(shù)據(jù)流都有一個(gè)自己的“配置寄存器”,舉例:

  1) DMA1的數(shù)據(jù)流0的“配置寄存器”在寫代碼是應(yīng)該寫:DMA1_Stream0->CR

  2) DMA2的數(shù)據(jù)流5的“配置寄存器”在寫代碼是應(yīng)該寫:DMA2_Stream5->CR

  3) DMA1的數(shù)據(jù)流3的“配置寄存器”在寫代碼是應(yīng)該寫:DMA1_Stream3->CR

  4) DMA2的數(shù)據(jù)流6的“配置寄存器”在寫代碼是應(yīng)該寫:DMA2_Stream6->CR

  位 27:25 CHSEL[2:0]:通道選擇 (Channel selection)

  這些位將由軟件置 1 和清零。

  000:選擇通道 0?

  001:選擇通道 1?

  010:選擇通道 2?

  011:選擇通道 3?

  100:選擇通道 4?

  101:選擇通道 5?

  110:選擇通道 6?

  111:選擇通道 7

  提問(wèn):數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,對(duì)應(yīng)代碼:DMA2_Stream7->CR |=

4<<25;

  位 17:16 PL[1:0]:優(yōu)先級(jí) (Priority level)

  設(shè)置數(shù)據(jù)流的優(yōu)先級(jí)

  這些位將由軟件置 1 和清零。

  00:低

  01:中

  10:高

  11:非常高

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,數(shù)據(jù)流7的優(yōu)先級(jí)設(shè)置為“中”,對(duì)應(yīng)代碼:DMA2_Stream7->CR |=

1<<16;

  位 14:13 MSIZE[1:0]:存儲(chǔ)器數(shù)據(jù)大小 (Memory data size)

  00:字節(jié)(8 位)

  01:半字(16 位)

  10:字(32 位)

  11:保留

  舉例:

  如果存儲(chǔ)器是自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf1[2] = {1,2};那么存儲(chǔ)器的數(shù)據(jù)大小是8位

  如果存儲(chǔ)器是自定的一個(gè)數(shù)組,自定的數(shù)組是:u16 dataBuf2[2] = {1,2};那么存儲(chǔ)器的數(shù)據(jù)大小是16位

  如果存儲(chǔ)器是自定的一個(gè)數(shù)組,自定的數(shù)組是:u32 dataBuf2[2] = {1,2};那么存儲(chǔ)器的數(shù)據(jù)大小是32位

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1發(fā)送自定的一個(gè)數(shù)組,   自定的數(shù)組是:u8 dataBuf1[2]

= {1,2}; ,那么存儲(chǔ)器的數(shù)據(jù)大小要設(shè)置為“8位”,DMA2_Stream7->CR &=~(3<<13);

  位 12:11 PSIZE[1:0]:外設(shè)數(shù)據(jù)大小 (Peripheral data size)

  00:字節(jié)(8 位)

  01:半字(16 位)

  10:字(32 位)

  11:保留

  舉例:

  如果外設(shè)是USART1_DR寄存器,由于USART1_DR寄存器是8位有效的,所以外設(shè)大小需要設(shè)置為"8位"

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1發(fā)送自定的一個(gè)數(shù)組,自定義的數(shù)組是:u8 dataBuf1[2] =

{1,2}; ,   那么外設(shè)的數(shù)據(jù)大小要設(shè)置為“8位”,DMA2_Stream7->CR &=~(3<<11);

  位 10 MINC:存儲(chǔ)器遞增模式 (Memory increment mode)

  0:存儲(chǔ)器地址是固定的

  1:每次傳輸完一個(gè)數(shù)據(jù),存儲(chǔ)器地址遞增(增量為 MSIZE 值)

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf1[2] =

{1,2};    需要告訴DMA控制器,每發(fā)送一個(gè)數(shù)據(jù)后,需要進(jìn)行地址偏移(地址遞增),對(duì)應(yīng)代碼:DMA2_Stream7->CR

|=1<<10;

  類比:串口發(fā)送數(shù)據(jù)

  u8 dataBuf1[2] = {1,2};

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

  {

  USART1->DR = dataBuf1[i]; // 數(shù)組下標(biāo)偏移→地址偏移

  }

  位 9 PINC:外設(shè)遞增模式 (Peripheral increment mode)

  0:外設(shè)地址固定

  1:每次傳輸完一個(gè)數(shù)據(jù),外設(shè)地址遞增(增量為 PSIZE 值)

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf1[2] =

{1,2};    由于一個(gè)芯片設(shè)置定型后,外設(shè)的地址都是固定的,所以一般都將外設(shè)地址設(shè)置為固定的。對(duì)應(yīng)的代碼:DMA2_Stream7->CR

&=~(1<<9);

  位 7:6 DIR[1:0]:數(shù)據(jù)傳輸方向 (Data transfer direction)

  這些位將由軟件置 1 和清零。

  00:外設(shè)到存儲(chǔ)器

  01:存儲(chǔ)器到外設(shè)

  10:存儲(chǔ)器到存儲(chǔ)器

  11:保留

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1DMA發(fā)送數(shù)據(jù),數(shù)據(jù)傳輸方向需要配置為“存儲(chǔ)器到外設(shè)”。

對(duì)應(yīng)代碼:DMA2_Stream7->CR |= 1<<6;

  位 4 TCIE:傳輸完成中斷使能 (Transfer complete interrupt enable)

  DMA搬運(yùn)完成后,可以觸發(fā)DMA中斷,前提是將該位置1

  0:禁止 TC 中斷

  1:使能 TC 中斷

  位 0 EN:數(shù)據(jù)流使能/讀作低電平時(shí)數(shù)據(jù)流就緒標(biāo)志 (Stream enable / flag stream ready when read

low)

  功能1:用于使能數(shù)據(jù)流

  0:禁止數(shù)據(jù)流

  1:使能數(shù)據(jù)流

  功能2:用于指示狀態(tài)

  讀取該位,如果為0,則允許"對(duì)器寄存器進(jìn)行配置"

  讀取該位,如果為1,則不允許"對(duì)器寄存器進(jìn)行配置"

  注意:只有“禁止了數(shù)據(jù)流”,才可以更改寄存器的配置。

  1.5.1 DMA 數(shù)據(jù)流 x 數(shù)據(jù)項(xiàng)數(shù)寄存器 (DMA_SxNDTR) (x = 0..7)

  位 15:0 NDT[15:0]:要傳輸(發(fā)送或接收)的數(shù)據(jù)個(gè)數(shù) (Number of data items to transfer)

  寫入的值是要傳輸?shù)臄?shù)據(jù)個(gè)數(shù)(0 到 65535)。

  如果讀取該寄存器,則可以知道剩余需要傳輸?shù)臄?shù)據(jù)有多少個(gè)。

  DMA每傳輸一個(gè)數(shù)據(jù)后,此寄存器將遞減。

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1的DMA發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf[ ]

= {“hello world”};    對(duì)應(yīng)的代碼:DMA2_Stream7->NDTR = sizeof(dataBuf);

  1.5.2 DMA 數(shù)據(jù)流 x 外設(shè)地址寄存器 (DMA_SxPAR) (x = 0..7)

  位 31:0 PAR[31:0]:外設(shè)地址 (Peripheral address)

  寫入的的是外設(shè)寄存器,作用是:用于告訴DMA控制將數(shù)據(jù)搬運(yùn)到哪個(gè)外設(shè)寄存器或者從哪個(gè)外設(shè)寄存器取數(shù)據(jù)。

  DMA發(fā)送:將數(shù)據(jù)搬運(yùn)到USART1_DR

  u8 dataBuf[ ] = {“hello world”}; → DMA發(fā)送 →USART1_DR

  DMA接收:從USART1_DR取數(shù)據(jù),搬運(yùn)到dataBuf

  u8 dataBuf[50 ] = {0}; ←DMA 接收←USART1_DR

  這兩種搬運(yùn),都需要將USART1_DR的地址寫入到PAR寄存器。

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1的DMA發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf[ ]

= {“hello world”};    需要將USART1_DR的地址寫入到PAR寄存器,對(duì)應(yīng)代碼:DMA2_Stream7->PAR =

(u32)&USART1->DR;

  1.5.3 DMA 數(shù)據(jù)流 x 存儲(chǔ)器 0 地址寄存器 (DMA_SxM0AR) (x = 0..7)

  需要寫入的是:存儲(chǔ)器的首地址(可以簡(jiǎn)單的理解為數(shù)組首地址)。

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1的DMA發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf[ ]

= {“hello world”}; 需要將數(shù)組的地址寫入到M0AR寄存器,對(duì)應(yīng)代碼:DMA2_Stream7->M0AR =

(u32)&dataBuf[0];

  1.5.4 DMA 低中斷狀態(tài)寄存器 (DMA_LISR)

  1.5.5 DMA 高中斷狀態(tài)寄存器 (DMA_HISR)

  TCIFx:數(shù)據(jù)流 x 傳輸完成標(biāo)志位 (Stream x transfer complete interrupt flag)

(x=0..7)

  此位將由硬件置 1,由軟件清零,清零方法:將 1 寫入 DMA_HIFCR或者 DMA_LIFCR 寄存器的相應(yīng)位。

  0:數(shù)據(jù)流 x 上無(wú)傳輸完成事件

  1:數(shù)據(jù)流 x 上發(fā)生傳輸完成事件,即:數(shù)據(jù)搬運(yùn)完成

  注意:清零不是直接操作LISR、HISR。而是操作HIFCR、LIFCR

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1的DMA發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf[ ]

= {“hello world”};如何判斷是否發(fā)送完成?

  方法1:阻塞判斷法→while(!(DMA2->HISR&(1<<27)));

  方法2:中斷方法

  1.5.6 DMA 低中斷標(biāo)志清零寄存器 (DMA_LIFCR)

  1.5.7 DMA 高中斷標(biāo)志清零寄存器 (DMA_HIFCR)

  CTCIFx:數(shù)據(jù)流 x 傳輸完成中斷標(biāo)志清零 (Stream x clear transfer complete interrupt flag)

(x = 0..7)

  將 1 寫入此位時(shí), DMA_LISR 和DMA_HISR寄存器中相應(yīng)的 TCIFx 標(biāo)志將清零

  舉例:數(shù)據(jù)流7的請(qǐng)求通道選擇為通道4,即USART1_TX功能,如果想實(shí)現(xiàn)串口1的DMA發(fā)送自定的一個(gè)數(shù)組,自定的數(shù)組是:u8 dataBuf[ ]

= {“hello world”};如何判斷是否發(fā)送完成?

  阻塞判斷法→while(!(DMA2->HISR&(1<<27)));

  清零代碼:DMA2->HIFCR |= 1<<27;

  1.6 DMA實(shí)例代碼

  從開發(fā)板發(fā)一串信息到電腦串口助手并顯示助手軟件屏幕上。

  PA9----TXD

  PA10---RXD

  1.6.0 main.c

View Code

  1.6.1 usart1.c

View Code

  1.6.1 dma.c

View Code

  1.6.1 dma.h

View Code

  1.6.1 usart1.h

View Code

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。