DMA简单的测试代码

MSP430F2616的DMA传输,根据触发方式的不同有多种模式,最简单的是Single Transfer,即:设置好源地址与目标地址,以及需要传输的byte/word数,全部传输完成之后DMAEN自动清零,而传输一个byte/word都需要触发一次。

MSP430的DMA源地址和目标地址可以为byte或者word类型,且可以设置递增、递减或者不变,通过寄存器进行相应的设置即可,但它们不是这里所要说明的内容,所以接下来,源地址和目标地址都将默认以word为单位,也就是MSP430默认的16位,且都设置成每触发一次,源地址和目标地址都递增。

(2014-03-22补充:前段时间一直在看Linux的内核源代码,慢慢的写程序的时候也会不自觉的往它的风格上面靠。Linux的内核源代码.c和.h文件里面的注释很少,仅有文件开头的说明,然后集中放置在Documentation中。但是我模仿这个风格写的代码,过一段时间之后自己再看,发现有些还算直观,有些却很难了解它说的是什么,自己也会糊涂。原因首先是文件开头没有写功能和关键参数说明,然后是函数里面引用的宏的字面意义也比较模糊,所以现在决定还是把关键性的注释加在函数里面,另外把无关当前功能的代码删掉,免得看起来一片一片的。)

/**********************************************************/
uint16_t dma_temp_A[8] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8};
uint16_t dma_temp_B[8] = {0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8};

int main (void)
{
    uint16_t i = 0;

    WDTCTL = WDTPW + WDTHOLD;

    // 传输4个word
    // 源地址为dma_temp_A
    // 目标地址为dma_temp_B
    DMA0SZ = 4;            
    DMA0SA = dma_temp_A;        
    DMA0DA = dma_temp_B;        

    // 采用Single transfer模式,源地址和目标地址都递增
    DMA0CTL = DMADT_0 + DMADSTINCR_3 + DMASRCINCR_3;
    
    DMA0CTL |= DMAEN;        
    for (i = 0; i < 4; i++)
        DMA0CTL |= DMAREQ;    

    while (1);
    return 0;
}

当执行到START2时,DMA0CTL = 0x0F10;
当执行for循环时,DMA0CTL = 0x0F10,因为DMAREQ触发后自动清零;
当for循环完成时,DMA0CTL = 0x0F08,说明DMAEN已经被清零,而中断标志位DMAIFG被挂起。

0x1100是数组所在地址(可能由于程序的不同而不同),通过观察它的值会发现:
dma_temp_A[8] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8};
dma_temp_B[8] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xB5, 0xB6, 0xB7, 0xB8};

以上就是DMA的Single Transfer模式使用方法。由于有寄存器缓存,所有的触发结束之后DMA0SA、DMA0DA和DMA0SZ的值都不会变化,如果要进行下一次传输,重新设置DMAEN、触发DMAREQ即可。

/***********************************************/
JTAG仿真器FET430UIF有单步执行的功能,只需要执行step命令即可,执行每一个step之后,都可以使用md命令观察相应地址的储值。md命令的使用方法是:
md address [length]
如果length不指定,则默认为64。

0x01d0是DMA0CTL所在地址:
(mspdebug)md 0x01d0

0x1100是数组的存储地址:
(mspdebug)md 0x1100

你可能感兴趣的:(MSP430+CC1101)