MSP430F1單片機(jī)的學(xué)習(xí)1——認(rèn)識(shí)和使用DMA
MSP430F1單片機(jī)的學(xué)習(xí)1——認(rèn)識(shí)和使用DMA

使用編譯工具:IAR For MSP430 6.4
使用單片機(jī):MSP430F1611

單片機(jī)的DAM是個(gè)啥?

說起DAM,玩單片機(jī)的人應(yīng)該大多都聽說過,但也有一些初學(xué)者不太了解,這到底是個(gè)啥,有人說用DAM的速度快,有人說用DMA不占用CPU內(nèi)存,但是有沒有比較好理解的解釋呢?哎嘿,那絕對(duì)是當(dāng)然的了,請(qǐng)看我的表演,其實(shí)DMA可以看做是一家專門的搬運(yùn)公司,沒錯(cuò),DMA就是MCU中的一家搬運(yùn)公司,它可以幫你把貨物從貨源地A搬運(yùn)到目的地B地址,只要你告訴他什么時(shí)候開始搬,要怎樣搬,你就不用管了,他就會(huì)給你搬過去,而且速度賊快。
?

在MSP430F1611中,搬運(yùn)公司共有3個(gè)司機(jī),分別是DMA0、DMA1、DMA2,
DMA總寄存器,DMACTL0、DMACTL1是公司的統(tǒng)一控制器,分別控制著三個(gè)司機(jī)的工作方式
DMACTL0???????? :選擇DAM的工作模式,選擇觸發(fā)源,運(yùn)輸?shù)臈l件
DMACTL1???????? : 傳輸條件、中斷,需要運(yùn)輸時(shí),司機(jī)響應(yīng)的情況

DMA0寄存器,主要給DMA0分配具體工作
DMA0SA????????? :設(shè)置DAM的貨源,必須為16位地址,(u16)?????????????????????????????????????? DMA0DA????????? :設(shè)置DAM的目的地,必須為16位地址,(u16)*
DMA0SZ????????? :設(shè)置送貨的數(shù)量,字節(jié)為單位
DMA0CTL???????? :設(shè)置運(yùn)輸方式,、啟動(dòng),停止、中斷、等控制

DMA1寄存器,主要給DMA1分配具體工作
DMA1SA????????? :設(shè)置DAM的貨源,必須為16位地址,(u16)?????????????????????????????????????? DMA1DA????????? :設(shè)置DAM的目的地,必須為16位地址,(u16)*
DMA1SZ????????? :設(shè)置送貨的數(shù)量,字節(jié)為單位
DMA1CTL???????? :設(shè)置運(yùn)輸方式、啟動(dòng),停止、中斷、等控制

DMA2寄存器,主要給DMA2分配具體工作
DMA2SA????????? :設(shè)置DAM的原始貨源地,必須為16位地址,(u16)* ?????????????????????????????????? DMA2DA????????? :設(shè)置DAM的原始目的地,必須為16位地址,(u16)*
DMA2SZ????????? :設(shè)置送貨的數(shù)量,字節(jié)為單位
DMA2CTL???????? :設(shè)置運(yùn)輸方式、啟動(dòng),停止、中斷、等控制

重點(diǎn)要控制的是,
DMACTL0 ——選擇觸發(fā)源,
DMAxCTL(以DMA0位代表DMA0CTL)——設(shè)置運(yùn)輸方式、啟動(dòng),停止、中斷、等控制
DMAxSA(DMA0SA)——原始貨源地,可以設(shè)置單片機(jī)內(nèi)的所有地址,包括UART的發(fā)送BUF,F(xiàn)lash,ROM等,
DMAxDA(DMA0DA )——原始貨源地,可以設(shè)置單片機(jī)內(nèi)的所有地址,包括UART的發(fā)送BUF,F(xiàn)lash,ROM等,
DMAxSZ (DMAxSZ )——貨物總量,所要傳輸?shù)臄?shù)據(jù)大小,以字節(jié)為單位,
DMACTL1
???????

具體程序測(cè)試,使用DMA0進(jìn)行測(cè)試,DMA1、DMA2的用法一樣,不贅述。
測(cè)試內(nèi)容:
在DMACTL1、DMA0SA、DMA0DA、DMA0SZ、DMA0CTL寄存器不變的情況下,改變DMACTL0的值,從而改變觸發(fā)傳輸?shù)姆绞?/p>
DMACTL0、DMA0SA、DMA0DA、DMA0SZ、DMA0CTL不變的情況下,改變DMACTL1
DMACTL1、DMACTL0、DMA0SA、DMA0SZ、DMA0CTL不變的情況下,改變DMA0DA

在DMACTL1、DMA0SA、DMA0DA、DMA0SZ、DMA0CTL寄存器不變的情況下,改變DMACTL0的值,從而改變觸發(fā)傳輸?shù)姆绞?;DMACTL0中低四位控制DMA0的觸發(fā)方式,總共有2^4=16種,如下圖所示,


測(cè)試開始:DMACTL0 = DMA0TSEL_0,DMA_REQ觸發(fā)模式,DMA0CTL寄存器的DMAREQ位 置位 了,就觸發(fā)1次傳輸,該位軟件設(shè)置觸發(fā),DMA0CTL |= DMAREQ;該位自動(dòng)清零;

打開Memory,在左上角的Go to中輸入我們要觀察的地址,

繼續(xù)運(yùn)行,可以看到 0x0220——0x025f 共0x40個(gè)字節(jié)被重新賦值,而0x0280——0x02bf 的0x40個(gè)字節(jié)的值還是沒變,比較亂;

繼續(xù)運(yùn)行,盯著這個(gè)值,運(yùn)行當(dāng)前一句代碼,

如下,DAM0把0x0220中的貨物(值)運(yùn)送到了目的地0x0280中,

以后每次觸發(fā)REQ,發(fā)現(xiàn)DMA0都會(huì)去以原始貨源地地址為基準(zhǔn)的下一個(gè)地址,然后把那里的值運(yùn)送到以原始目的地為基準(zhǔn)的下一地址,最終把所有貨物 DMA0SZ = 0x040;運(yùn)輸完成

DMA完成傳輸,之后再觸發(fā)REQ,后面地址的值也不會(huì)變,DAM0已經(jīng)干完活,去休息了。


測(cè)試代碼:
#include <msp430.h>
__no_init u8 SDEventBuf[0x10] @0x0220;
//u8 SDEventBuf[0x10] ={0};
int main(void)
{
? WDTCTL = WDTPW + WDTHOLD;???????????????? // 關(guān)閉看門狗
? for(u16 temp=0;temp<0x40;temp++)????????? //給數(shù)組賦值
? {
???? *(SDEventBuf+temp) = temp;
? }
? DMACTL0 = DMA0TSEL_0;???????????????????? // 選擇DMA0觸發(fā)方式?? ,REQ
? DMACTL1 = 0;????????????????????????????? //觸發(fā)時(shí)的響應(yīng),中斷等,無
? DMA0SA = (u16)SDEventBuf;???????????????? // DMA0貨源地,16bit
? DMA0DA = 0x0280;????????????????????????? // DMA0目的地,16bit
? DMA0SZ = 0x040;?????????????????????????? // 貨物總量,字節(jié)
? // 字節(jié)to字節(jié),每次觸發(fā)運(yùn)輸一個(gè)字節(jié),貨源地地址自加,目的地地址自加,啟動(dòng)DMA0
? DMA0CTL = DMASBDB + DMADT_4 + DMASRCINCR_3 + DMADSTINCR_3 + DMAEN;
? for (;;)???????????????????????????????? ?
? {
??? DMA0CTL |= DMAREQ;????????????????????? // 手動(dòng)觸發(fā),DMA0REQ
? }
}

改變DMACTL0,DMACTL0 = DMA0TSEL_0,觸發(fā)方式為Timer_A(TACCR2.IFG), TACCTL2的CCIFG位 置位 了,就觸發(fā)1次傳輸,如果設(shè)置了Timer_A定時(shí)器的CCR2,并使能了標(biāo)志位,那么每次定時(shí)時(shí)間到,就觸發(fā)1次傳輸;本次測(cè)試使用軟件設(shè)置該位,TACCTL2 |= CCIFG;標(biāo)志位自動(dòng)清零;這就是DMA和定時(shí)器Timer的結(jié)合使用

直接來到這一步,觸發(fā)之前,可以看到 0x0220——0x025f 共0x40個(gè)字節(jié)被重新賦值,而0x0280——0x02bf 的0x40個(gè)字節(jié)的值還是沒變,比較亂;

運(yùn)行當(dāng)前一句代碼,如下,同樣的,DAM0把0x0220中的貨物(值)運(yùn)送到了目的地0x0280中,

跟上面是一樣的,除了觸發(fā)方式不一樣了,其他都一樣,

測(cè)試代碼:
#include <msp430.h>
#include "typeredefine.h"
__no_init u8 SDEventBuf[0x10] @0x0220;
//u8 SDEventBuf[0x10] ={0};
int main(void)
{
? WDTCTL = WDTPW + WDTHOLD;???????????????? // 關(guān)閉看門狗
? for(u16 temp=0;temp<0x40;temp++)????????? //給數(shù)組賦值
? {
???? *(SDEventBuf+temp) = temp;
? }
? DMACTL0 = DMA0TSEL_1;???????????????????? // 選擇DMA0觸發(fā)方式?? ,REQ
? DMACTL1 = 0;????????????????????????????? //觸發(fā)時(shí)的響應(yīng),中斷等,無
? DMA0SA = (u16)SDEventBuf;???????????????? // DMA0貨源地,16bit
? DMA0DA = 0x0280;????????????????????????? // DMA0目的地,16bit
? DMA0SZ = 0x040;?????????????????????????? // 貨物總量,字節(jié)
? // 字節(jié)to字節(jié),每次觸發(fā)運(yùn)輸一個(gè)字節(jié),貨源地地址自加,目的地地址自加,啟動(dòng)DMA0
? DMA0CTL = DMASBDB + DMADT_4 + DMASRCINCR_3 + DMADSTINCR_3 + DMAEN;
? for (;;)
? {
??? TACCTL2 |= CCIFG;?????????????????????? // 手動(dòng)觸發(fā),TACCTL2 |= CCIFG
? }
}

總結(jié), DMACTL0控制著DMA0——DMA2的觸發(fā)方式,每個(gè)DMA通道有16種觸發(fā)方式,以DMA為例(其他的為相應(yīng)的DMAxTSEL_x)進(jìn)行簡單描述:
DMA0TSEL_0????? 軟件設(shè)置DMA0CTL |= DMAREQ;觸發(fā),??? ? ? ? ???????????????????? DMA0TSEL_1?? 定時(shí)器Timer_A的CCR2標(biāo)志位 置位,即TACCTL2 &CCIFG==CCIFG觸發(fā) DMA0TSEL_2?? 定時(shí)器Timer_B的CCR2標(biāo)志位 置位,即TACCTL2 &CCIFG==CCIFG;觸發(fā)???? DMA0TSEL_3??? UART0/I2C的接收標(biāo)志位 置位,UART/SPI模式: IFG1 &URXIFG0 == URXIFG0; 觸發(fā) 。I2C模式,未測(cè)試
DMA0TSEL_4????UART0/I2C的發(fā)送標(biāo)志位 置位,? UART/SPI模式 IFG1 &UTXIFG0 == UTXIFG0; 觸發(fā);但是需要注意的是,IFG1的UTXIFG0位需要在U0CTL的 SWRST要置零后才能觸發(fā),即U0CTL &= ~SWRST; 做個(gè)標(biāo)記,當(dāng)設(shè)置U0CTL &= ~SWRST之后觸發(fā)了一次中斷。后面有時(shí)間測(cè)試一下UART功能。I2C模式,未測(cè)試
DMA0TSEL_5? DAC12的中斷標(biāo)志位 置位,即DAC12_0CTL &DAC12IFG== DAC12IFG;觸發(fā)??
DMA0TSEL_6 ,標(biāo)記,測(cè)試失敗
DMA0TSEL_7???定時(shí)器Timer_A的CCR0標(biāo)志位 置位,即TACCTL0 &CCIFG==CCIFG觸發(fā)?????
DMA0TSEL_8???定時(shí)器Timer_B的CCR0標(biāo)志位 置位,即TACCTL0 &CCIFG==CCIFG;觸發(fā)?????
DMA0TSEL_9???UART1的接收標(biāo)志位 置位,即 IFG2 &URXIFG1 == URXIFG0; 觸發(fā)???? DMA0TSEL_10???UART1的發(fā)送標(biāo)志位 置位,即 IFG2 &URXIFG1 == URXIFG0; 觸發(fā);但是需要注意的是,IFG2的UTXIFG2位需要在U1CTL的 SWRST要置零后才能觸發(fā),即U1CTL &= ~SWRST; 做個(gè)標(biāo)記,當(dāng)設(shè)置U1CTL &= ~SWRST之后觸發(fā)了一次中斷。后面有時(shí)間測(cè)試一下UART功能。 ???
DMA0TSEL_11???????
DMA0TSEL_14? DMA其他中斷標(biāo)志位置位觸發(fā),其中DAM2→DMA0,DMA0→ DMA1, DMA1?→ DMA2,即,DMA2CTL &DMAIFG ==? DMAIFG; 觸發(fā)DMA0傳輸,以此類推。 ???
DMA0TSEL_15?? 暫未找到如何測(cè)試

DMACTL0、DMA0SA、DMA0DA、DMA0SZ、DMA0CTL不變的情況下,改變DMACTL1, DAMCTL1寄存器的各個(gè)位的控制如下?????????????????????????????????????????????????????????????

14-12位,控制每次傳輸?shù)姆绞?,DMADT_0——DMADT_7共8種模式;
11-10位,控制目的地地址的變化方式,共DMADSTINCR_0——DMADSTINCR_3四種,其實(shí)是三種;
9-8位,控制貨源地地址的變化方式,共DMASRCINCR_0——DMASRCINCR_3四種,其實(shí)是三種;
7-6位,控制貨源地→目的地的地址分配方式,共四種,DMASWDW:字→字, DMASBDW:字節(jié)→字,DMASWDB :字→字節(jié),DMASBDB:字節(jié)→字節(jié);上面的測(cè)試使用的都是:字節(jié)→字節(jié);
第5位,控制傳輸觸發(fā)是上升沿觸發(fā),還是高電平觸發(fā),DMALEVEL=0為上升沿觸發(fā);
第4位,DMAEN控制啟動(dòng)DMA的開關(guān),DMAEN=1,開;
第3位,DMAIFG,中斷觸發(fā)標(biāo)志位,當(dāng)開啟中斷后,傳輸?shù)目傌浟客瓿桑―MA0SZ=0)之后,觸發(fā)中斷,DMAIFG =1;
第2位,DMAIE,DMA中斷開關(guān),DMAIE=1,開啟DMA中斷;
第1位,DMAABORT,DMA停止傳輸開關(guān),當(dāng)DMAABORT=1,傳完當(dāng)前的一次傳輸后,停止傳輸;
第0位,DMAREQ,軟件觸發(fā)DAM傳輸,當(dāng)觸發(fā)方式為DMA0TSEL_0——DMAREQ觸發(fā)時(shí),DMAREQ = 1,觸發(fā)傳輸,并且自動(dòng)清零。

為了方便測(cè)試,DMACTL0 = DMA0TSEL_0;使用軟件觸發(fā)方式進(jìn)行測(cè)試。

先改變傳輸方式:
DMA0CTL = DMASBDB + DMAIE?+ DMASRCINCR_3 + DMADSTINCR_3 + DMAEN;
不變,
改變:DMA0CTL |=DMADT_0;從DMADT_0——DMADT_78種模式

程序測(cè)試:未完待續(xù)。。。
飛花兩岸照船紅
百里榆堤半日風(fēng)
臥看滿天云不動(dòng)
不知云與我俱東
????????????????????????——————2020年6月24日09:02:15