程序?qū)崿F(xiàn):
DMA的使用主要是DMA寄存器的初始設(shè)置,設(shè)置完成后,DMA接到觸發(fā)信號即可自動傳輸數(shù)據(jù)。
設(shè)置函數(shù)如下:
void DMAInit(char channel,char trigger,char transMode,char srcMode,char dstMode,
unsigned int src,unsigned int dst,unsigned int size)
{
unsigned int *DMAxCTL,*DMAxSA,*DMAxDA,*DMAxSZ;
DMACTL0 = trigger 《《 (channel 《《 2);
DMACTL1 = 0x04; //DMA收到觸發(fā)請求時(shí),等待當(dāng)前指令執(zhí)行完成后
switch (channel) //選擇當(dāng)前設(shè)置哪個(gè)DMA通道
{
case 0:
DMAxCTL = (unsigned int *)&DMA0CTL;
DMAxSA = (unsigned int *)&DMA0SA;
DMAxDA = (unsigned int *)&DMA0DA;
DMAxSZ = (unsigned int *)&DMA0SZ;
break; //指針 = 0通道控制
case 1:
DMAxCTL = (unsigned int *)&DMA1CTL;
DMAxSA = (unsigned int *)&DMA1SA;
DMAxDA = (unsigned int *)&DMA1DA;
DMAxSZ = (unsigned int *)&DMA1SZ;
break; //指針 = 1通道控制
case 2:
DMAxCTL = (unsigned int *)&DMA2CTL;
DMAxSA = (unsigned int *)&DMA2SA;
DMAxDA = (unsigned int *)&DMA2DA;
DMAxSZ = (unsigned int *)&DMA2SZ;
break; //指針 = 2通道控制
}
switch (transMode) //設(shè)置DMA通道的傳輸模式
{
case ‘S’: *DMAxCTL = DMADT_0; break; //單次傳輸
case ‘s’: *DMAxCTL = DMADT_4; break; //重復(fù)單次傳輸
case ‘B’: *DMAxCTL = DMADT_1; break; //塊傳輸
case ‘b’: *DMAxCTL = DMADT_5; break; //重復(fù)塊傳輸
case ‘I’: *DMAxCTL = DMADT_2; break; //突發(fā)塊傳輸 交錯(cuò)
case ‘i’: *DMAxCTL = DMADT_6; break; //重復(fù)突發(fā)塊傳輸 交錯(cuò)
}
*DMAxCTL |= (srcMode & 0x04) 《《 2; //源 字或字節(jié)
*DMAxCTL |= (srcMode & 0x03) 《《 8; //源 地址改變方式
*DMAxCTL |= (dstMode & 0x04) 《《 3; //目的 字或字節(jié)
*DMAxCTL |= (dstMode & 0x03) 《《 10; //目的 地址改變方式
*DMAxSA = src;
*DMAxDA = dst;
*DMAxSZ = size;
*DMAxCTL |= DMAEN; //DMA使能
}
函數(shù)比較麻煩,函數(shù)內(nèi)容按參數(shù)設(shè)置每個(gè)寄存器。DMACTL0 = trigger 《《 (channel 《《 2); 這個(gè)是設(shè)置對應(yīng)channel通道的的參考源,不大明白的可以看下DMACTL0的寄存器內(nèi)容;switch (channel)語句則根據(jù)通道設(shè)置對應(yīng)指針指向的寄存器;然后對應(yīng)設(shè)置參數(shù)即可。
當(dāng)設(shè)置成非重復(fù)模式時(shí),需要重新置位DMAEN,本程序就函數(shù)DMAReEnable實(shí)現(xiàn):
void DMAReEnable(char channel)
{
switch (channel) //使能對應(yīng)通道
{
case 0: DMA0CTL |= DMAEN; break; //0通道
case 1: DMA1CTL |= DMAEN; break; //1通道
case 2: DMA2CTL |= DMAEN; break; //2通道
}
}
這個(gè)函數(shù)比較簡單,只是根據(jù)傳入?yún)?shù)設(shè)置對應(yīng)通道的DMAEN位。
當(dāng)設(shè)置為軟件觸發(fā)時(shí),需要軟件啟動DMA程序如下:
void DMAStart(char channel)
{
switch (channel) //使能對應(yīng)通道
{
case 0: DMA0CTL |= DMAREQ; break; //0通道
case 1: DMA1CTL |= DMAREQ; break; //1通道
case 2: DMA2CTL |= DMAREQ; break; //2通道
}
}
這個(gè)和上個(gè)函數(shù)類似:僅僅設(shè)置一個(gè)控制位,函數(shù)很簡單,不再解釋啦。
程序?qū)崿F(xiàn)就這么多了,有關(guān)詳細(xì)內(nèi)容可以下載附件里的程序庫,程序的注釋很詳細(xì)。
使用示例:
使用這個(gè)程序時(shí),步驟和原來的相同:工程中加入DMA.c文件,然后源文件中包含DMA.h頭文件即可。
示例程序主要如下:
#include 《msp430x16x.h》
#include “DMA.h”
unsigned int a[5] = {8693,5689,2356,23565,5656};
unsigned int b[5];
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
//塊傳輸,5個(gè)字(16位) a-》b
DMAInit(0,0x00,‘B’,3,3,(unsigned int)a,(unsigned int)b,5);
DMAStart(0);
//如果需要再次傳輸 而不改變設(shè)置,只需調(diào)用DMAReEnable再次啟動傳輸即可
// 如果是重復(fù)塊傳輸,則不需要重新使能DMAReEnable 直接啟動即可
//這里僅僅演示了使用方法,實(shí)際應(yīng)用中,應(yīng)根據(jù)需要選擇適當(dāng)?shù)挠|發(fā)源。
//
LPM0;
}
示例程序完成功能很簡單,僅僅把一個(gè)數(shù)組的值賦給另外一個(gè)數(shù)組。數(shù)組地址即是數(shù)組名強(qiáng)制轉(zhuǎn)換為所需類型(無符號16位),傳入函數(shù)初始化設(shè)置。這里為了簡便,設(shè)置為軟件啟動。
運(yùn)行效果如下:
單步運(yùn)行完啟動DMA傳輸后,結(jié)果即出來了;說明DMA傳輸數(shù)據(jù)的速度是很快的。
DMA可以用于對速度要求比較高的程序中。例如:DMA配合硬件乘法器和ADC12模塊,可以很容易的實(shí)現(xiàn)比較高頻率的數(shù)字濾波方案。
評論