【ZIGBEE(CC2530)学习】11-CC2530基础实验——DMA传输配置


在这里插入图片描述

一、实验介绍

  直接存取访问(DMA)控制器可以用来减轻8051CPU内核传送数据操作的负担,从而实现在高效利用电源的条件下的高性能。只需要 CPU 极少的干预,DMA 控制器就可以将数据从诸如 ADC 或 RF 收发器的外设单 元传送到存储器。
  DMA 控制器协调所有的 DMA 传送,确保DMA 请求和 CPU 存储器访问之间按照优先等级协调、合理地 进行。DMA控制器含有若干可编程的DMA通道,用来实现存储器-存储器的数据传送。
  DMA 控制器控制整个 XDATA 存储空间的数据传送。由于大多数SFR寄存器映射到 DMA存储器空间,这些灵活的DMA通道的操作能够以创新的方式减轻CPU的负担,例如,从存储器传送数据到USART,或定期在ADC和存储器之间传送数据样本等等。使用 DMA 还可以保持CPU在低功耗模式下与外设单元之间传送数据,不需要唤醒,这就降低了整个系统的功耗。

  1. 5 个独立的 DMA 通道;
  2. 3 个可以配置的 DMA 通道优先级;
  3. 32 个可以配置的传送触发事件;
  4. 源地址和目标地址的独立控制;
  5. 单独传送、数据块传送和重复传送模式;
  6. 支持传输数据的长域域,设置可变传输长度。

  既可以工作在字模式,又可以工作在字节模式。

二、实验目的

  1. 通过本实验了解CC2530 的DMA相关寄存器的配置;
  2. 通过本实验了解CC2530的DMA功能的运用及操作。

三、实验设备

3.1、硬件设备

  1. ZIGBEE开发板
  2. SmartRF04EB仿真器
  3. Micro-USB线

3.2、软件环境

  1. IAR Embedded Workbench for 8051集成开发环境
  2. 串口调试助手

四、实验原理

4.1、DMA操作

  DMA 控制器有5个通道,即DMA通道0到通道4。每个DMA通道能够从DMA 存储器空间的一个位置传送数据到另一个位置。
  当DMA 通道配置完毕后,在允许任何传输发起之前,必须进入工作状态。DMA通道通过将DMA 通道工作状态寄存器DMAARM 中指定位置1,就可以进入工作状态。
  一旦DMA 通道进入工作状态,当配置的DMA 触发事件发生时,传送就开始了。DMAREQ 位只能在相应的DMA 传输发生时清除。当通道解除准备工作状态时,DMAREQ 位不被清除。

4.2、DMA配置参数

4.2.1、源地址

  DMA通道开始读的数据地址。

4.2.2、目标地址

  DMA通道从源地址读出要写的数据首地址。

4.2.3、传送数量/数据长度

  DMA传送完成之前必须传送的字节或字的个数。

4.2.4、VLEN设置/传送长度

  DMA通道可以利用源数据中的第一个字节或字作为传送长度。
  在任何情况下,都设置传送长度为传送的最大长度LEN。若首字节或字指明的传输最大长度大于LEN,那么LEN个字节或字将被传送。
  当设置为可变长度传输,LEN应设置为允许传输的最大长度加一。

4.2.5、触发事件

  设置每个DMA通道接受单个事件的触发。

4.2.6、源和目标增量

  当DMA通道进入工作状态胡总和重新进入工作状态时,源地址和目标地址传送到内部地址指针。
  增量为0,每次传送后地址指针将保持不变。
  增量为1,每次传送后地址指针将加上1个数。
  增量为2,每次传送后地址指针将加上2个数。
  减量为1,每次传送后地址指针将减去1个数。
  在字节模式下,1个数等于一个字节;在字模式下,1个数等于2个字节。

4.2.7、传送模式

  指定DMA通道开始传输时如何工作。
  单一模式:触发时发生一个DMA传送并等待下一次触发,完成指定长度后传送结束,通报CPU解除DMA通道的工作状态。
  块模式:触发时按照传送长度传送DMA传送,通报CPU解除DMA通道的工作状态。
  重复的单一模式:触发时发生一个DMA传送并等待下一次触发,完成指定长度后传送结束,通报CPU重新进入DMA通道的工作状态。
  重复的块模式:触发时按照传送长度传送DMA传送,报CPU重新进入DMA通道的工作状态。

4.2.8、优先级

  DMA优先级对每个DMA通道是可以配置的,分为高级、一般级、低级。

4.2.9、字节或字传送/单次传送长度

  判断已完成的传送是8位还是16位。

4.2.10、中断屏蔽

  在完成DMA传送的基础上,该通道能够产生一个中断到CPU,该位可以屏蔽中断。

4.2.11、模式8设置

  决定采用7位还是8位的字节来传送数据,仅适用于字节传送。

4.3、DMA配置安装

  定义结构体。DMA通道参数必须在DMA通道进入工作状态之前配置并激活,通过写入特殊的DMA配置数据结构中配置。
在这里插入图片描述

在这里插入图片描述

  将结构体首地址分别写入DMA0CFGH和DMA0CFGL。

4.4、相关寄存器

  DMAARM寄存器用于启动DMA通道。
在这里插入图片描述
  DMAREG寄存器用于开启DMA通道请求。
在这里插入图片描述

  DMAIRG寄存器用来判断DMA传送是否完成。
在这里插入图片描述
  DMA0CFGH/L寄存器用于存放DMA通道0配置地址。
在这里插入图片描述

五、实验演示

  现在我们要进行DMA配置并传送数据,实现串口输出对应字符。
  首先是分别创建dma.c和dma.h文件,在dma.h文件内定义结构体:

#pragma bitfields=reversed
typedef struct
{
    uint8_t SRCADDRH;					//源地址高8位
    uint8_t SRCADDRL;					//源地址低8位
    uint8_t DESTADDRH;					//目的地址高8位
    uint8_t DESTADDRL;					//目的地址低8位
    uint8_t VLEN			:3;			//可变长度传输模式
    uint8_t LENH			:5;			//传送长度高5位
    uint8_t LENL			:8;			//传送长度低8位
    uint8_t WORDSIZE		:1;			//8位或16位传送,字节或字传送
    uint8_t TMODE			:2;			//传送模式选择
    uint8_t TRIG			:5;			//触发事件选择
    uint8_t SRCINC			:2;			//源地址增量 -1/0/1/2
    uint8_t DESTINC			:2;			//目标地址增量 -1/0/1/2
    uint8_t IRQMASK			:1;			//中断屏蔽
    uint8_t M8				:1;			//8位传输长度
    uint8_t PRIORITY		:2; 		//优先级别
}DMA_DESC;
#pragma bitfields=default

  接着在dma.c文件内初始化DMA:

#include "headfile.h"

char srcbuf[] = "Hello World\n";                                //源数组
char destbuf[sizeof(srcbuf)];                                   //目标数组

void dma_init(void)
{
    DMA_DESC dmaconfig;
    dmaconfig.SRCADDRH = (uint8_t)((uint16_t)&srcbuf >>8)	;	//配置源地址
    dmaconfig.SRCADDRL = (uint8_t)((uint16_t)&srcbuf & 0xFF);	//&0xFF的作用是防止警告
    dmaconfig.DESTADDRH = (uint8_t)((uint16_t)&destbuf >>8);	//配置目标地址
    dmaconfig.DESTADDRL = (uint8_t)((uint16_t)&destbuf & 0xFF);
    dmaconfig.VLEN = 0x00;										//LEN为传送长度
    dmaconfig.LENH = (uint8_t)((uint16_t)sizeof(srcbuf) >>8);	//配置传输长度
    dmaconfig.LENL = (uint8_t)((uint16_t)sizeof(srcbuf));
    dmaconfig.WORDSIZE = 0x00;									//字节传送
    dmaconfig.TMODE = 0x01;										//块传送模式
    dmaconfig.TRIG = 0;											//手动触发
    dmaconfig.SRCINC = 0x01;									//源地址增量为1
    dmaconfig.DESTINC = 0x01;									//目标地址增量为1
    dmaconfig.IRQMASK = 0;										//中断屏蔽
    dmaconfig.M8 = 0x00;										//8为字节传送数据
    dmaconfig.PRIORITY = 0x02;									//高优先级
    DMA0CFGH = (uint8_t)((uint16_t)&dmaconfig >>8);				//将配置结构体的首地址赋予相关SFR
    DMA0CFGL = (uint8_t)((uint16_t)&dmaconfig & 0xFF);
}

  在dma.h文件内要加入以下两行代码,用于声明源数组和目标数组为外部数组,方便在main.c内使用:

extern char srcbuf[20];
extern char destbuf[sizeof(srcbuf)];

  接着在main.c内输入以下:

#include "iocc2530.h"                     //头文件
#include "headfile.h"

char buf[20];
void main(void)
{
    clk32m_init();
    uart0_init();
    dma_init();
    DMAARM = 0x01;									//启动DMA通道0
    DMAIRQ = 0x00;									//清除所有中断标志位
    DMAREQ = 0x01;									//DMA通道0传送请求
    while((DMAIRQ & 0x01) == 0);					//等待DMA通道0传送完成
    sprintf(buf,"finish\r\n");
    uartsendstring(buf,sizeof(buf));				//传送完成串口输出
    uartsendstring(destbuf,sizeof(destbuf));		//检测是否传输完成
    while(1);
}

  接上Micro-USB线并打开串口调试助手,当上电时将输出以下结果:
在这里插入图片描述
  有疑问可以加入QQ群交流:324611467

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值