CC2530无线RF,串口透传

1.前言

本文将分析一个利用CC2530实现无线串口,文中将会列举部分代码并对CC2530的具体操作进行分析。本文的具体的内容包括以下几个部分:

  • CC2530是符合802.15.4标准的无线收发芯片,但是本文并没有遵守802.15.4协议规则,在发送过程中忽略了网络ID、源地址和目标地址等参数,在接收的过程中禁止了帧过滤。通过发送和接收过程的处理使得CC2530无线部分的使用尽可能的简单清晰,通过最少的代码说明问题。
  • 无线芯片的调试具有一定的难度,一般存在发送设备和接收设备。为了通过最简单的代码说明无线芯片的使用,本文中仅编写一种设备代码同时实现发送和接收功能。设备的功能也相对简单,CC2530从串口接收数据并把数据通过RF部分“无损”发送,于此同时CC2530把从RF部分接收的数据通过串口“无损”发送,通过这样的方式实现无线串口。
  •  串口数据属于“流”型数据包,RF部分属于“帧”型数据包。在串口数据处理与分析中,一般采用特定的串口头和长度的方式解析数据,但是本文采用通过串口时间间隔的方式接收数据,这种方法等同于modbus-RTU串口数据处理方法。通过这种检测字节数据时间间隔的方法使得CC2530的串口部分可以接收无特殊格式要求的数据,真正实现无线串口功能。

1.1实验准备

为了实现无线串口功能,需要准备两套CC2530模块和一个仿真器。如果条件允许可以增加一个仿真器,仿真器可以是CC Debugger也可以是SmartRF04EB,同时也可以准备一套CC2531 USBDongle做为嗅探器,抓取RF发送数据做调试分析。

1.2 实验结果

本文主要实现了无线串口功能,通过串口调试助手发送字节数据。例如通过串口向设备A发送Hello CC2530,设备B可收到Hello CC2530,并把该字符串通过串口调试助手打印至屏幕。设备B发送Hello RF,设备A同样可以收到数据并打印至屏幕。

图1.2.1(a-b) 设备A和设备B串口调试界面

      图中中括号包含的数字为RSSI结果,RSSI表示接收信号强度,例如图中的-28。RSSI结果的单位为dBm,dBm为绝对单位且参考的标准为1mW。

2.代码

RF部分的寄存器较多,需要耐心阅读数据手册和相关工具才可以完成设置。虽然RF部分的寄存器较多,但是还是借助smartRF工具、数据手册和示例代码,依然可以总结出使用CC2530无线部分的一般方法。

初始化部分包括接收数据包帧过滤控制,发射功率控制和信道选择;借助smartRF工具生成若干推荐值;打开接收终端并进入接收状态。

2.1 主函数

void main(void)
{
  P1SEL &= ~0x13; //功能:通用I/O,默认为通用I/O  P1.0 P1.1 P1.4设置为通用IO
  P1DIR |= 0x13; //方向:输出   P1.0 P1.1 P1.4设置为输出
  
//  P1DIR |= ( 1<< 4) | (1<<1);

  TX =0;
  RX =1;
  EA = 0;                                     // 暂时关闭全局中断
  SLEEPCMD &= ~0x04;                       
  while( !(SLEEPSTA & 0x40) );
  CLKCONCMD &= ~0x47;     // 设置系统时钟为32MHz
  SLEEPCMD |= 0x04; 
      
  WDCTL = 0x00;     //将超时时间设置为1s,在IDLE模式写CLR寄存器不会产生影响,因此直接赋值只会改变INT和MODE。
  WDCTL |= 0x08;    //将看门狗定时器设置为看门狗模式
  
  uart0_init();                                // 38400
  timer1_init();                              
  timer3_init();                               // 1s
  rf_init();                                   // RF
  
  EA = 1;                                      
  LED1 = 1;  
  uart0_sendbuf("20181025",8);    
  delay(1000);
  uart0_sendbuf(serial_rxbuf,4);

  while(1) 
  {
    WDCTL = 0xa0;     //在看门狗模式写INT寄存器和MODE模式不会产生影响,因此直接赋值只会改变CLR
    WDCTL = 0x50;

    rx();
    if(Time_1s > 900)//超过十五分钟未接收到数据,重新初始化串口及RF
    {
      Time_1s = 0;
      //uart0_init();                                //38400
      rf_init();   
    }
//   tx();
//   uart0_sendbuf(serial_rxbuf,4);
    delay(10);
  }
}

分析:

初始化IO口,设置为通用IO、输出模式,分别为LED灯、PA、LNA。

初始化看门狗,做产品并非做实验,软件开门狗必须使用,以防死机。

初始化串口,定时器1,定时器3,RF。定时器1用于串口接收,定时器3用于计时。

whilexu循环中实时监测是否接收到串口数据,收到则立即RF发送。以及判断shif是否连续15分钟内都没接收到RF数据,若无则重新初始化RF。(此机制是因为长时间射频收发,会出现各种干扰导致接收不到RF数据,但可正常发射,程序正常运行。15分钟为实际项目需求,根据实际情况选择。

2.2 RF发送及接收

void rf_send( char *pbuf , int len)
{
  int i=0;
  RFST = 0xE3;                      // RF接收使能 ISRXON 
  // 等待发送状态不活跃 并且 没有接收到SFD
  while( FSMSTAT1 & (( 1<<1 ) | ( 1<<5 ))); 
  
  RFIRQM0 &= ~(1<<6);               // 禁止接收数据包中斿  
  IEN2 &= ~(1<<0);                  // 清除RF全局中断

  RFST = 0xEE;                      // 清除发送缓冲区 ISFLUSHTX
  RFIRQF1 = ~(1<<1);                // 清除发送完成标忿
  // 填充缓冲匿填充过程需要增势字节,CRC校验自动填充
  RFD = len + 2;        
  for (int i = 0; i < len; i++) 
  {
    RFD = *pbuf++;
  }

  RFST = 0xE9;                      // 发送数据包 ISTXON
  while (!(RFIRQF1 & (1<<1))) // 等待发送完房  RFIRQF1 = ~(1<<1);                // 清除发送完成标志位
  {
   i++;
   if( i > 50 )//增加退出机制,受干扰会死在此循环中
   {
      i=0;
      break;
   }  
   WDCTL = 0xa0;     //在看门狗模式写INT寄存器和MODE模式不会产生影响,因此直接赋值只会改变CLR
   WDCTL = 0x50;
   delay(100);
  }
       
  
  RFIRQM0 |= (1<<6);                // RX接收中断
  IEN2 |= (1<<0); 
}

分析:

除主函数中while的死循环,其他任何地方的while死循环都要特别注意,比如此处实际调试中发现会程序卡死在等待发送完成,因此增加了退出机制。然而退出机制的时间判断亦不可随意设置,过短会导致每次传输数据长度收限制。本人因对程序时间概念不重视,导致此bug困惑许久。实测此延时时间至少可发送100个数据。

void rf_receive_isr()
{
  int rf_rx_len = 0;
  int rssi = 0;
  char crc_ok = 0;

  rf_rx_len = RFD - 2;                        //长度去除两字节附加结果
  rf_rx_len &= 0x7F;
  for (int i = 0; i < rf_rx_len; i++)
  {
    rf_rx_buf[i] = RFD;                      //连续读取接收缓冲区内容
  }
  
  rssi = RFD - 73;                             //读取RSSI结果
  crc_ok = RFD;                              //读取CRC校验结果 BIT7
 
  RFST = 0xED;                                 //清除接收缓冲区
  if( crc_ok & 0x80 )
  {
    LED1 ^= 1; 
    Time_1s = 0;
    uart0_sendbuf( rf_rx_buf , rf_rx_len);    
    comtx(rssi );
  }
  else
  {
    uart0_sendbuf("\r\nCRC Error\r\n",12);
  }
}

分析: 

RF接收函数,接收到的数据自带两位硬件CRC校验,即crc_ok。校验通过认为是有效数据,将计时清零,LED灯反转,串口发送出接收到的数据,并发送出rssi。

3.备注

PA:功率放大器                     发射前置高电平,发射结束立即置低电平。

LNA: 低噪声放大器                发射前置低电平,发射结束立即置高电平。

(不可操作失误,否则导致数据接收异常)

猜你喜欢

转载自blog.csdn.net/qq_27747359/article/details/83660486