基于STM32驱动CC1101的程序分析 浅谈CC1101调试

电子说

1.2w人已加入

描述

  本文主要是关于CC1101的相关介绍,并着重对基于STM32驱动CC1101的程序进行了详尽的分析。

  基于STM32驱动CC1101的程序分析

  首先明确:CC1101是通过SPI与MCU进行通信的。根据从TI官方上获得CC1101驱动,直接先移植SPI部分,STM32F103提供了SPI1和SPI2两条SPI总线,可自行选择,对于SPI的移植,直接参考STM32开发板上关于通过SPI操作Flash示例代码,对于SPI的配置与TI提供的驱动代码里的SPI配置保持一致。SPI移植完成之后,接上CC1101射频模块,测试SPI是否能正常通信,主要通过向CC1101任意可读可写寄存器写一个任意值,然后再读出该寄存器里的值,通过串口打印出该值,通过以上操作判断SPI是否正常通信,SPI移植是否成功。当然,这里使用到了串口,所以需要同时将串口的代码实现,同样参考串口实例。

  其次,当STM32与CC1101的SPI通信完成后,果断开始CC1101后续驱动的移植。移植过程中,所有变量名、函数名与TI提供的驱动里的保持一致,当然CC1101寄存器配置也保持移植。对于移植初期,我并没有太多的关心CC1101的时序问题,只关心怎么去移植,这也是自己的一个不好的习惯,所以初期移植的时候,对着TI提供的驱动代码,TI代码里有什么函数,我也移植什么函数;函数里有CS管脚的操作,也对应在操作在STM32下定义的CS管脚;TI里延时多长,我也跟着在STM32下延时相应的时间。整个驱动移植下来,关于CC1101的驱动函数也大多了然在心了。

  /*

  ** CC1101 433MHz无线模块相互通信

  ** 2014-11-16

  */

  #include “stm32f10x.h”

  #include “cc1101.h”

  #include “led.h”

  /*************NVIC控制器配置***************************/

  //组号 抢占位数 子优先级数量

  // 组0 0 4

  // 组1 1 3

  // 组2 2 2

  // 组3 3 1

  // 组4 4 0

  #define NVIC_PRIORITY_GROUP_0 (7 - 0)

  #define NVIC_PRIORITY_GROUP_1 (7 - 1)

  #define NVIC_PRIORITY_GROUP_2 (7 - 2)

  #define NVIC_PRIORITY_GROUP_3 (7 - 3)

  #define NVIC_PRIORITY_GROUP_4 (7 - 4)

  #define NVIC_PRIORITY_GROUP (NVIC_PRIORITY_GROUP_2) /* 设置为组2 */

  //#include “RF_Send.h”

  //#include “task.h”

  //***************更多功率参数设置可详细参考DATACC1100英文文档中第48-49页的参数表******************

  //INT8U PaTabel[8] = {0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04 ,0x04}; //-30dBm 功率最小

  //INT8U PaTabel[8] = {0x17,0x17 ,0x17 ,0x17 ,0x17 ,0x17,0x17 ,0x17}; //-20dBm

  //INT8U PaTabel[8] = {0x1D,0x1D ,0x1D ,0x1D ,0x1D ,0x1D,0x1D ,0x1D}; //-15dBm

  //INT8U PaTabel[8] = {0x26,0x26 ,0x26 ,0x26 ,0x26 ,0x26,0x26 ,0x26}; //-10dBm

  //INT8U PaTabel[8] = {0x37,0x37 ,0x37 ,0x37 ,0x37 ,0x37,0x37 ,0x37}; //-6dBm

  //INT8U PaTabel[8] = {0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60};//0dBm

  //INT8U PaTabel[8] = {0x86,0x86 ,0x86 ,0x86 ,0x86 ,0x86,0x86 ,0x86}; //5dBm

  const u8 PaTabel[8] = {0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0 ,0xC0};//12dBm

  u8 RF_Read_Buff[64];//接收缓冲区

  _RF_Sta RF_Sta;//RF状态

  /////////////////////////////////////////////////////////////////

  const RF_SETTINGS rfSettings =

  {

  0x00,

  0x08, // FSCTRL1 Frequency synthesizer control.

  0x00, // FSCTRL0 Frequency synthesizer control.

  0x10, // FREQ2 Frequency control word, high byte.

  0xA7, // FREQ1 Frequency control word, middle byte.

  0x62, // FREQ0 Frequency control word, low byte.

  0x5B, // MDMCFG4 Modem configuration.

  0xF8, // MDMCFG3 Modem configuration.

  0x03, // MDMCFG2 Modem configuration.

  0x22, // MDMCFG1 Modem configuration.

  0xF8, // MDMCFG0 Modem configuration.

  0x00, // CHANNR Channel number.

  0x47, // DEVIATN Modem deviation setting (when FSK modulation is enabled)。

  0xB6, // FREND1 Front end RX configuration.

  0x10, // FREND0 Front end RX configuration.

  0x18, // MCSM0 Main Radio Control State Machine configuration.

  // 0x0F, // MCSM1 Main Radio Control State Machine configuration.

  0x1D, // FOCCFG Frequency Offset Compensation Configuration.

  0x1C, // BSCFG Bit synchronization Configuration.

  0xC7, // AGCCTRL2 AGC control.

  0x00, // AGCCTRL1 AGC control.

  0xB2, // AGCCTRL0 AGC control.

  0xEA, // FSCAL3 Frequency synthesizer calibration.

  0x2A, // FSCAL2 Frequency synthesizer calibration.

  0x00, // FSCAL1 Frequency synthesizer calibration.

  0x11, // FSCAL0 Frequency synthesizer calibration.

  0x59, // FSTEST Frequency synthesizer calibration.

  0x81, // TEST2 Various test settings.

  0x35, // TEST1 Various test settings.

  0x09, // TEST0 Various test settings.

  0x0B, // IOCFG2 GDO2 output pin configuration.

  0x06, // IOCFG0D GDO0 output pin configuration. Refer to SmartRF?Studio User Manual for detailed pseudo register explanation.

  0x04, // PKTCTRL1 Packet automation control.

  0x05, // PKTCTRL0 Packet automation control.

  0x00, // ADDR Device address.

  RFDATLEN // PKTLEN Packet length.

  };

  //*****************************************************************************************

  //函数名:delayus(unsigned int s)

  //输入:时间

  //输出:无

  //功能描述:普通廷时,内部用

  //*****************************************************************************************

  void delayus(u16 timeout)

  {

  u8 i;

  do

  {

  for(i=0; i《20; i++);

  }

  while (--timeout);

  }

  /*****************************************************************************************/

  //函数名:CC1101_SpiInit()

  //输入:无

  //输出:无

  //功能描述:SPI初始化程序

  /*****************************************************************************************/

  void CC1101_SpiInit(void)

  {

  RCC-》APB2ENR|=1《《4; //使能PORTC时钟

  GPIOC-》CRL&=0Xff000000;

  GPIOC-》CRL|=0X00833388;

  GPIOC-》ODR|=0x00000023;

  }

  void Open_GD0_Interrupt(void)

  {

  uint32_t priority;

  /* 使能io复用时钟 */

  RCC-》APB2ENR |= 1 《《 0;

  /* 配置为输外部中断5在PC5上 */

  AFIO-》EXTICR[1] &= ~(0xF 《《 4);

  AFIO-》EXTICR[1] |= (2 《《 4);

  /* 开启外部中断5 */

  EXTI-》IMR |= (1 《《 5);

  /* 上升沿触发 */

  EXTI-》RTSR |= (1 《《 5);

  EXTI-》FTSR &= ~(1 《《 5);

  NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUP); /* 设置为组2 */

  priority = NVIC_EncodePriority (NVIC_PRIORITY_GROUP, 2, 3);

  NVIC_SetPriority(EXTI9_5_IRQn,priority); /* EXTIx_IRQn 在stm32f10x.h中有定义 */

  NVIC_EnableIRQ(EXTI9_5_IRQn);

  }

  //*****************************************************************************************

  //函数名:SpisendByte(INT8U dat)

  //输入:发送的数据

  //输出:无

  //功能描述:SPI发送一个字节

  //*****************************************************************************************

  u8 SpiTxRxByte(u8 dat)

  {

  u8 i,j,temp= 0;

  SCK = 0;

  for(i=0; i《8; i++)

  {

  if(dat & 0x80)MOSI = 1;

  else MOSI = 0;

  j++;j++;

  dat 《《= 1;

  j++;j++;

  SCK = 1;

  j++;j++;

  temp 《《= 1;

  if(MISO)temp++;

  SCK = 0;

  j++;j++;

  }

  return temp;

  }

  //*****************************************************************************************

  //函数名:void RESET_CC1100(void)

  //输入:无

  //输出:无

  //功能描述:复位CC1100

  //*****************************************************************************************

  u8 RESET_CC1100(void)

  {

  u16 n=0;

  CSN = 0;

  while(MISO)

  {

  if(++n》300)return 0;

  delayus(5);

  }

  n=0;

  SpiTxRxByte(CCxxx0_SRES); //写入复位命令

  while(MISO)

  {

  if(++n》300)return 0;

  delayus(5);

  }

  CSN = 1;

  return 1;

  }

  //*****************************************************************************************

  //函数名:void POWER_UP_RESET_CC1100(void)

  //输入:无

  //输出:无

  //功能描述:上电复位CC1100

  //*****************************************************************************************

  u8 POWER_UP_RESET_CC1100(void)

  {

  CSN = 1;

  delayus(10);

  CSN = 0;

  delayus(10);

  CSN = 1;

  delayus(100);

  if(RESET_CC1100())return 1; //复位CC1100

  return 0;

  }

  CC1101调试

  关于滤波指令和寄存器配置:

  其实这里也TFT配置差不多,玩过TFT的都有同感,TFT可以通过RW引脚控制是读还是写,如果是写寄存器,先写寄存器的地址,然后写数据,数据就到了相应的寄存器里面了;读就是RW引脚设置为读对应的电平,先写寄存器的地址,该寄存器里面的数据就可以读出来了。明白了这些其实理解CC1101就可以很容易理解了。

  那么对应CC1101的理解:

  寄存器的配置:

  CC1101寄存器地址是0~0x3F,也就是BIT0~BIT5

  CC1101读写控制是BIT7,BIT7为1时,为读对应的寄存器,BIT7为0时,为写相应的寄存器。

  那么还剩下一个BIT6,BIT6是突发访问控制为,BIT6为1为突发访问,BIT6为0为单字节访问。(突发访问下面说)

  这样我们就可以很容易理解了,比如配置PKTCTRL0寄存器,其地址0x08,我们突发访问写的话写先数据0x48,再连续写数据,这里明白了突发访问后就很容易知道了,如果单字节读这个寄存器,先写数据0x88,读一下就可以了。

  命令滤波:

  命令滤波这里和TFT的写0x22是一样的,它就自动跳转到寄存器的出口,cc1101这里也是,只要写一下对应的寄存器的地址,不用写数据,它就内部自动执行相应的指令,比如重启芯片,设置为发送模式,共有14个滤波指令,地址从0x30~0x3D。

  关于滤波指令的状态寄存器其实是可读不可写的,

  也就是0x30~0x3D的地址加上0xC0,(BIT7 和IBT6为1,前面说过了),比如写数据0xF4,就可以读到相应RSSI状态寄存器里面的值。

  CC1101的几个状态:

  几个状态分别是,IDLE,TX,RX,FSTXON,校准,迁移,RXFIFO_OVERFLOW,TXFIFO_OVERFLOW,有读的状态字的BIT6~BIT4决定

  结语

  关于基于STM32驱动CC1101的程序的相关介绍就到这了,如有不足之处欢迎指正。

相关阅读推荐:一文看懂CC110L与CC1101的区别

相关阅读推荐:无线芯片CC1100和CC1101的区别

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分