高性能射频收发器CC1101

高性能射频收发器CC1101

简介:

CC1101是一款低于1GHz高性能射频收发器,设计旨在用于极低功耗RF应用。其主要针对工业、科研和医疗(ISM)以及短距离无线通信设备(SRD)。CC1101可提供对数据包处理、数据缓冲、突发传输、接收信号强度指示(RSSI)、空闲信道评估(CCA)、链路质量指示以及无线唤醒(WOR)的广泛硬件支持。CC1101在代码、封装和外引脚方面均与CC1100兼容,可用于全球最为常用的开放式低于1GHz频率的RF设计。

 

详细介绍:

1.  数据包格式:可以对数据包格式进行配置,其由如下各项组成:前导;同步字;可选长度字节;可选地址字节;有效负载;可选 2 字节 CRC。

 

 

2.  接收模式下的数据包滤波
CC1100E 支持三种不同类型的数据包滤波:地址滤波,最大长度滤波,CRC 滤波。


2.1 地址滤波:
设置 PKTCTRL1.ADR_CHK 为 0 以外的任何值便可开启数据包地址滤波器。该包处理器引擎会将数据包中的目标地址字节与 ADDR 寄存器中的编程节点地址, 以及 PKTCTRL1.ADR_CHK=10 时的 0x00 广播地址或者PKTCTRL1.ADR_CHK=11 时的 0x00 和0Xff 广播地址进行比较。如果接收到的地址匹配一个有效地址,则接收该数据包,并将其写入 RX FIFO。如果地址匹配失败, 则丢弃该数据包, 并重新启动接收模式( 与MCSM1.RXOFF_MODE 设置无关)。当使用无限数据包长度模式并且地址滤波开启时,如果接收到的地址匹配一个有效地址,那么 0xFF 便会被写入 RX FIFO,之后是地址字节,最后是有效负载数据。

2.2 最大长度滤波
在 可 变 数 据 包 长 度 模 式 下 , 即 PKTCTRL0.LENGTH_CONFIG=1 ,PKTLEN.PACKET_LENGTH 寄存器值用于设置最大允许的数据包长度。如果接收到的长度字节具有一个比该允许的长度更大值,则丢弃该数据包,并且重新启动接收模式(与 MCSM1.RXOFF_MODE 设置无关)。

2.3 CRC 滤波
如果 CRC 校验失败,则设置 PKTCTRL1.CRC_AUTOFLUSH=1 来开启数据包滤波。如果 CRC 校验失败,CRC 自动刷新功能将会刷新整个 RX FIFO。自动刷新 RX FIFO 以后,后面的状态则取决于 MCSM1.RXOFF_MODE 的设置。请注意, 开启PKTCTRL1.APPEND_STATUS 之后,最大允许的数据包长度减小 2 字节,目的是在 RX FIFO 中为数据包末尾添加的 2 个状态字节留出空间。由于 CRC校验失败时整个 RX FIFO 被刷新,之前接收到的数据包必须在接收当前数据包以前从 FIFO 读取出来。在 CRC 校验为 OK 以前,MCU 不能读取当前数据包。

 

3.  发送模式下的数据包处理
必须要将即将要被发送的有效负载写入 TX FIFO 中。开启可变数据包长度以后,长度字节必须最先被写入。长度字节具有一个与数据包有效负载相当的值(包括可选地址字节)。如果接收机端开启了地址识别,则写入 TX FIFO 的第二个字节必须为地址字节。如果开启了固定数据包长度,则写入 TX FIFO 的第一个字节应为地址字节(假设接收机使用了地址识别)。

 

 

设计:

1.  本程序运行平台为MSP430 5438:

(1)采用SPI通信方式实现单片机与CC1101之间的通信;

(2)CC1101采用可变长度+地址滤波+CRC校验滤波模式,收发功能均待命;

(3)程序以高精度气压传感器MS5611的测量数据进行传输。

 

2.  为了充分适配单片机的性能,使用了以下方法:

(1)从气压传感器得到的数据仍需经过后续计算才能得到海拔值,但由于传感节点MSP430性能有限,因此决定将大部分后续计算转移至汇聚节点(ARM)中进行计算:速度快、并且传感节点也能尽可能省电;

(2)由于单片机电量限制,CC1101必须尽量省电,同时也为了尽可能减少丢包率,数据包应当尽可能小。因此,将气压传感器测量得到的经过部分处理后得到的气压值(浮点数)以其在内存中的存储形式(计算机组成原理)进行      发送,以尽可能减小数据包长度;

(3)由于CC1101接收数据和发送数据需要利用中断来处理,并且MSP430不支持多级中断,为了及时响应后续任务,中断函数中的语句应当尽可能少。为此,添加全局变量标识符,在中断中将标识符置位后,退出中断而在主函数中执行所需任务。

 

3.  所得经验和教训:

(1)若CC1101需要切换模式,则必须先切换至SIDLE(空闲)模式后才能进行切换!

 

    /*-----------退出任何状态或者进入任何状态前先行进行idle状态!*-----------*/
    SPI_B2_Strobe(CCxxx0_SIDLE);
    /*-----------退出任何状态或者进入任何状态前先行进行idle状态!*-----------*/

 

(2)当将发送任务不是在中断函数中实现,而是在主函数中实现时,CC1101的GDO0将会被置位,此时将会产生莫名的中断!因此必须在进入发送状态和完成发送时关闭总中断,并且将GDO0中断标志位清零!

    _DINT();  
    SPI_B2_Strobe(CCxxx0_STX);        // 进入发射状态
    while(!(P1IN& GDO0));             // 等待GDO0置高,置高表示数据报头已经发送
    while(P1IN& GDO0);                // 等待GDO0置低,置低表示数据报已经发送完成
    P1IFG &=~ GDO0; 
    _EINT();

 

 

例程:

1.  系统初始化函数

/*
*@Function name:Init_CLK
*@Descriptions: 初始化系统时钟和看门狗模块
                ——MCLK=SMCLK=XT2/2=8M;
                ——看门狗为INTERVAL模式,中断间隔为250ms
*@Parameters:   NONE
*@Returned Value:NONE
*@Others:       NONE
*/
void Init_CLK(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
  WDTCTL = WDT_ADLY_250;
  SFRIE1|= WDTIE;
  
  P5SEL |= 0x0C; // Port select XT2
  P7SEL |= 0x03;
  UCSCTL6 &= ~XT2OFF; // Enable XT2 even if not used
  UCSCTL6 &= ~XT1OFF;   
  UCSCTL6 |= XCAP_3; 
  do
  {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);// Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
   }while (SFRIFG1&OFIFG); // Test oscillator fault flag
  UCSCTL4 |= SELS_5 + SELM_5 + SELA_0; // SMCLK=MCLK=XT2-16M,ACLK=XT1
  UCSCTL5 |= DIVM__2 + DIVS__2+DIVA__2; //主系统时钟2分频-8M;子系统时钟2分频-8M
}

 

 

2.  SPI端口初始化:

/*---------------------SPI B2相关函数-----------------------------*/
void Init_SPI_B2(void)
{  
    P9SEL |= 0x0E; // P9.1-3 SPI option select  
    UCB2CTL1 |= UCSWRST; // 复位SPI状态机
    UCB2CTL1 |= UCSSEL__SMCLK; // 选择SCK参考源为SMCLK
    UCB2CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB; // 3-pin, 8-bit SPI master, Clock polarity high, MSB
    UCB2CTL0 &=~UCCKPL;   
    UCB2BR0 = 0x02;
    UCB2BR1 = 0x00;
    UCB2CTL1 &= ~UCSWRST; // 复位SPI状态机
    P9DIR|=BIT5;
    P9OUT|=BIT5;
}

unsigned char SPI_B2_Send_byte(unsigned char byte)
{        
    while((UCB2IFG&UCTXIFG)==0);
        UCB2TXBUF=byte;
    while((UCB2IFG&UCRXIFG)==0);
    return(UCB2RXBUF);
}

unsigned char SPI_B2_Receive_byte(void)
{    
     return SPI_B2_Send_byte(0);

}

void SPI_B2_WriteReg(unsigned char addr, unsigned char value)
{
    CC1101_Enable;                       //CS=0 CS enable       
    Wait_cc();                     // Wait for CCxxxx ready
    SPI_B2_Send_byte(addr);                  // Send address
    SPI_B2_Send_byte(value);                 // Send data
    CC1101_Disable; 
}

unsigned char SPI_B2_Read(unsigned char addr)
{
    unsigned char rTemp;
    CC1101_Enable;                   // CS=0 CS enabl
    Wait_cc();
    SPI_B2_Send_byte(addr | CCxxx0_READ_SINGLE);    // Send address
    rTemp = SPI_B2_Receive_byte();  
    CC1101_Disable;                      // CS=1 CS disable
    return ( rTemp );           

}

void SPI_B2_WriteBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count)
{
   unsigned char i;
   CC1101_Enable;                        //CS=0 CS enable
   Wait_cc();                             // Wait for CCxxxx ready 
   SPI_B2_Send_byte(addr | CCxxx0_WRITE_BURST);// Send address
   for (i = 0; i < count; i++)
   {
       SPI_B2_Send_byte(buffer[i]);        // Send data
   }
   CC1101_Disable;                     //CS=1 CS disable
}  

void SPI_B2_ReadBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count)
{
    unsigned char i;
    CC1101_Enable;                          // CS=0 CS enable
    Wait_cc();                              // Wait for CCxxxx ready
    SPI_B2_Send_byte(addr | CCxxx0_READ_BURST); // Send address
    for (i = 0; i < count; i++)
    {
        buffer[i] = SPI_B2_Receive_byte();      // Read data
    }
    CC1101_Disable;                       //CS=1 CS disable
}

void SPI_B2_Strobe(unsigned char strobe)
{
     CC1101_Enable;                       //CS=0 CS enable
     Wait_cc();                             // Wait for CCxxxx ready
     SPI_B2_Send_byte(strobe);      // Send strobe
     CC1101_Disable;
}

/*---------------------SPI B2相关函数-----------------------------*/

 

3.  CC1101初始化:

/*
*@Function name:Init_1101
*@Descriptions: 初始化CC1101,接收终端使能,上电重启,初始化各寄存器
                进入信道为RxChannel=33的接收模式
*@Parameters:   NONE
*@Returned Value:NONE
*@Others:       NONE
*/
void Init_1101()
{
    Init_SPI_B2(); 
    P1DIR&=~GDO0;
    P1OUT|=GDO0;
    P1REN|=GDO0;
    P1IES |= GDO0;                       //使能GDO0中断发生在下降沿
    P1IFG = 0x00;                        //中断寄存器清零
    P1IE |= GDO0;                        //中断使能    
    P1IFG=0;    
    
    PowerupResetCCxxxx();     
    writeRFSettings();
    SPI_B2_Strobe(CCxxx0_SIDLE);                //cc1101退出SWOR,唤醒
    SPI_B2_WriteReg(CCxxx0_PATABLE, PA_VALE); 
    SPI_B2_WriteReg(CCxxx0_CHANNR,RxChannel);
    SPI_B2_Strobe(CCxxx0_SFRX);              //复位SWORr5
    SPI_B2_Strobe(CCxxx0_SRX);
}

 

 4.  主函数

/*
*@Function name:main
*@Descriptions: 主函数,初始化系统时钟、CC1101和MS5611,开总中断,然后进入低功耗模式
                若看门狗标志为1,则气压传感器进行测量、1101进行数据发送
*@Parameters:   NONE
*@Returned Value:NONE
*@Others:       NONE
*/
void main(void)
{  
  Init_CLK(); 
  Init_1101();
  MS5611_Init();
  _EINT(); 
  while(1)
  {
    //SFRIE1&=~WDTIE;//用于屏蔽发送功能,测试接收功能:经测试正常!     
    if(WDTFlag)
    {
      char length=4,address=0x18,ID=1;//十六进制浮点型气压值长度;汇聚节点地址;自身ID地址
      float Pressure;  
      unsigned long temp;

      /*----------------------测量数据-----------------------*/
      Pressure=MS5611_getPressure(SamplingPeriod);
      //int heighth=KalmanFilter(get_altitude(Pressure));//用于检验数据的正确性
      /*----------------------转换数据-----------------------*/
      temp=*(unsigned long *)&Pressure;//IAR中long型才为32位,int型为16位;而在VC,VS中int型为32位
      Buffer[0]=length+2;//地址字节+气压值长度+ID地址字节
      Buffer[1]=address;//目标地址长度
      Buffer[2]=ID;//自身ID地址
      Buffer[3]=temp>>24;//十六进制浮点型气压值
      Buffer[4]=temp>>16;
      Buffer[5]=temp>>8;
      Buffer[6]=temp;
      /*----------------------发送数据-----------------------*/
      //for(int i=0;i<2;i++)
      //{
        TxData(Buffer,length+3);//长度字节+地址字节+ID字节+气压值长度,标明写进缓冲区的字节数量
      //}
      /*----------------------继续接收-----------------------*/
      SPI_B2_Strobe(CCxxx0_SIDLE);
      SPI_B2_WriteReg(CCxxx0_CHANNR,RxChannel);

      SPI_B2_Strobe(CCxxx0_SFRX);
      //SPI_B2_Strobe(CCxxx0_SRX); 
      SPI_B2_Strobe(CCxxx0_SWORRST);              //复位SWOR r5
      SPI_B2_Strobe(CCxxx0_SWOR);                 //进入低功耗接收 
      WDTFlag=0;
    } 
    LPM4;
  } 
}

 

5.  看门狗中断响应处理函数:

/*
*@Function name:WDT_ISR
*@Descriptions: 看门狗中断处理函数,将看门狗标志置为1
*@Parameters:   NONE
*@Returned Value:NONE
*@Others:       NONE
*/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
  WDTFlag=1; 
  LPM4_EXIT;
}


6.  CC1101接收中断处理函数:

/*
*@Function name:P1_ISR
*@Descriptions: P1中CC1101中断处理函数,其进行以下操作:
                检测CRC校验状态-——>如果正确则接收该数据包,否则丢弃-——>恢复低功耗接收模式
*@Parameters:   NONE
*@Returned Value:NONE
*@Others:       NONE
*/
#pragma vector = PORT1_VECTOR
__interrupt void P1_ISR(void)
{ 
  unsigned char RxBufferLength,addr=3;//addr为命令所在位置
  //_DINT(); //5438不支持多级中断?
  if(P1IFG&GDO0)
  {
   if(SPI_B2_Read(0xF8) & CCxxx0_CRC_OK)//判断CRC校验
    { 
      /*-----------------------接收数据----------------------*/
      RxBufferLength = SPI_B2_Read(0XFB);//读取数据包长度
      SPI_B2_ReadBurstReg(CCxxx0_RXFIFO, read, RxBufferLength);//读取数据 
      CommandProcess(read[addr]);//处理命令函数
    }
    SPI_B2_Strobe(CCxxx0_SFRX);
    //SPI_B2_Strobe(CCxxx0_SRX); 
    SPI_B2_Strobe(CCxxx0_SWORRST);//复位SWOR r5
    SPI_B2_Strobe(CCxxx0_SWOR);//进入低功耗接收 
    P1IFG &= ~GDO0; 
  }
}

 

 

 

转载于:https://www.cnblogs.com/yangweijie/p/3450327.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值