CC2530串口DMA研究,本次测试代码主要涉及串口初始化,串口DMA发送,串口DMA接收,串口发送,串口中断接收。
所用串口为:
// uart1
// p0_4 - TX, p0_5 - RX
具体代码如下,仅供参考。
1.dma.c
#include "hal_types.h"
#include "bspDma.h"
#include "ioCC2530.h"
#include "hal_dma.h"
#include "uart.h"
DMA_DESC __xdata dmaConfig;
bool sDataReceived=0;
bool mDataTransmitted=0;
void NOPn(uint8 temp)
{
for(uint8 i=0;i<temp;i++)
{
NOP();
}
}
void DMA_Transmission(uint8 channel)
{
//DMA进入工作模式通道0
DMAARM |= (1<<channel);//为了任何DMA传输能够在该通道上发生,该位必须置1,对于非重复传输模式,一旦完成传送,该位自动清0
//一个通道准备工作(即获得配置数据)的时间需要9个系统时钟
NOPn(9);
DMAIRQ = 0; //清中断标志
//DMA通道0传送请求,即触发DMA传送
DMAREQ |= (1<<channel);//设置为1,激活DMA通道0(与一个触发事件具有相同的效果),当DMA传输开始清除该位
//等待DMA通道0传送完毕
//for (; !(DMAIRQ & DMAIRQ_DMAIF0););//当DMA通道0传送完成,DMAIRQ:DMAIF1位置1,与上DMAIRQ_DMAIF1(0x01),取非后为0退出循环
while(!(DMAIRQ&(1<<channel))); //等待DMA通道0传输结束
//清除中断标志
DMAIRQ = ~(1<<channel);
}
void DMA_Copy_Init(uint8* sourceaddr, uint8* distanationaddr, uint8 len)
{
//测试DMA通道,无源触发,data数据复制到copy,测试成功,DMA传输无误
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, sourceaddr);//load address of the dma source
SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, distanationaddr);//load address of the dma distanation
SET_WORD(dmaConfig.LENH, dmaConfig.LENL, len); //LEN = nmax
dmaConfig.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
dmaConfig.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
dmaConfig.TRIG = DMA_TRIG_NONE;//dmaConfig.TRIG = DMA_TRIG_URX1;
dmaConfig.TMODE = DMA_TMODE_BLOCK;// Transfer block of data (length len) after each DMA trigger
dmaConfig.SRCINC = DMA_SRCINC_1; // Increase source addr. by 1 between transfers
dmaConfig.DESTINC = DMA_DESTINC_1; // Keep the same dest. addr. for all transfers
dmaConfig.IRQMASK = DMA_IRQMASK_DISABLE;
dmaConfig.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
dmaConfig.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
SET_WORD(DMA0CFGH, DMA0CFGL, &dmaConfig);
DMAARM = ABORT; //停止DMA所有通道进行传输
DMA_Transmission(0); //DMA进入工作模式通道0
}
void UART_DMA_RX_Init(uint8* distanationaddr, uint8 len)
{/*
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &X_U1DBUF);//load address of the dma source
SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, distanationaddr);//load address of the dma distanation
SET_WORD(dmaConfig.LENH, dmaConfig.LENL, len); //LEN = nmax
dmaConfig.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
dmaConfig.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
dmaConfig.TRIG = DMA_TRIG_URX1;//DMA_TRIG_URX1;DMA_TRIG_NONE;
dmaConfig.TMODE = DMA_TMODE_SINGLE;// Transfer block of data (length len) after each DMA trigger//DMA_TMODE_SINGLE,DMA_TMODE_BLOCK
dmaConfig.SRCINC = DMA_SRCINC_0; // Keep the same source addr. addr. for all transfers
dmaConfig.DESTINC = DMA_DESTINC_1; // Increase dest. by 1 between transfers
dmaConfig.IRQMASK = DMA_IRQMASK_ENABLE;//DMA_IRQMASK_ENABLE;DMA_IRQMASK_DISABLE
dmaConfig.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
dmaConfig.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
SET_WORD(DMA0CFGH, DMA0CFGL, &dmaConfig);
DMAIF = 0;
DMAIRQ &= ~DMAARM_DMAARM0;
DMAIE = 1;
EA = 1;
DMAARM |= DMAARM_DMAARM0;
DMAREQ |= DMAREQ_DMAREQ0;
*/
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &X_U1DBUF);//load address of the dma source
SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, distanationaddr);//load address of the dma distanation
SET_WORD(dmaConfig.LENH, dmaConfig.LENL, len); //LEN = nmax
dmaConfig.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
dmaConfig.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
dmaConfig.TRIG = DMA_TRIG_URX1;//DMA_TRIG_URX1;DMA_TRIG_NONE;
dmaConfig.TMODE = DMA_TMODE_SINGLE;// Transfer block of data (length len) after each DMA trigger//DMA_TMODE_SINGLE,DMA_TMODE_BLOCK
dmaConfig.SRCINC = DMA_SRCINC_0; // Increase source addr. by 1 between transfers
dmaConfig.DESTINC = DMA_DESTINC_1; // Keep the same dest. addr. for all transfers
dmaConfig.IRQMASK = DMA_IRQMASK_ENABLE;//DMA_IRQMASK_ENABLE;DMA_IRQMASK_DISABLE
dmaConfig.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
dmaConfig.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
SET_WORD(DMA0CFGH, DMA0CFGL, &dmaConfig);
DMAARM = ABORT; //停止DMA所有通道进行传输
DMA_Transmission(0);
}
void UART_DMA_TX_Init(uint8* sourceaddr, uint8 len)
{
//测试DMA通道,DMA_TRIG_UTX1触发,data数据复制到X_U1DBUF,启用DMA中断,测试成功,DMA传输无误
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, sourceaddr);//load address of the dma source
SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, &X_U1DBUF);//load address of the dma distanation
SET_WORD(dmaConfig.LENH, dmaConfig.LENL, len); //LEN = nmax
dmaConfig.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
dmaConfig.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
dmaConfig.TRIG = DMA_TRIG_UTX1;//DMA_TRIG_UTX1;DMA_TRIG_NONE
dmaConfig.TMODE = DMA_TMODE_SINGLE;// Transfer block of data (length len) after each DMA trigger//DMA_TMODE_SINGLE,DMA_TMODE_BLOCK
dmaConfig.SRCINC = DMA_SRCINC_1; // Increase source addr. by 1 between transfers
dmaConfig.DESTINC = DMA_DESTINC_0; // Keep the same dest. addr. for all transfers
dmaConfig.IRQMASK = DMA_IRQMASK_ENABLE;
dmaConfig.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
dmaConfig.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
SET_WORD(DMA1CFGH, DMA1CFGL, &dmaConfig);
DMAIF = 0;
DMAIRQ &= ~DMAARM_DMAARM1;
DMAIE = 1;
EA = 1;
DMAARM |= DMAARM_DMAARM1;
DMAREQ |= DMAREQ_DMAREQ1;
/*
//测试DMA通道,DMA_TRIG_UTX1触发,data数据复制到X_U1DBUF,测试成功,DMA传输无误
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, sourceaddr);//load address of the dma source
SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, &X_U1DBUF);//load address of the dma distanation
SET_WORD(dmaConfig.LENH, dmaConfig.LENL, len); //LEN = nmax
dmaConfig.VLEN = DMA_VLEN_USE_LEN; // Transfer number of bytes commanded by n
dmaConfig.WORDSIZE = DMA_WORDSIZE_BYTE; // Each transfer is 8 bits
dmaConfig.TRIG = DMA_TRIG_UTX1;//DMA_TRIG_UTX1;DMA_TRIG_NONE
dmaConfig.TMODE = DMA_TMODE_SINGLE;// Transfer block of data (length len) after each DMA trigger//DMA_TMODE_SINGLE,DMA_TMODE_BLOCK
dmaConfig.SRCINC = DMA_SRCINC_1; // Increase source addr. by 1 between transfers
dmaConfig.DESTINC = DMA_DESTINC_0; // Keep the same dest. addr. for all transfers
dmaConfig.IRQMASK = DMA_IRQMASK_DISABLE;
dmaConfig.M8 = DMA_M8_USE_8_BITS; // Use all 8 bits of first byte in source data to determine the transfer count
dmaConfig.PRIORITY = DMA_PRI_HIGH; // DMA memory access has high priority
SET_WORD(DMA1CFGH, DMA1CFGL, &dmaConfig);
DMAARM = ABORT; //停止DMA所有通道进行传输
DMA_Transmission(1); //DMA进入工作模式通道1
*/
}
#pragma vector=DMA_VECTOR
__interrupt void dma_IRQ(void)
{
DMAIF = 0;
DMAIRQ &= ~DMAIRQ_DMAIF0;
sDataReceived = TRUE;
DMAIRQ &= ~DMAIRQ_DMAIF1;
while(U1ACTIVE);
mDataTransmitted = TRUE;
}
2.main.c
#include <iocc2530.h>
#include "hal_types.h"
#include "hal_board.h"
#include "hal_mcu.h"
#include "string.h"
#include "W25Qxx.h"
#include "uart.h"
#include "bspDma.h"
#define LED P2_0
uint8 string[] = "uart DMA test!";//http://en.core.cn
//此数据是用来复制到内存的其他区域
uint8 data[] = "W25Q64 R&W test!";
//数据长度
#define DATA_AMOUNT sizeof(data)
//用来保存复制来的数据区域
uint8 copy[DATA_AMOUNT];
extern bool sDataReceived;
extern bool mDataTransmitted;
void InitClockTo32M(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
while(!(CLKCONSTA & 0x40)); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
}
void InitLed(void)
{
P2DIR |= 0x01;
P2_0 = 0;
}
void UART1_Init(void)
{
// uart1 init config
PERCFG &= ~1<<1; //bit1 = 0, uart1 -- postion 1 p0_4, p0_5, bit1 = 1, postion 2 p1_6, p1_7
P0SEL |= (1<<4 | 1<<5);//uart1 p0_4, p0_5:bit4,5 = 1
P2DIR &= ~1<<7; //bit[7-6] = 01, at P0 port, uart1 get a higher priority than uart0
P2DIR |= 1<<6;
U1CSR |= 1<<7; //bit7=0 uartMode;1 spiMode
U1GCR |= 11; //U0GCR and U0BAUD set baud rate.
U1BAUD |= 216; //115200
UTX1IF = 0; //clear uart0 TX interrupt flag. //we does not use it.
URX1IF = 0; //clear uart0 RX interrupt flag.
URX1IE = 1; //Enable rx interrupt
U1CSR |= 0X40; //Enable rx
EA=1;
}
void main(void)
{
InitClockTo32M();
InitLed();
UART1_Init();
Uart_Send_String(string,sizeof(string));
while(1)
{
UART_DMA_RX_Init(copy,DATA_AMOUNT);
if (copy[0]!=0)
{
Uart_Send_String(copy,sizeof(copy));
memset(copy,0,sizeof(copy));
}
/*
//DMA通道0串口接收,数据从串口缓冲区放到copy,可以通过电脑串口助手查看串口打印出来的数据
//UART_DMA_RX(copy, DATA_AMOUNT);
if (sDataReceived)
{
sDataReceived = FALSE;
Uart_Send_String(copy,sizeof(copy));
memset(copy,0,sizeof(copy));
}
*/
/*
//DMA通道1串口发送,数据从data放到串口缓冲区,可以通过电脑串口助手查看串口打印出来的数据
UART_DMA_TX_Init(string, sizeof(string));
if (mDataTransmitted)
{
mDataTransmitted=0;
}
*/
/*
//DMA通道0数组拷贝测试,无源触发,数据从data复制到copy,可以通过电脑串口助手查看串口打印出来的数据
DMA_Copy_Init(data, copy, sizeof(data));
Uart_Send_String(copy,sizeof(copy));
*/
/*
//串口中断接收测试
if(copy[0] != 0)
{
Uart_Send_String(copy,DATA_AMOUNT);
memset(copy,0,DATA_AMOUNT);
}
*/
LED = ~LED;
halMcuWaitMs(1000);
}
}
#pragma vector = URX1_VECTOR
__interrupt void UART1_ISR(void)
{
static uint8 i=0;
URX1IF = 0;
if(i < DATA_AMOUNT-1)
{
copy[i] = U1DBUF;
i++;
}
else
{
i = 0;
}
}
3.仿真调试
4.串口打印