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模式吧~
相关文章推荐
- Mayor's posters(线段树+离散化POJ2528)
- win8右下角的输入法宽度变化的问题
- 合并多个DataTable及将DataTable添加到DataSet的方法
- 【英语】Bingo口语笔记(65) - 我也是系列
- 安装wget
- Mayor's posters(线段树+离散化POJ2528)
- [HDOJ5360]Hiking
- Struts2 part6:数据校验
- Linux之grub的运行机制及grub修复
- C++基础---无返回值函数(void函数)
- 家里接双线方法,带宽和网速都提高
- 网线接错,也可以上网,老断线
- 我是懒人
- usaco Longest Prefix
- Wget下载终极用法和15个详细的例子
- Largest Number —— Leetcode(sort的妙用)
- [网络流24题] 21 最长k可重区间集(最大权不相交路径 ,最小费用最大流)
- 28. 原型
- VMware CentOS Device eth0 does not seem to be present
- io心得