cc1101低功耗设计方案 CC1101收发驱动程序

cc1101低功耗设计方案 CC1101收发驱动程序,第1张

  本文主要是关于cc1101的相关介绍,并着重对cc1101低功耗以及驱动收发程序进行了详尽的阐述。

  cc1101

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

  ● 超低功耗无线收发器

  ● 家庭和楼宇自动化

  ● 高级抄表架构(AMI)

  ● 无线报警安全系统

  ◆ 387.0MHz~464.0MHz工作频段。

  (433MHz,0.6kbps,1%误码率时为-116dBm)。

  (接收模式,433MHz,1.2kbps时仅16.0mA)。

  ◆ 最高可设置为+10dBm的发射功率。

  ◆ 支持0.6kbps~500kbps的数据传输速率。

  ◆ 支持多种调制模式(OOK、ASK、GFSK、2-FSK、4-FSK和MSK)。

  ◆ 提供对同步字检测、地址校验、灵活的数据包长度以及自动CRC处理的支持。

  ◆ 支持RSSI(接收信号强度指示)和LQI(链路质量指示)。

  ◆ 通过4线SPI接口MCU连接,同时提供2个可设定功能的通用数字输出引脚。

  ◆ 独立的64字节RXFIFO和TX FIFO。

  ◆ 工作电压范围:1.9V~3.6V,待机模式下电流仅为200nA。

  ◆ 工作温度范围:-40℃~+85℃

  cc1101低功耗设计方案

  电路设计上,只用到了一个LED、串口1、一个模拟SPI、一个中断线、一个读卡芯片RESET线,硬件上就只剩下这么点东西了,这个时候我采用的是待机模式,使用的是读卡芯片的中断接PA0唤醒STM32,在此之前要先使得读卡芯片进入低功耗、然后STM32进入低功耗,这一步完成了,貌似没什么问题,功耗确实从几十mA骤降到3mA左右,开始还挺满意的,但是测试厂商提供的样板,功耗却只有几十uA,有点郁闷了。为什么会这样?反复查看硬件、程序,都找不出原因,而且这个时候的工作效果很烂,根本就不能唤醒,所以我就怀疑是读卡芯片一端低功耗有问题,因为我将PA0脚直接短接VCC,这样就可以产生一个边沿触发STM32唤醒了,但是用读卡芯片无法唤醒,所以我怀疑是读卡芯片的RESET脚电平不对,经检查,确实是因为RESET脚加了上拉电阻,读卡芯片是高电平复位,在STM32进入待机后,管脚全都浮空了,导致RESET被拉高,一直在复位;我去掉上拉电阻,觉得很有希望解决问题了,但是测试结果是:有时候能唤醒,有时候不能,我仔细一想难道是因为STM32待机后管脚电平不确定,导致读卡芯片RESET脚电平不定,而工作不正常,看样子只有换用其他方案了。后面确实验证了我的想法,使用STOP模式后,唤醒问题引刃而解。

  就在关键时刻,芯片原厂火种送炭,送来急需的技术支持资料,一个包含低功耗源代码,赶紧拿过来测试,先研读下代码,使用的是STOP模式,而不是待机模式,使用的是任意外部中断唤醒,功耗低制40uA,这个时候就相当激动啊,赶快下载测试啊,结果功耗确实降了,但还是有1mA,更人家一比多了几十倍啊。。。

  我第一反应是硬件不对,经过测试修改,首先找到第一个原因,读卡芯片RESET管脚上拉电阻又给焊上去了。。.,拆掉后功耗骤降到几百uA,还是不行。。 测试过程中,为了去掉LDO的干扰,整板采用3.3V供电,但是后面经过测试,LDO的功耗其实也只有5uA不到,这LDO功耗值得赞一个;虽然结果还是没达到预期,但是看到了希望,胜利就在眼前啊。

  为此我反复看了技术支持提供的程序,发现他们的STM32的所有管脚都的设置都有所考究:(因为公司保密原则,代码中删除掉了关于该读卡芯片的前缀信息等)

  GPIO_InitTypeDef GPIO_InitStructure;

  /* GPIOA Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  /* GPIOB Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  /* GPIOC Periph clock enable */

  //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

  //####################################################

  //USART1 Port Set

  //TXD

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //RXD

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //RST output pushpull mode

  GPIO_InitStructure.GPIO_Pin = TRST;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(PORT1, &GPIO_InitStructure);

  //IRQ input pull-up mode

  GPIO_InitStructure.GPIO_Pin = TIRQ;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(PORT1, &GPIO_InitStructure);

  //MISO input pull-up mode

  GPIO_InitStructure.GPIO_Pin = MISO;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(PORT2, &GPIO_InitStructure);

  //NSS,SCK,MOSI output pushpull mode

  GPIO_InitStructure.GPIO_Pin = (NSS|SCK|MOSI);

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(PORT2, &GPIO_InitStructure);

  //############################################################################

  //TEST Port set

  //TESTO input pushpull mode

  GPIO_InitStructure.GPIO_Pin = TESTO;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(TEST_PORT, &GPIO_InitStructure);

  //############################################################################

  //TEST Port set

  //TESTI output pushpull mode

  GPIO_InitStructure.GPIO_Pin = TESTI;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(TEST_PORT, &GPIO_InitStructure);

  //############################################################################

  //LED Port Set

  //LED output pushpull mode

  GPIO_InitStructure.GPIO_Pin = LED;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(LED_PORT, &GPIO_InitStructure);

  //############################################################

  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_15);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  首先,想MOSI、SCK、CS、LED、RST这些管脚应该设置为推挽输出,TXD设置为复用输出,而IRQ、RXD、MISO设置浮空输入,什么都没接的管脚全都设置为下拉输入,而TESTI、TESO我一直不解是什么东东,开始就没管,而开始的时候MISO我也没怎么注意,设置成上拉输入(而不是浮空输入),反正大部分按照厂家提供的参考,我并没有照搬,测试效果一样,但功耗确是还有80-90uA,期间我找了好久没找到原因,给技术支持一看,原来是因为MISO没有设置成浮空输入,我是设置成了上拉输入,上拉电阻一直在消耗大约40uA的电流。。。 好吧,这是自己不够细心导致的,以后做低功耗的项目管脚配置是个大问题,不能再这么马虎了!!! 我将MISO设置成浮空输入之后,最低功耗还是有40+,离10uA的最低功耗还有段距离,到底是为什么呢?最后我发现

  ,该读卡芯片有个TESTIN/TESTOUT管脚,是用来测试用的,出厂后也就用不上了,我也一直以为这两个脚确实没什么用,就没接;可是我发现厂家提供的样板居然接了这两个脚,但是厂商也没说这两个脚接或不接会影响功耗啊,抱着试一试的心态,我我把TESTIN/TESTOUT两个管脚接到单片机上进行相应的配置,接下来是见证奇迹的时刻了,功耗居然真的、真的降到10uA了。。。。。。。。。。。 此处省略n个字

  这时候真的很激动,真的很想骂人啊,坑爹的厂家,为什么不给提示说这两个脚不接单片机会消耗电流呢?(也许是文档里面提到了,但是几百页的文档,还是全英文的,一堆堆的文字,我再看一遍,确实没有提到这两个管脚会有漏电流。)

  项目就这样完工了,中间最重要的是技术支持的强力支持,不然项目不能完工了,这个项目低功耗STM32方面难度不高,主要是读卡芯片上面的低功耗调试起来问题很多,还是人家原厂的出马才解决了问题,因为众多原因,不能公布该芯片的资料,包括该芯片怎么进入低功耗也无法公开,所以抱歉~~。

  关于STM32进入低功耗,我简单的总结了一下:

  1.管脚设置,这个很关键,还是跟你电路有关系,外加上拉、下拉电阻切记不能随便加

  2.STM32的systick clock、DMA、TIM什么的,能关就全都关掉,STM32低功耗很简单,关键是外围电路功耗是关键

  3.选择一个低功耗的LDO,这个项目用到的LDO功耗就很不错,静态功耗10uA都不到。

  4.确定STM32设置没问题,进入低功耗有好几种情况可以选择(睡眠、停机、待机),我还是推荐选择STOP模式,这个我觉的比较好是因为可以任意外部中断都可以唤醒,而且管脚可以保留之前的设置,进入停机模式的代码使用库函数自带的,就一句:

  PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);

  意思是,在进入停机模式之前,也关掉电压调节器,进一步降低功耗,使用WFI指令(任意中断唤醒),但是经过测试,使用WFE(任事件唤醒)指令效果、功耗一模一样。

  最后一步是从STOP模式怎么恢复了,恢复其实也很简单,外部中断来了会进入中断函数,然后STM32就被唤醒,唤醒还要做一些工作,需要开启外部晶振(当然你也可以选择使用内部自带振荡器)、开启你需要的外设等等。

  CC1101收发驱动程序

  #include “system.h”

  #include “delay.h”

  #include “CC1101.h”

  //CC1101命令掩码

  #define WRITE_BURST 0x40 //连续写入

  #define READ_SINGLE 0x80 //读

  #define WRITE_SINGLE 0x00 //写

  #define READ_BURST 0xC0

  //连续读

  #define BURST_READ_FIFO 0xff //突发读取RX FIFO

  #define BYTE_READ_FIFO 0xBF //单字节读取 RX FIFO

  #define BURST_WRITE_FIFO 0x7f //突发写TX FIFO

  #define BYTE_WRITE_FIFO 0x3f //单字节写 TX FIFO

  #define CC1101_DATA_LEN 64

  //SPI接口

  //底层接口宏定义

  #define CC1101_CS_H() (GPIOA-》ODR|=BIT3) //PA3=1

  #define CC1101_CS_L() (GPIOA-》ODR&=~BIT3) //PA3=0

  #define CC1101_MOSI_H() (GPIOC-》ODR|=BIT6) //PC6

  #define CC1101_MOSI_L() (GPIOC-》ODR&=~BIT6) //PC6

  #define CC1101_SCLK_H() (GPIOC-》ODR|=BIT5) //PC5

  #define CC1101_SCLK_L() (GPIOC-》ODR&=~BIT5) //PC5

  #define CC1101_GetMISO() (GPIOC-》IDR&BIT7) //PC7

  //CC1101 SPI读写一字节

  //不带片选

  u8 CC1101_ReadWriteByte(u8 data)

  {

  u8 i;

  u8 temp = 0;

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

  {

  if(data & 0x80)

  {

  CC1101_MOSI_H();

  }

  else

  {

  CC1101_MOSI_L();

  }

  data 《《= 1;nop;

  CC1101_SCLK_H(); //时钟上升沿写入数据

  temp 《《= 1;nop;

  if(CC1101_GetMISO()) temp ++;

  CC1101_SCLK_L(); //时钟下降沿读取数据

  }

  return temp;

  }

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

  * 函数 : u8 CC1101_Command(CC1101_CMD_TYPE Cmd)

  * 功能 : 发送单字节命令

  * 参数 : Cmd;命令,见CC1101_CMD_TYPE

  * 返回 : 寄存器的值

  * 依赖 : 底层宏定义

  * 作者 : cp1300@139.com

  * 时间 : 2013-12-06

  * 最后修改时间 : 2013-12-06

  * 说明 : 以写的方式单直接访问将触发响应的命令

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

  u8 CC1101_Command(CC1101_CMD_TYPE Cmd)

  {

  u8 status;

  CC1101_CS_L(); //片选有效

  while(CC1101_GetMISO());

  status = CC1101_ReadWriteByte((u8)Cmd); //发送命令

  while(CC1101_GetMISO());

  CC1101_CS_H(); //片选关闭

  return status;

  }

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

  * 函数 : u8 CC1101_ReadReg(CC1101_REG_TYPE RegAddr)

  * 功能 : 读取CC1101通用寄存器

  * 参数 : RegAddr:寄存器地址,见:CC1101_REG_TYPE

  * 返回 : 寄存器的值

  * 依赖 : 底层宏定义

  * 作者 : cp1300@139.com

  * 时间 : 2013-12-06

  * 最后修改时间 : 2013-12-06

  * 说明 : 一次读取一个寄存器

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

  u8 CC1101_ReadReg(CC1101_REG_TYPE RegAddr)

  {

  u8 data;

  CC1101_CS_L(); //片选有效

  CC1101_ReadWriteByte((u8)READ_SINGLE|RegAddr); //发送读命令以及寄存器索引

  data = CC1101_ReadWriteByte(0xff); //读取

  CC1101_CS_H(); //片选关闭

  return data;

  }

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

  * 函数 : u8 CC1101_WriteReg(CC1101_REG_TYPE RegAddr, u8 data)

  * 功能 : 写入CC1101通用寄存器

  * 参数 : RegAddr:寄存器地址,见:CC1101_REG_TYPE,data:需要写入的数据

  * 返回 : 状态寄存器的值

  * 依赖 : 底层宏定义

  * 作者 : cp1300@139.com

  * 时间 : 2013-12-06

  * 最后修改时间 : 2013-12-06

  * 说明 : 一次写入一个寄存器,并返回状态

  不要对只读的寄存器进行写 *** 作

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

  u8 CC1101_WriteReg(CC1101_REG_TYPE RegAddr, u8 data)

  {

  u8 status;

  if(RegAddr 》 0x80) return 0; //防止误 *** 作,0x30以后的寄存器为只读状态寄存器

  CC1101_CS_L(); //片选有效

  while(CC1101_GetMISO());

  status = CC1101_ReadWriteByte((u8)WRITE_SINGLE|RegAddr); //发送写命令以及寄存器索引

  CC1101_ReadWriteByte(data); //写入数据

  CC1101_CS_H(); //片选关闭

  return status;

  }

  #include “LED.h”

  void CC1101_Init(u8 Addr)

  {

  //初始化片选

  GPIOx_Init(GPIOA, BIT3, OUT_PP_10M);

  CC1101_CS_H();

  //初始化SCLK

  GPIOx_Init(GPIOC, BIT5, OUT_PP_10M);

  CC1101_SCLK_H();

  //初始化MOSI

  GPIOx_Init(GPIOC, BIT6, OUT_PP_10M);

  CC1101_MOSI_H();

  //初始化MISO

  GPIOx_Init(GPIOC, BIT7, IN_UP);

  CC1101_SCLK_L();

  CC1101_MOSI_L();

  //初始化GDO0,GDO2对应PC3,PC4

  GPIOx_Init(GPIOC, BIT3, IN_UP);

  GPIOx_Init(GPIOC, BIT4, IN_UP);

  //初始化寄存器

  CC1101_Command(CC1101_CMD_SRES); //复位

  Delay_MS(10);

  while(CC1101_ReadReg(CC1101_REG_AGCTEST) != 0x3F) //检测通信

  {

  LED_ON();

  Delay_MS(10);

  LED_OFF();

  Delay_MS(100);

  }

  LED_OFF();

  CC1101_WriteReg(CC1101_REG_IOCFG0,0x06); //发送提示引脚

  CC1101_WriteReg(CC1101_REG_IOCFG2,0x01); //接收提示引脚

  CC1101_WriteReg(CC1101_REG_FIFOTHR,0x0f); //RX FIFO和TX FIFO门限

  CC1101_WriteReg(CC1101_REG_SYNC1,0xD3); //同步词汇,高字节

  CC1101_WriteReg(CC1101_REG_SYNC0,0x91); //同步词汇,低字节

  CC1101_WriteReg(CC1101_REG_PKTLEN,CC1101_DATA_LEN); //数据包长度,255

  CC1101_WriteReg(CC1101_REG_PKTCTRL1,0x04); //数据包自动控制

  CC1101_WriteReg(CC1101_REG_PKTCTRL0,0x04); //数据包自动控制

  CC1101_WriteReg(CC1101_REG_ADDR,0x00); //设备地址

  CC1101_WriteReg(CC1101_REG_CHANNR,0x00); //信道

  CC1101_WriteReg(CC1101_REG_FSCTRL1,0x06); //频率合成器控制,高字节

  CC1101_WriteReg(CC1101_REG_FSCTRL0,0x00); //频率合成器控制,低字节

  CC1101_WriteReg(CC1101_REG_FREQ2,0x10); //频率控制词汇,高字节

  CC1101_WriteReg(CC1101_REG_FREQ1,0xb1); //频率控制词汇,中间字节

  CC1101_WriteReg(CC1101_REG_FREQ0,0x3b); //频率控制词汇,低字节

  //2.4KBPS

  CC1101_WriteReg(CC1101_REG_MDMCFG4,0xF6); //调制器配置

  CC1101_WriteReg(CC1101_REG_MDMCFG3,0x83); //调制器配置

  CC1101_WriteReg(CC1101_REG_MDMCFG2,0x13); //调制器配置

  CC1101_WriteReg(CC1101_REG_MDMCFG1,0x22); //调制器配置

  CC1101_WriteReg(CC1101_REG_MDMCFG0,0xf8); //调制器配置

  CC1101_WriteReg(CC1101_REG_DEVIATN,0x15); //调制器背离设置

  CC1101_WriteReg(CC1101_REG_MCSM2,0x07); //主通信控制状态机配置

  CC1101_WriteReg(CC1101_REG_MCSM1,0x30); //主通信控制状态机配置

  CC1101_WriteReg(CC1101_REG_MCSM0,0x18); //主通信控制状态机配置

  CC1101_WriteReg(CC1101_REG_FOCCFG,0x16); //频率偏移补偿配置

  CC1101_WriteReg(CC1101_REG_BSCFG,0x6c); //位同步配置

  CC1101_WriteReg(CC1101_REG_AGCTRL2,0x03); //AGC控制

  CC1101_WriteReg(CC1101_REG_AGCTRL1,0x40); //AGC控制

  CC1101_WriteReg(CC1101_REG_AGCTRL0,0x91); //AGC控制

  CC1101_WriteReg(CC1101_REG_WOREVT1,0x87); //高字节时间0暂停

  CC1101_WriteReg(CC1101_REG_WOREVT0,0x6b); //低字节时间0暂停

  CC1101_WriteReg(CC1101_REG_WORCTRL,0xfb); //电磁波激活控制

  CC1101_WriteReg(CC1101_REG_FREND1,0x56); //前末端RX配置

  CC1101_WriteReg(CC1101_REG_FREND0,0x10); //前末端TX配置

  CC1101_WriteReg(CC1101_REG_FSCAL3,0xe9); //频率合成器校准

  CC1101_WriteReg(CC1101_REG_FSCAL2,0x2a); //频率合成器校准

  CC1101_WriteReg(CC1101_REG_FSCAL1,0x00); //频率合成器校准

  CC1101_WriteReg(CC1101_REG_FSCAL0,0x1f); //频率合成器校准

  CC1101_WriteReg(CC1101_REG_RCCTRL1,0x41); //RC振荡器配置

  CC1101_WriteReg(CC1101_REG_RCCTRL0,0x00); //RC振荡器配置

  CC1101_WriteReg(CC1101_REG_FSTEST,0x59); //频率合成器校准控制

  //10DB

  //CC1101_WriteReg(CC1101_REG_PATABLE0,0xc0);

  //CC1101_WriteReg(CC1101_REG_PATABLE1,0xc0);

  /*CC1101_WriteReg(CC1101_REG_PATABLE2,0xc0);

  CC1101_WriteReg(CC1101_REG_PATABLE3,0xc0);

  CC1101_WriteReg(CC1101_REG_PATABLE4,0xc0);

  CC1101_WriteReg(CC1101_REG_PATABLE5,0xc0);

  CC1101_WriteReg(CC1101_REG_PATABLE6,0xc0);

  CC1101_WriteReg(CC1101_REG_PATABLE7,0xc0); */

  Delay_MS(10);

  }

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

  * 函数 : void CC1101_WriteTxFIFO(u8 *pBuff,u8 len)

  * 功能 : 写入数据到发送缓冲区

  * 参数 : pBuff:需要写入的数据缓冲区指针,len:需要写入的数据长度

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 作者 : cp1300@139.com

  * 时间 : 2014-01-01

  * 最后修改时间 : 2014-01-01

  * 说明 : 写入数据到发送FIFO

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

  void CC1101_WriteTxFIFO(u8 *pBuff,u8 len)

  {

  u16 i;

  CC1101_CS_L();

  CC1101_ReadWriteByte(BURST_WRITE_FIFO);

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

  {

  CC1101_ReadWriteByte(pBuff);

  }

  CC1101_CS_H();

  }

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

  * 函数 : void CC1101_ReadRxFIFO(u8 *pBuff,u8 len)

  * 功能 : 读取接收缓冲区

  * 参数 : pBuff:需要读取的数据缓冲区指针,len:需要读取的数据长度

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 作者 : cp1300@139.com

  * 时间 : 2014-01-01

  * 最后修改时间 : 2014-01-01

  * 说明 : 从接收FIFO读取数据

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

  void CC1101_ReadRxFIFO(u8 *pBuff,u8 len)

  {

  u16 i;

  CC1101_CS_L();

  CC1101_ReadWriteByte(BURST_READ_FIFO);

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

  {

  pBuff = CC1101_ReadWriteByte(0xff);

  }

  CC1101_CS_H();

  }

  //发送数据,将缓冲区数据全部发送出去

  //一次最多64B,因为受到FIFO限制

  void CC1101_RfDataSend(u8 *pBuff,u8 len)

  {

  CC1101_Command(CC1101_CMD_SIDLE); //退出当前模式

  CC1101_Command(CC1101_CMD_SFTX); //清空发送缓冲区

  CC1101_WriteTxFIFO(pBuff, len); //写入数据到发送缓冲区

  CC1101_Command(CC1101_CMD_STX); //开始发送数据

  while(!CC1101_GDO0);

  while(CC1101_GDO0);

  CC1101_Command(CC1101_CMD_SIDLE); //退出当前模式

  }

  //发送数据包

  //每次发送最多65B,第一字节为长度,数据多将会重复发送

  //可以发送任意大小

  //CC1101PackSize有效数据包大小,0-64,也就是CC1101单次发送数据大小-1

  void CC1101_RfDataSendPack(u8 *pBuff, u16 len)

  {

  u16 i,m,n,j;

  m = len / (CC1101_DATA_LEN-1); //整数数据帧数量

  n = len % (CC1101_DATA_LEN-1); //余数

  //发送整数包

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

  {

  Delay_MS(1);

  CC1101_Command(CC1101_CMD_SIDLE); //退出当前模式

  CC1101_Command(CC1101_CMD_SFTX); //清空发送缓冲区

  CC1101_CS_L();

  CC1101_ReadWriteByte(BURST_WRITE_FIFO);

  CC1101_ReadWriteByte(CC1101_DATA_LEN-1);//先写入包大小

  for(j = 0;j 《 (CC1101_DATA_LEN-1);j ++)

  {

  CC1101_ReadWriteByte(*pBuff++); //写入数据到发送缓冲区

  }

  CC1101_CS_H();

  CC1101_Command(CC1101_CMD_STX); //开始发送数据

  while(!CC1101_GDO0);

  while(CC1101_GDO0); //等待发送完成

  }

  //发送余数包

  if(n!=0)

  {

  Delay_MS(1);

  CC1101_Command(CC1101_CMD_SIDLE); //退出当前模式

  CC1101_Command(CC1101_CMD_SFTX); //清空发送缓冲区

  CC1101_CS_L();

  CC1101_ReadWriteByte(BURST_WRITE_FIFO);

  CC1101_ReadWriteByte(n); //先写入包大小

  for(j = 0;j 《 n;j ++)

  {

  CC1101_ReadWriteByte(*pBuff++); //写入数据到发送缓冲区

  }

  CC1101_CS_H();

  CC1101_Command(CC1101_CMD_STX); //开始发送数据

  while(!CC1101_GDO0);

  while(CC1101_GDO0); //等待发送完成

  }

  CC1101_Command(CC1101_CMD_SIDLE); //退出当前模式

  }

  //读取芯片状态

  u8 CC1101_GetStatus(void)

  {

  return CC1101_WriteReg(CC1101_REG_TEST2, 0x98);

  }

  结语

  关于cc1101的相关介绍就到这了,如有不足之处欢迎指正。

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

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2702817.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-16
下一篇 2022-08-16

发表评论

登录后才能评论

评论列表(0条)

保存