本帖最后由 jxc827 于 2012-6-24 19:12 编辑
使用DMA实现UART0收发功能。直接在网站例程基础上修改,在此谢谢原作者。
UART0通过DMA方式接收串口数据,当长度达到16字节时,将接收到的数据通过DMA发送回来。两个LED闪烁指示UART0的发送和接收。
实验板上焊掉了R5,R6两个电阻。
需要注意的是:DMA接收数据长度必须4字节对齐,最少接收4个字节才能触发DMA接收中断。
主程序main.c
/*----------------------------------------------------------------------------*/
/* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
/*----------------------------------------------------------------------------*/
#include "includes.h" //包含所需的头文件
#define DMA_LENTH 16
uint8_t RX_BUFF[DMA_LENTH];
uint8_t i=0, j=1;
/*************PDMA CH0传输完成中断函数********************************/
void PFN_DRVPDMA0_callback(void)
{
DrvPDMA_ClearIntFlag(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD_FLAG); //清除中断标志
if(i%2)
DrvGPIO_SetBit(E_GPA,2);
else
DrvGPIO_ClrBit(E_GPA,2);
i++;
}
/*************PDMA CH1传输完成中断函数****************************/
void PFN_DRVPDMA1_callback(void)
{
DrvPDMA_ClearIntFlag(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD_FLAG); //清除中断标志
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //将接收的数据DMA发送回去
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //重新开始接收
if(j%2)
DrvGPIO_SetBit(E_GPA,3);
else
DrvGPIO_ClrBit(E_GPA,3);
j++;
}
/*************PDMA CH0配置函数********************************/
void PDMA0_Configuration(void)
{
STR_PDMA_T sPDMA;
DrvPDMA_Init(); //使能PDMA时钟
DrvPDMA_CHSoftwareReset(eDRVPDMA_CHANNEL_0); //软件复位CH0内部状态机和指针
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0,eDRVPDMA_UART0,eDRVPDMA_WRITE_APB); //指定PDMA0为UART0的发送
sPDMA.sSrcCtrl.u32Addr = (uint32_t)RX_BUFF; //源地址为发送BUFF
sPDMA.sDestCtrl.u32Addr = UART0_BASE; //目的地址为UART0发送FIFO
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS; //8位宽度
sPDMA.u8Mode = eDRVPDMA_MODE_MEM2APB; //内存到外设模式
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED; //源地址增长
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; //目的地址固定不变
sPDMA.i32ByteCnt = DMA_LENTH; //传输长度
DrvPDMA_Open(eDRVPDMA_CHANNEL_0,&sPDMA); //配置DMA CH0参数
DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD ); //使能传输完成中断
DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0,eDRVPDMA_BLKD,(PFN_DRVPDMA_CALLBACK)PFN_DRVPDMA0_callback);
}
/*************PDMA CH1配置函数********************************/
void PDMA1_Configuration(void)
{
STR_PDMA_T sPDMA;
DrvPDMA_Init(); //使能PDMA时钟
DrvPDMA_CHSoftwareReset(eDRVPDMA_CHANNEL_1); //软件复位CH1内部状态机和指针
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_1,eDRVPDMA_UART0,eDRVPDMA_READ_APB); //指定PDMA1为UART0的接收
sPDMA.sSrcCtrl.u32Addr = UART0_BASE; //源地址为UART0 FIFO
sPDMA.sDestCtrl.u32Addr =(uint32_t)RX_BUFF ; //目的地址为接收BUFF
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS;
sPDMA.u8Mode = eDRVPDMA_MODE_APB2MEM; //外设到内存模式
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; //源地址固定
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED; //目的地址增长
sPDMA.i32ByteCnt = DMA_LENTH; //一次DMA长度4字节
DrvPDMA_Open(eDRVPDMA_CHANNEL_1,&sPDMA); //配置DMA CH1参数
DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD );
DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_1,eDRVPDMA_BLKD,(PFN_DRVPDMA_CALLBACK)PFN_DRVPDMA1_callback);
}
/**************************************************************** Function name: main
** Descriptions: usart
** input parameters: 无
** output parameters: 无
** Returned value: 无
*************************************************************/
int main (void)
{
Set_System(); //封装一些初始化模块
PDMA0_Configuration(); //配置发送DMA
PDMA1_Configuration(); //配置接收DMA
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //开始接收
while(1)
{
;
}
}
工程压缩包: |