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

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操作”。


扫描二维码关注公众号,回复: 2420378 查看本文章

这段话已经将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模式吧~

猜你喜欢

转载自blog.csdn.net/u012993936/article/details/48210293