CC2530-DMA传输(1)

之前提到过在学习2530的spi模式传输,用flash芯片已经调通,但想用DMA传输数据,之前未接触DMA使用,就做一下DMA调试记录。DMA配置,数据拷贝,无源触发模式已调通,串口触发DMA待解决。下面是测试代码,仅供参考。

1.Dma配置

1.1bspDma.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(void);
void DMA_Init(void);
#endif

1.2.bspDma.c

#include "hal_types.h"
#include "bspDma.h"
#include "ioCC2530.h"
#include "hal_dma.h"
#include "uart.h"

uint8 sourcedata[] = "datacopy DMA test!";
#define datacount sizeof(sourcedata)
uint8 destdata[datacount];

DMA_DESC __xdata dmaConfig;

void DMA_Init(void)
{
  //测试DMA通道,无源触发,data数据复制到copy,测试成功,DMA传输无误
  SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourcedata);//load address of the dma source
  SET_WORD(dmaConfig.DESTADDRH, dmaConfig.DESTADDRL, &destdata);//load address of the dma distanation
  SET_WORD(dmaConfig.LENH, dmaConfig.LENL, datacount); //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所有通道进行传输
}

void DMA_Transmission(void)
{
  //DMA进入工作模式通道0
  DMAARM |= DMAARM_DMAARM0;//为了任何DMA传输能够在该通道上发生,该位必须置1,对于非重复传输模式,一旦完成传送,该位自动清0
  //一个通道准备工作(即获得配置数据)的时间需要9个系统时钟
  NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); 
  
  DMAIRQ = 0x00;              //清中断标志    
  
  //DMA通道0传送请求,即触发DMA传送
  DMAREQ |= DMAREQ_DMAREQ0;//设置为1,激活DMA通道0(与一个触发事件具有相同的效果),当DMA传输开始清除该位
  
  //等待DMA通道0传送完毕
  //for (; !(DMAIRQ & DMAIRQ_DMAIF0););//当DMA通道0传送完成,DMAIRQ:DMAIF1位置1,与上DMAIRQ_DMAIF1(0x01),取非后为0退出循环
  while(!(DMAIRQ&DMAIRQ_DMAIF0));    //等待DMA通道0传输结束
  //清除中断标志
  DMAIRQ = ~DMAIRQ_DMAIF0;  
  
  Uart_Send_String(destdata,sizeof(destdata));
}

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!";

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));
  while(1)
  {
    DMA_Init();
    DMA_Transmission();

    LED = ~LED;
    halMcuWaitMs(1000);
  }
}

3.串口初始化和发送数据。

选用串口1(p0_4 - TX, p0_5 - RX)作为数据打印口。

// uart1 
// p0_4 - TX, p0_5 - RX
// PERCFG &= ~1<<1; //bit0 = 0
// P0SEL |= (1<<4 | 1<<5); //bit4-5 = 1
//
// p1_6 p1_7
// PERCFG |= 1<<1;  //bit0 = 1
// P1SEL |= (1<<46 | 1<<7); //bit6-7 = 1
static void uart1Init(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
}

void Uart1_Send_String(uint8 *Data,uint8 len) 
{
    for(uint8 j=0; j<len; j++)
    {
        U1DBUF=*Data++;
        while(UTX1IF==0);
        UTX1IF=0;
    } 
}

4.仿真测试,串口助手接收数据

 5.待解决:DMA串口发送问题

void DMA_Init(void)
{
  SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourcedata);//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, datacount); //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;//DMA_TRIG_UTX1; DMA_TRIG_URX1;DMA_TRIG_NONE
  dmaConfig.TMODE = DMA_TMODE_BLOCK;// 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(DMA0CFGH, DMA0CFGL, &dmaConfig);
  DMAARM = ABORT;              //停止DMA所有通道进行传输  
}

void DMA_Transmission(void)
{
  //DMA进入工作模式通道0
  DMAARM |= DMAARM_DMAARM0;//为了任何DMA传输能够在该通道上发生,该位必须置1,对于非重复传输模式,一旦完成传送,该位自动清0
  //一个通道准备工作(即获得配置数据)的时间需要9个系统时钟
  NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP(); 
  
  DMAIRQ = 0x00;              //清中断标志    
  
  //DMA通道0传送请求,即触发DMA传送
  DMAREQ |= DMAREQ_DMAREQ0;//设置为1,激活DMA通道0(与一个触发事件具有相同的效果),当DMA传输开始清除该位
  
  //等待DMA通道0传送完毕
  //for (; !(DMAIRQ & DMAIRQ_DMAIF0););//当DMA通道0传送完成,DMAIRQ:DMAIF1位置1,与上DMAIRQ_DMAIF1(0x01),取非后为0退出循环
  while(!(DMAIRQ&DMAIRQ_DMAIF0));    //等待DMA通道0传输结束
  //清除中断标志
  DMAIRQ = ~DMAIRQ_DMAIF0;  
  
  //Uart_Send_String(destdata,sizeof(destdata));
  
}

void DMA_Init(void)里更改配置,目的地址为串口1数据缓冲区,传输过程中目的地址不变

void DMA_Transmission(void)里屏蔽串口发送

即://Uart_Send_String(destdata,sizeof(destdata));

启动通道传输,每次只能传输第一个字节,后面全是00.

若void DMA_Init(void)里更改配置,目的地址为串口1数据缓冲区,传输过程中目的地址+1

则什么都不传输。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值