您的位置:首页 > 其它

Zigbee协议栈内核分析 – 串口分析

2015-09-04 16:44 204 查看

Zigbee协议栈内核分析– 串口分析

在 Z-Stack里面,USART有两种配置方式,一种是DMA模式,另一种是ISR模式。那么首先让我们先来看看 DMA模式是什么样子的吧。

想要了解Z-Stack的USART DMA传输模式,首先我们得先知道裸机是怎么配置USART用DMA模式传输的。

为了了解USART是怎么用DMA模式传输数据的,我们来做一个简单的实验:

用USART0接收电脑发来的数据并存储到一个数组缓存区中,然后通过DMA通道直接从这块缓存区中提取数据到USART0的U0DBUF,将数据显示到电脑的串口调试助手。

首先我们得先把USART0调试的能收发,这个很简单吧。

USART0.c
/*   配置串口0波特率为115200,接收中断使能,数据位:8,停止位:1,校验位:无   */
static voidConfig_Clock(void)
{
CLKCONCMD &= ~0x40;                   // 设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40);                      // 等待晶振稳定
CLKCONCMD &= ~0x47;                          // 设置系统主时钟频率为 32MHZ
}

static voidConfig_Usart0_GPIO(void)
{
//USART0:P0_3:TX ; P0_2:RX ; 备用位置1
PERCFG &= ~(1<<0);      //USART0 备用位置1
P0SEL |= 0X3C;           //设置P0_2\P0_3\P0_4\P0_5为外设功能
P0DIR |= (1<<3);         //设置P0_3为输出
P2DIR &= ~0XC0;        //设置第一优先级为USART0
}

static voidConfig_Usart0(void)
{
U0CSR |= (1<<7);     //设置为UART模式
U0UCR |= (1<<7);     //清除单元
//设置波特率:115200,BAUD_M=216;BAUD_E=11
U0GCR &= ~0X1F;
U0GCR |= 11;
U0BAUD = 216;
//使能接收器
U0CSR |= (1<<6);
//中断使能
IEN0 |= 0X84;         //USART0RX中断使能
}

voidInit_Usart0(void)
{
Config_Clock();
Config_Usart0_GPIO();
Config_Usart0();
Config_Usart0DMA();
}


好了,到此串口0的初始化配置已经写完了,接下来该写DMA的配置了。

我们先看看CC2530的数据手册的“8.1 DMA操作”。



这段话已经将DMA初始化配置的过程说的十分的详尽了,我给大家大概的总结一下:

一、 配置DMA通道(配置一个固定的结构体)

二、 加载DMA通道配置(将结构体的地址赋给某寄存器就算是加载配置了!)

三、 在传输发起之前DMA通道要进入工作状态(将DMAARM.DMAARM0置1)

四、 当配置的DMA触发事件发生,DMA传送就开始了(当DMA触发源触发的时候即开始传送)

接下来按照上面总结的步骤写出DMA初始化配置。

USART0.c
static voidConfig_Usart0DMA(void)
{
/*配置DMA通道0:
1.以串口接收到的数据缓存区作为源地址
2. 以 USART0 U0DBUF 缓冲区作为目标地址
3. 设置传送长度为10bit
4. 设置为采用LEN作为传送长度
5. 配置USART0接收完成为触发事件
6.源地址内部指针设置增量为1,目标地址内部指针设置增量为0
7. 设置传输模式为单一模式
8. 设置优先级为高级,DMA优先
9. 设置为字传输
10. DMA通道中断使能
11. 设置为8位字节传输数据
*/
HAL_DMA_SET_SOURCE(USART0DMA, revbuf);                    //设置源地址,以串口接收到的数据缓存区作为源地址
HAL_DMA_SET_DEST(USART0DMA, DMA_U0BUF);               //设置目标地址,以 USART0 U0DBUF 缓冲区作为目标地址
HAL_DMA_SET_LEN(USART0DMA, LEN);                             //设置传送长度为10bit
HAL_DMA_SET_VLEN(USART0DMA,HAL_DMA_VLEN_USE_LEN);       //设置为采用LEN作为传送长度
HAL_DMA_SET_TRIG_SRC(USART0DMA, DMATRIG_RX);                  //配置USART0接收完成为触发事件
HAL_DMA_SET_SRC_INC(USART0DMA,HAL_DMA_SRCINC_1);         //设置增量为1
HAL_DMA_SET_DST_INC(USART0DMA,HAL_DMA_SRCINC_0);         //设置增量为0
HAL_DMA_SET_TRIG_MODE(USART0DMA,HAL_DMA_TMODE_SINGLE );           //设置传输模式为单一模式
HAL_DMA_SET_PRIORITY(USART0DMA,HAL_DMA_PRI_HIGH );                    //设置优先级为高级,DMA优先
HAL_DMA_SET_WORD_SIZE(USART0DMA,HAL_DMA_WORDSIZE_BYTE );          //设置为字传输
HAL_DMA_SET_IRQ(USART0DMA,HAL_DMA_IRQMASK_ENABLE );                       //DMA通道中断使能
HAL_DMA_SET_M8(USART0DMA,HAL_DMA_M8_USE_8_BITS );                     //设置为8位字节传输数据
//加载DMA通道配置
HAL_DMA_SET_ADDR_DESC0(&USART0DMA);
//DMA启动配置
DMAARM |= (1<<0);
//清除DMA通道0中断标志
DMAIRQ &= (1<<0);
}


到此为止,DMA的配置就全部结束啦~上面的那些配置用的函数都是我从协议栈里面复制过来的,这样就不用自己一位一位的去填充寄存器配置了。

最后我们来看一下主函数写了什么。

main.c
#include<iocc2530.h>
#include"usart0.h"

uint8_trevbuf[10] = {0};
static uint8_tflag;

void main(void)
{
//初始化串口0
Init_Usart0();

while(1)
{
//当到达DMA传输长度LEN的时候需重新加载DMA配置
if(flag)
{
flag = 0;
//DMA启动配置
DMAARM |= (1<<0);
//清除DMA通道0中断标志
DMAIRQ &= (1<<0);
}
}
}

#pragma vector =URX0_VECTOR
__interrupt voidUARST0_ISR(void)
{
static uint8_t count = 0;
revbuf[count++] = U0DBUF;
if(count>=10)
{
flag = 1;
count = 0;
}
}


运行结果分析:



1、发送字符串“123456”到CC2530,CC2530回复的是6个0。



2、第二次发送字符串“123456”到CC2530,CC2530回复的是字符串“000012”。



3、第三次发送字符串“123456”到CC2530,CC2530回复的是字符串“345612”。

从上面的运行结果我们可以看出,当第一次发送字符串“123456”的时候,CC2530先接收到字符‘1’,然后USART0接收完成,触发DMA传输,DMA将当前接收缓冲区的rxbuf[0]到U0DBUF,然后源目标地址指针加1,所以串口调试助手收到的就是字符‘0’啦~后面同理可得。

直到DMA发送到了LEN个数据的时候,我们设置的LEN是10,也就是10个数据的时候,DMA通道就会退出工作状态,而此时,DMA已经将rxbuf接收缓冲数组里面的所有数值都发送出去了,也就是“0000000000”,此时我们就需要再重新加载DMA通道配置,然后再通过串口调试助手发送数值的时候,DMA就会将之前我们发送过去的数值显示出来啦~

完整代码已上传,读者自己可下载验证:http://download.csdn.net/detail/u012993936/9078185

以上就是USART DMA模式裸机情况下的作用流程,大家先熟悉熟悉,然后我们就去看协议栈里面的USART DMA模式吧~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: