DMA数组之间拷贝在CC2530-DMA传输(1)已经记录过了,这次主要是解决当时提到串口发送问题,现在串口发送已解决。具体代码如下,仅供参考交流。
1.Dma
1.1.bspDma.h
#ifndef __BSP_DMA_H__
#define __BSP_DMA_H__
#include "hal_types.h"// Define basic data types:
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned char UINT8;
// Define data
#pragma bitfields = reversed
typedef struct {
uint8 SRCADDRH; //源地址高字节
uint8 SRCADDRL; //源地址低字节
uint8 DESTADDRH; //目的地址高字节
uint8 DESTADDRL; //目的地址低字节
uint8 VLEN:3; //变成传输模式
uint8 LENH:5; //传输长度高字节
uint8 LENL:8; //传输长度低字节
uint8 WORDSIZE:1; //字节传输或字传输
uint8 TMODE:2; //传输模式
uint8 TRIG:5; //触发时间选择
uint8 SRCINC:2; //源地址增量方式选择
uint8 DESTINC:2; //目的地址增量方式选择
uint8 IRQMASK:1; //中断屏蔽位
uint8 M8:1; //字节传输模式时用,8或7bit传输,仅仅适合在字节传输模式下
uint8 PRIORITY:2; //优先级选择
}DMA_DESC;
#pragma bitfields = default
#define DMA_IRQ_CH0 1<<0
#define DMA_IRQ_CH1 1<<1
#define DMA_IRQ_CH2 1<<2
#define DMA_IRQ_CH3 1<<3
#define DMA_IRQ_CH4 1<<4
#define DMA_AMOUNT 4
#define DMA_CH0 1<<0
#define DMA_CH1 1<<1
#define DMA_CH2 1<<2
#define DMA_CH3 1<<3
#define DMA_CH4 1<<4
#define DMA_VLEN_USE_LEN 0x00 // Use LEN for transfer count
#define DMA_VLEN_USE_LEN1 0x01 // Transfer number of bytes commanded by LEN + 1
#define DMA_WORDSIZE_BYTE 0x00 // Transfer a byte at a time
#define DMA_WORDSIZE_WORD 0x01 // Transfer a 16-bit word at a time
#define DMA_TMODE_SINGLE 0x00 // Transfer a single byte/word after each DMA trigger 单个传输模式
#define DMA_TMODE_BLOCK 0x01 // Transfer block of data (length len) after each DMA trigger 块传输模式
#define DMA_TMODE_SINGLE_REPEATED 0x02 // Transfer single byte/word (after len transfers, rearm DMA) 重复单个传输模式
#define DMA_TMODE_BLOCK_REPEATED 0x03 // Transfer block of data (after len transfers, rearm DMA) 重复块传输模式
#define DMA_TRIG_NONE 0 // No trigger, setting DMAREQ.DMAREQx bit starts transfer 无触发
#define DMA_TRIG_URX0 0x10 /* USART0 RX complete. */
#define DMA_TRIG_UTX0 0x0F /* USART0 TX complete. */
#define DMA_TRIG_URX1 0x10 /* USART1 RX complete. */
#define DMA_TRIG_UTX1 0x11 /* USART1 TX complete. */
#define DMA_SRCINC_0 0x00 // Increment source pointer by 0 bytes/words after each transfer源地址递增0字节/字
#define DMA_SRCINC_1 0x01 // Increment source pointer by 1 bytes/words after each transfer源地址递增1字节/字
#define DMA_DESTINC_0 0x00 // Increment source pointer by 0 bytes/words after each transfer源地址递增0字节/字
#define DMA_DESTINC_1 0x01 // Increment destination pointer by 1 bytes/words after each transfer目标地址递增1字节/字
#define DMA_IRQMASK_DISABLE 0x00 // Disable interrupt generation 通道的中断屏蔽
#define DMA_IRQMASK_ENABLE 0x01 // Enable interrupt generation upon DMA channel done 通道的中断使能
#define DMA_M8_USE_8_BITS 0x00 // Use all 8 bits for transfer count 采用所有8位作为传输长度
#define DMA_M8_USE_7_BITS 0x01 // Use 7 LSB for transfer count 采用字节地7位作为传输长度
#define DMA_PRI_LOW 0x00 // Low, CPU has priority 低优先级,CPU优先
#define DMA_PRI_GUARANTEED 0x01 // Guaranteed, DMA at least every second try 保证级,DMA至少在每秒一次的尝试中优先
#define DMA_PRI_HIGH 0x02 // High, DMA has priority 高优先级,DMA优先
#define DMA_PRI_ABSOLUTE 0x03 // Highest, DMA has priority. Reserved for DMA port access.
#define ABORT 0x80 // Bit mask for DMA abort bit (DMAARM)
#define DMAARM_DMAARM0 0x01// Bit mask for DMA arm channel 0 bit (DMAARM)
#define DMAARM_DMAARM1 0x02
#define DMAREQ_DMAREQ0 0x01
#define DMAREQ_DMAREQ1 0x02
#define DMAIRQ_DMAIF0 0x01// Bit mask for DMA channel 0 interrupt flag (DMAIRQ)
#define DMAIRQ_DMAIF1 0x02
#define NOP() asm("NOP")
// Define macro for splitting 16 bits in 2 x 8 bits:
#define HIBYTE(a) (BYTE) ((WORD)(a) >> 8)
#define LOBYTE(a) (BYTE) (WORD)(a)
#define SET_WORD(regH, regL, word) \
do { \
(regH) = HIBYTE( word ); \
(regL) = LOBYTE( word ); \
} while(0)
void DMA_Transmission(uint8 channel);
void UART_DMA_TX_Init(uint8* sourceaddr, uint8 len);
void DMA_Copy_Init(uint8* sourceaddr, uint8* distanationaddr, uint8 len);
#endif
1.2.bspDma.c
#include "hal_types.h"
#include "bspDma.h"
#include "ioCC2530.h"
#include "hal_dma.h"
#include "uart.h"
DMA_DESC __xdata dmaConfig;
DMA_DESC __xdata dmaConfigTx;// DMA进入工作模式通道1
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_TX_Init(uint8* sourceaddr, uint8 len)
{
//测试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
}
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
#define FLASH_SIZE 120 //FLASH 大小为8M字节
uint16 IDTYPE = 0;//W25QXX器件ID
uint8 string[] = "uart DMA test!";
//此数据是用来复制到内存的其他区域
uint8 data[] = "W25Q64 R&W test!";
//数据长度
#define DATA_AMOUNT sizeof(data)
//用来保存复制来的数据区域
uint8 copy[DATA_AMOUNT];
//DMA_DESC __xdata dmaConfig0;
void InitClockTo32M(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
while(!(CLKCONSTA & 0x40)); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
}
void InitLed(void)
{
P2DIR |= 0x01;
P2_0 = 0;
}
void main(void)
{
InitClockTo32M();
InitLed();
UART_Init();
EA=1;
Uart_Send_String(string,sizeof(string));
//W25QXX_Init();
//IDTYPE = W25QXX_ReadID();//IDTYPE = 0xEF16
while(1)
{
//DMA通道1串口发送,数据从data放到串口缓冲区,可以通过电脑串口助手查看串口打印出来的数据
UART_DMA_TX_Init(string, sizeof(string));
/*
//DMA通道0数组拷贝测试,无源触发,数据从data复制到copy,可以通过电脑串口助手查看串口打印出来的数据
DMA_Copy_Init(data, copy, sizeof(data));
Uart_Send_String(copy,sizeof(copy));
*/
/*
//W25Q64读写测试,数据从data写入flash地址,等亮,从flash读取数据放到copy,可以通过电脑串口助手查看串口打印出来的数据
W25QXX_Write_Page(data,FLASH_SIZE,DATA_AMOUNT);//W25QXX_Read_Byte
LED = ~LED;
halMcuWaitMs(1000);
W25QXX_Read(copy,FLASH_SIZE,DATA_AMOUNT);//W25QXX_Read_Byte
Uart_Send_String(copy,sizeof(copy));
memset(copy,0,DATA_AMOUNT);
*/
LED = ~LED;
halMcuWaitMs(1000);
}
}
3. 通过电脑串口助手查看串口打印出来的数据
4.待解决
串口DMA接收