DMAの数据传输

来源:互联网 发布:js confirm 套for循环 编辑:程序博客网 时间:2024/06/13 13:34
//这里采用定时器溢出中断作为触发源。每次溢出发送一个字节。
#include "../dma_driver.h"
#include "../avr_compiler.h"

//board.h中定义了按键Switch和LED灯所连接的IO端口。这个头文件是专门为Xmega A1 Xplained而配置的。
#include "../board.h"

#define SAMPLE_COUNT 9 //LED状态的数目。
uint8_t samples[SAMPLE_COUNT]={
0xff>>0,
0xff>>1,
0xff>>2,
0xff>>3,
0xff>>4,
0xff>>5,
0xff>>6,
0xff>>7,
0xff>>8
};


//DMA通道会被定时器溢出中断标志所触发,并会连续地触发只要溢出中断标志被置位。
//每次发生溢出时我们只执行一次数据传输。因此,我们需要使能溢出中断,并且当中断服务程序执行时会自动清除溢出中断标志。

ISR(TCC0_OVF_vect)//仅用于清除溢出中断标志位
{
nop();
}


//设置channel的参数以写LED的值。源地址会重新装载当数据块传输完成。
//使能Single-shot,使得每次溢出都传输一个字节的数据。
void SetupWriteChannel( DMA_CH_t * dmaChannel  )
{
DMA_SetupBlock(
dmaChannel,
samples,
DMA_CH_SRCRELOAD_BLOCK_gc,
DMA_CH_SRCDIR_INC_gc,
(void *) &(LEDPORT.OUT),
DMA_CH_DESTRELOAD_NONE_gc,
DMA_CH_DESTDIR_FIXED_gc,
SAMPLE_COUNT,
DMA_CH_BURSTLEN_1BYTE_gc,
0,
false//不重复传输
);
DMA_EnableSingleShot( dmaChannel );
DMA_SetTriggerSource( dmaChannel, DMA_CH_TRIGSRC_TCC0_OVF_gc ); // TCC0 溢出作为触发源。
}

//设置定时器以特定的采样频率产生溢出中断。2MHz / 2^16
void SetupSampleTimer( void )
{
TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
TCC0.PER = 0xffff;
TCC0.INTCTRLA = TC_OVFINTLVL_LO_gc;
PMIC.CTRL |= PMIC_LOLVLEN_bm;
}


//显示用途
void BlinkLEDs( void )
{
LEDPORT.OUT = 0x00;
delay_us( 1000000 ); // 等待一秒
LEDPORT.OUT = 0xff;
}


int main( void )
{
// 用于些数据到LED的DMA channel
DMA_CH_t * WriteChannel = &DMA.CH1;

// 设置为上拉输入。
PORTCFG.MPCMASK = SWITCHPORTL_MASK_gc;
SWITCHPORTL.PIN0CTRL = PORT_OPC_PULLUP_gc;
SWITCHPORTL.DIR = ~SWITCHPORTL_MASK_gc;//输入
LEDPORT.DIR = 0xff;//输出
DMA_Enable();//使能DMA
SetupWriteChannel(WriteChannel);
SetupSampleTimer();
sei(); // 使能全局中断
while(1)
{
//不断地把数据写到LED上,直到写完数据。
DMA_EnableChannel( WriteChannel );
    do {} while ((SWITCHPORTL.IN | PIN6_bm | PIN7_bm) == 0xff);
   DMA_DisableChannel( WriteChannel );
   //重新启动写通道。
   SetupWriteChannel(WriteChannel);
}
}