专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

cc1101的详解及单片机程序

作者:huqin   来源:本站原创   点击数:  更新时间:2014年11月12日   【字体:

1.初始化SPI,MCU各引脚。

    
        当有数据接收或发送状态声明时,有中断和查询两种方式。GDO0与GDO2引脚输出至MCU引脚,若要用中断则要接至MCU外部中断引脚,查询时则可用GPIO。
 
    2.复位CC1101。
 
    3.初始化CC1101。(写操作时可从SO中读出CC1101状态)
 
        初始化后CC1100为IDLE状态.
    
    4.状态机转换,写/读FIFO数据。
 
        每次写操作时SO返回的值为写操作前的CC1100状态值,具体值见Table20;读状态命令为当前CC1100状态值,具体值见寄存器0X35说明;注意两者区别。
 
快速认识Cc1100
 
             Cc1100可以工作在同步模式下,代价是:MCU自己控制前导码。本系统中,Cc1100将工作在异步模式下。
  
知识点
 
             Head Byte:在 引脚 Cc1100.Csn 有效后,通过SPI总线写入 Cc1100的第一个字节。
 
             Status Byte: 在写入 HeadByte 的同时,MCU 得到 Status Byte。
 
             Burst Bit:在 Head Byte 中的一个 Bit, 有效值=="1",无效值=="0"
 
GDO0:
             GDO0可用作FIFO状态输出,载波感应(CS),时钟输出,GDO0 脚也能用作集成于芯片的模拟温度传感器(未用).配置寄存器为IOCFG0(0X02),现在配置为RX模式下数据状态反应输出.
 
GDO1:
             GDO1与SPI的SO共用引脚,默认状态下为3态,当CSn为低电平时,此引脚SPI的SO功能生效。配置寄存器为IOCFG0(0X01),现在配置为空闲状态下3态,SPI模式下SO.
 
GDO2:
 
             GDO2可用作FIFO状态输出,载波感应(CS),时钟输出,配置寄存器为IOCFG0(0X00),现在配置为载波感应(CS)输出.
 
TXOFF_MODE/RXOFF_MODE:
 
             注意,此配置为在数据包被发送/接收后状态机状态决定位,仅是在发生发送或者接收后动作;当为IDLE时发SRX/STX后状态机不按此配置运行。TX/RX后要校准。
 
功率放大控制(PATABLE):
 
             0X3E为功率写入地址,0X22为为功率配置寄存器。PATABLE 是一个8字节表,定义了8个PA 功率值。这个表从最低位(0)到最高位(7)可读和写,一次一位。一个索引计数器用来控制对这个表的访问。
 
             每读出或写入表中的一个字节,计数器就加 1。当 CSn 为高时,计数值置为最小值。当达到最大值时,计数器由零重新开始计数。
    
             FREND0.PA_POWER(2:0)从8个功率值中选择1个,且振幅为相应数等级。
 
 
异步模式:
             在此模式下,CC1101中的MCU的若干支持机制会停用,包括数据包硬件处理,FIFO 缓冲,数据白化,交错(interleaver)和前向纠错(FEC) ,曼彻斯特编码(Manchester encoding);
 
             MSK不支持异步模式;
 
             PKTCTRL0.PKT_FORMAT == 3 使能异步模式,GDO0为input,GDO0, GDO1或GDO2为output 相应配置位为IOCFG0.GDO0_CFG, IOCFG1.GDO1_CFG IOCFG2.GDO2_CFG;
 
电磁波激活(WOR):
 
             在WOR滤波使用之前RC振荡器必须启用,RC振荡器是 WOR 定时器的时钟源.在WOR下,收到信号后会自动进入RX模式.
 
载波感应(CS)与RSSI:
 
             因此两配置相互有连系,所以一起论述.
 
             RSSI 只能在RX模式下才能有效,作用为对当前信号质量评估,信号质量可从RSSI寄存器读出.RSSI信号强度可从0X34取出.
 
             RSSI(信号强度)计算公式: 注:此为433M下,结果为负数,
 
                                            RSSI_dBm=(RSSI-256)/2-74 (RSSI>=128)
 
                                            RSSI_dBm= (RSSI/2)-74      (RSSI<128)
 
             CS 只在RX模式下才能有效,当信号质量高于设定门限值时,CS状态将会被声明。现在配置为GDO2输出感应状态.
 
             CS门限值由以下4个寄存器决定
 
             ?? AGCCTRL2.MAX_LNA_GAIN  
             ?? AGCCTRL2.MAX_DVGA_GAIN
             ?? AGCCTRL1.CARRIER_SENSE_ABS_THR
             ?? AGCCTRL2.MAGN_TARGET
             
             CS门限值计算公式:     表默认门限值 + (MAGN_TARGET-33) + CARRIER_SENSE_ABS_THR.
 
                                           表默认门限值见table29,table30. 由AGCCTRL2.MAX_LNA_GAIN   AGCCTRL2.MAX_DVGA_GAIN 决定.
 
                                          默认门限值表只给了两个数据速率下的值,其余由自己测.我们对此要求不是太高,可以参考用这个表.
 
                                           CARRIER_SENSE_ABS_THR为对应表中-7~7的值,最后单位为dBm.
 
                                           Example:
 
                                                         在250K下AGCCTRL2.MAX_LNA_GAIN = 00   AGCCTRL2.MAX_DVGA_GAIN = 00 得出表中为-90.5
 
                                                          MAGN_TARGET = 7(42), CARRIER_SENSE_ABS_THR = 1(1)
 
                                                         门限为-90.5 + (42-33) + 1= -82.5dBm            
 
清理信道访问(CCA):

             清理信道访问用来指示当前信号是空闲还是忙。当忙时是否丢弃当前数据,寄存器MCSM1.CCA_MODE决定是否丢弃.默认配置为保留当前寄存器中数据,丢弃下一步要处理数据.

 

数据FIFO:

          

 
             当TX操作时,由MCU控制,溢出时CC1101出错;当RX操作时,读空时CC1101出错
 
             RX FIFO 和 TX FIFO 中的字节数也能分别从状态寄存器 RXBYTES.NUM_RXBYTES和TXBYTES.NUM_TXBYTES 中读出
 
             4 位 FIFOTHR.FIFO_THR 设置用来控制FIFO 门限点
 
             读单字节时,,CSn继续保持低;。突发访问方式允许一地址字节,然后是连续的数据字节,直到通过设置 CSn 为高来断访问
            
             当写操作时,最后一个字节被传送至 SI 脚后, 被 SO脚接收的状态位会表明在 TX FIFO中只有一个字节是空闲,
 
寄存器分类
         
  Configration Registers

共47个,可读,可写

0x00~0x2E

   
  Status Registers

共14个,只读

0x30~0x3D

   
  Command Strobe

共14个,只写

寻址空间:0x30~0x3D

 

14个地址,对相应的地址进行写,

就相当于激活了对应的命令

本系统是用到的Strobe:

CC1100_STROBE_RESET
CC1100_STROBE_ENTER_RX_MODE
CC1100_STROBE_ENTER_TX_MODE
CC1100_COMMAND_STROBE_SIDLE
CC1100_COMMAND_STROBE_SFRX

 
  TX FIFO 共64个,只写    
  RX FIFO 共64个,只读    
         
 
 
Status(Command)Registers操作:
 
     当地址为0X30~0X3D时
 
     burst为1:对Status Registers的操作
 
                   Status Registers只可读,且只能一次读一个字节,不可写                 
     burst为0:对Command Registers操作
 
                 寄存器的访问和一个寄存器的操作一样,但没有数据被传输.写完毕后,CC1100便执行相应操作.
 
 
 
 
     读写FIFO,有两种模式:单字节读写;Burst读写。
         单字节读写时序:
             1 Cc1100.Csn有效。
             2 写入Head Byte。
              3 读、写一个1字节。
             4 Cc1100.Csn无效。
#include <reg52.h>
#include <intrins.h>
#define  INT8U  unsigned char
#define  INT16U  unsigned int
#define  WRITE_BURST      0x40      //连续写入
#define  READ_SINGLE      0x80      //读
#define  READ_BURST       0xC0      //连续读
#define  BYTES_IN_RXFIFO     0x7F        //接收缓冲区的有效字节数
#define  CRC_OK              0x80       //CRC校验通过位标志
//*****************************************************************************************
sbit  GDO0 =P1^3;
sbit  GDO2 =P3^2;
sbit MISO =P1^6;
sbit MOSI =P1^5;
sbit SCK =P1^7;
sbit CSN =P1^2;
//*****************************************************************************************
sbit    LED2    =P3^4;
sbit    LED1    =P3^5;
sbit    KEY1    =P3^6;
sbit    KEY2    =P3^7;
//*****************************************************************************************
sbit led3=P2^3;
sbit led2=P2^2;
sbit led1=P2^1;
sbit led0=P2^0;
//*****************************************************************************************
//INT8U PaTabel[8] = {0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60};
INT8U PaTabel[8] = {0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0};//修改发射功率
//*****************************************************************************************
void SpiInit(void);
void CpuInit(void);
void RESET_CC1100(void);
void POWER_UP_RESET_CC1100(void);
void halSpiWriteReg(INT8U addr, INT8U value);
void halSpiWriteBurstReg(INT8U addr, INT8U *buffer, INT8U count);
void halSpiStrobe(INT8U strobe);
INT8U halSpiReadReg(INT8U addr);
void halSpiReadBurstReg(INT8U addr, INT8U *buffer, INT8U count);
INT8U halSpiReadStatus(INT8U addr);
void halRfWriteRfSettings(void);
void halRfSendPacket(INT8U *txBuffer, INT8U size);
INT8U halRfReceivePacket(INT8U *rxBuffer, INT8U *length); 
//*****************************************************************************************
// CC1100 STROBE, CONTROL AND STATUS REGSITER
#define CCxxx0_IOCFG2       0x00        // GDO2 output pin configuration
#define CCxxx0_IOCFG1       0x01        // GDO1 output pin configuration
#define CCxxx0_IOCFG0       0x02        // GDO0 output pin configuration
#define CCxxx0_FIFOTHR      0x03        // RX FIFO and TX FIFO thresholds
#define CCxxx0_SYNC1        0x04        // Sync word, high INT8U
#define CCxxx0_SYNC0        0x05        // Sync word, low INT8U
#define CCxxx0_PKTLEN       0x06        // Packet length
#define CCxxx0_PKTCTRL1     0x07        // Packet automation control
#define CCxxx0_PKTCTRL0     0x08        // Packet automation control
#define CCxxx0_ADDR         0x09        // Device address
#define CCxxx0_CHANNR       0x0A        // Channel number
#define CCxxx0_FSCTRL1      0x0B        // Frequency synthesizer control
#define CCxxx0_FSCTRL0      0x0C        // Frequency synthesizer control
#define CCxxx0_FREQ2        0x0D        // Frequency control word, high INT8U
#define CCxxx0_FREQ1        0x0E        // Frequency control word, middle INT8U
#define CCxxx0_FREQ0        0x0F        // Frequency control word, low INT8U
#define CCxxx0_MDMCFG4      0x10        // Modem configuration
#define CCxxx0_MDMCFG3      0x11        // Modem configuration
#define CCxxx0_MDMCFG2      0x12        // Modem configuration
#define CCxxx0_MDMCFG1      0x13        // Modem configuration
#define CCxxx0_MDMCFG0      0x14        // Modem configuration
#define CCxxx0_DEVIATN      0x15        // Modem deviation setting
#define CCxxx0_MCSM2        0x16        // Main Radio Control State Machine configuration
#define CCxxx0_MCSM1        0x17        // Main Radio Control State Machine configuration
#define CCxxx0_MCSM0        0x18        // Main Radio Control State Machine configuration
#define CCxxx0_FOCCFG       0x19        // Frequency Offset Compensation configuration
#define CCxxx0_BSCFG        0x1A        // Bit Synchronization configuration
#define CCxxx0_AGCCTRL2     0x1B        // AGC control
#define CCxxx0_AGCCTRL1     0x1C        // AGC control
#define CCxxx0_AGCCTRL0     0x1D        // AGC control
#define CCxxx0_WOREVT1      0x1E        // High INT8U Event 0 timeout
#define CCxxx0_WOREVT0      0x1F        // Low INT8U Event 0 timeout
#define CCxxx0_WORCTRL      0x20        // Wake On Radio control
#define CCxxx0_FREND1       0x21        // Front end RX configuration
#define CCxxx0_FREND0       0x22        // Front end TX configuration
#define CCxxx0_FSCAL3       0x23        // Frequency synthesizer calibration
#define CCxxx0_FSCAL2       0x24        // Frequency synthesizer calibration
#define CCxxx0_FSCAL1       0x25        // Frequency synthesizer calibration
#define CCxxx0_FSCAL0       0x26        // Frequency synthesizer calibration
#define CCxxx0_RCCTRL1      0x27        // RC oscillator configuration
#define CCxxx0_RCCTRL0      0x28        // RC oscillator configuration
#define CCxxx0_FSTEST       0x29        // Frequency synthesizer calibration control
#define CCxxx0_PTEST        0x2A        // Production test
#define CCxxx0_AGCTEST      0x2B        // AGC test
#define CCxxx0_TEST2        0x2C        // Various test settings
#define CCxxx0_TEST1        0x2D        // Various test settings
#define CCxxx0_TEST0        0x2E        // Various test settings
// Strobe commands
#define CCxxx0_SRES         0x30        // Reset chip.
#define CCxxx0_SFSTXON      0x31        // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
                                        // If in RX/TX: Go to a wait state where only the synthesizer is
                                        // running (for quick RX / TX turnaround).
#define CCxxx0_SXOFF        0x32        // Turn off crystal oscillator.
#define CCxxx0_SCAL         0x33        // Calibrate frequency synthesizer and turn it off
                                        // (enables quick start).
#define CCxxx0_SRX          0x34        // Enable RX. Perform calibration first if coming from IDLE and
                                        // MCSM0.FS_AUTOCAL=1.
#define CCxxx0_STX          0x35        // In IDLE state: Enable TX. Perform calibration first if
                                        // MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled:
                                        // Only go to TX if channel is clear.
#define CCxxx0_SIDLE        0x36        // Exit RX / TX, turn off frequency synthesizer and exit
                                        // Wake-On-Radio mode if applicable.
#define CCxxx0_SAFC         0x37        // Perform AFC adjustment of the frequency synthesizer
#define CCxxx0_SWOR         0x38        // Start automatic RX polling sequence (Wake-on-Radio)
#define CCxxx0_SPWD         0x39        // Enter power down mode when CSn goes high.
#define CCxxx0_SFRX         0x3A        // Flush the RX FIFO buffer.
#define CCxxx0_SFTX         0x3B        // Flush the TX FIFO buffer.
#define CCxxx0_SWORRST      0x3C        // Reset real time clock.
#define CCxxx0_SNOP         0x3D        // No operation. May be used to pad strobe commands to two
                                        // INT8Us for simpler software.
#define CCxxx0_PARTNUM      0x30
#define CCxxx0_VERSION      0x31
#define CCxxx0_FREQEST      0x32
#define CCxxx0_LQI          0x33
#define CCxxx0_RSSI         0x34
#define CCxxx0_MARCSTATE    0x35
#define CCxxx0_WORTIME1     0x36
#define CCxxx0_WORTIME0     0x37
#define CCxxx0_PKTSTATUS    0x38
#define CCxxx0_VCO_VC_DAC   0x39
#define CCxxx0_TXBYTES      0x3A
#define CCxxx0_RXBYTES      0x3B
#define CCxxx0_PATABLE      0x3E
#define CCxxx0_TXFIFO       0x3F
#define CCxxx0_RXFIFO       0x3F
// RF_SETTINGS is a data structure which contains all relevant CCxxx0 registers
typedef struct S_RF_SETTINGS
{
    INT8U FSCTRL2;   //自已加的
    INT8U FSCTRL1;   // Frequency synthesizer control.
    INT8U FSCTRL0;   // Frequency synthesizer control.
    INT8U FREQ2;     // Frequency control word, high INT8U.
    INT8U FREQ1;     // Frequency control word, middle INT8U.
    INT8U FREQ0;     // Frequency control word, low INT8U.
    INT8U MDMCFG4;   // Modem configuration.
    INT8U MDMCFG3;   // Modem configuration.
    INT8U MDMCFG2;   // Modem configuration.
    INT8U MDMCFG1;   // Modem configuration.
    INT8U MDMCFG0;   // Modem configuration.
    INT8U CHANNR;    // Channel number.
    INT8U DEVIATN;   // Modem deviation setting (when FSK modulation is enabled).
    INT8U FREND1;    // Front end RX configuration.
    INT8U FREND0;    // Front end RX configuration.
    INT8U MCSM0;     // Main Radio Control State Machine configuration.
    INT8U FOCCFG;    // Frequency Offset Compensation Configuration.
    INT8U BSCFG;     // Bit synchronization Configuration.
    INT8U AGCCTRL2;  // AGC control.
    INT8U AGCCTRL1;  // AGC control.
    INT8U AGCCTRL0;  // AGC control.
    INT8U FSCAL3;    // Frequency synthesizer calibration.
    INT8U FSCAL2;    // Frequency synthesizer calibration.
    INT8U FSCAL1;    // Frequency synthesizer calibration.
    INT8U FSCAL0;    // Frequency synthesizer calibration.
    INT8U FSTEST;    // Frequency synthesizer calibration control
    INT8U TEST2;     // Various test settings.
    INT8U TEST1;     // Various test settings.
    INT8U TEST0;     // Various test settings.
    INT8U IOCFG2;    // GDO2 output pin configuration
    INT8U IOCFG0;    // GDO0 output pin configuration
    INT8U PKTCTRL1;  // Packet automation control.
    INT8U PKTCTRL0;  // Packet automation control.
    INT8U ADDR;      // Device address.
    INT8U PKTLEN;    // Packet length.
} RF_SETTINGS;
/////////////////////////////////////////////////////////////////
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.
 //0xf6, // MDMCFG4 chang by allen
    0xF8,   // MDMCFG3   Modem configuration. 
 //0x83, // MDMCFG3 chang by allen   data rate = 2.398K
    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.
    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.
 0x01, //PKTCTRL0  crc disable chang by allen at 09.12.24
    0x00,   // ADDR      Device address.
    0x0c    // PKTLEN    Packet length.
};
//*****************************************************************************************
//函数名:delay(unsigned int s)
//输入:时间
//输出:无
//功能描述:普通廷时,内部用
//*****************************************************************************************  
static void delay(unsigned int s)
{
 unsigned int i;
 for(i=0; i<s; i++);
 for(i=0; i<s; i++);
}

void halWait(INT16U timeout) {
    do {
        _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
    } while (--timeout);
}

void SpiInit(void)
{
 CSN=0;
 SCK=0;
 CSN=1;
}
/*****************************************************************************************
//函数名:CpuInit()
//输入:无
//输出:无
//功能描述:SPI初始化程序
/*****************************************************************************************/
void CpuInit(void)
{
 SpiInit();
 delay(5000);
}
 
//*****************************************************************************************
//函数名:SpisendByte(INT8U dat)
//输入:发送的数据
//输出:无
//功能描述:SPI发送一个字节
//*****************************************************************************************
INT8U SpiTxRxByte(INT8U dat)
{
 INT8U i,temp;
 temp = 0;
 
 SCK = 0;
 for(i=0; i<8; i++)
 {
  if(dat & 0x80)
  {
   MOSI = 1;
  }
  else MOSI = 0;
  dat <<= 1;
  SCK = 1;
  _nop_();
  _nop_();
  temp <<= 1;
  if(MISO)temp++;
  SCK = 0;
  _nop_();
  _nop_(); 
 }
 return temp;
}
//*****************************************************************************************
//函数名:void RESET_CC1100(void)
//输入:无
//输出:无
//功能描述:复位CC1100
//*****************************************************************************************
void RESET_CC1100(void)
{
 CSN = 0;
 while (MISO);
    SpiTxRxByte(CCxxx0_SRES);   //写入复位命令
 while (MISO);
    CSN = 1;
}
//*****************************************************************************************
//函数名:void POWER_UP_RESET_CC1100(void)
//输入:无
//输出:无
//功能描述:上电复位CC1100
//*****************************************************************************************
void POWER_UP_RESET_CC1100(void)
{
 CSN = 1;
 halWait(1);
 CSN = 0;
 halWait(1);
 CSN = 1;
 halWait(41);
 RESET_CC1100();     //复位CC1100
}
//*****************************************************************************************
//函数名:void halSpiWriteReg(INT8U addr, INT8U value)
//输入:地址和配置字
//输出:无
//功能描述:SPI写寄存器
//*****************************************************************************************
void halSpiWriteReg(INT8U addr, INT8U value)
{
    CSN = 0;
    while (MISO);
    SpiTxRxByte(addr);  //写地址
    SpiTxRxByte(value);  //写入配置
    CSN = 1;
}
//*****************************************************************************************
//函数名:void halSpiWriteBurstReg(INT8U addr, INT8U *buffer, INT8U count)
//输入:地址,写入缓冲区,写入个数
//输出:无
//功能描述:SPI连续写配置寄存器
//*****************************************************************************************
void halSpiWriteBurstReg(INT8U addr, INT8U *buffer, INT8U count)
{
    INT8U i, temp;
 temp = addr | WRITE_BURST;
    CSN = 0;
    while (MISO);
    SpiTxRxByte(temp);
    for (i = 0; i < count; i++)
  {
        SpiTxRxByte(buffer[i]);
    }
    CSN = 1;
}
//*****************************************************************************************
//函数名:void halSpiStrobe(INT8U strobe)
//输入:命令
//输出:无
//功能描述:SPI写命令
//*****************************************************************************************
void halSpiStrobe(INT8U strobe)
{
    CSN = 0;
    while (MISO);
    SpiTxRxByte(strobe);  //写入命令
    CSN = 1;
}
 
 
//*****************************************************************************************
//函数名:INT8U halSpiReadReg(INT8U addr)
//输入:地址
//输出:该寄存器的配置字
//功能描述:SPI读寄存器
//*****************************************************************************************
INT8U halSpiReadReg(INT8U addr)
{
 INT8U temp, value;
    temp = addr|READ_SINGLE;//读寄存器命令
 CSN = 0;
 while (MISO);
 SpiTxRxByte(temp);
 value = SpiTxRxByte(0);
 CSN = 1;
 return value;
}

//*****************************************************************************************
//函数名:void halSpiReadBurstReg(INT8U addr, INT8U *buffer, INT8U count)
//输入:地址,读出数据后暂存的缓冲区,读出配置个数
//输出:无
//功能描述:SPI连续写配置寄存器
//*****************************************************************************************
void halSpiReadBurstReg(INT8U addr, INT8U *buffer, INT8U count)
{
    INT8U i,temp;
 temp = addr | READ_BURST;  //写入要读的配置寄存器地址和读命令
    CSN = 0;
    while (MISO);
 SpiTxRxByte(temp);  
    for (i = 0; i < count; i++)
 {
        buffer[i] = SpiTxRxByte(0);
    }
    CSN = 1;
}

//*****************************************************************************************
//函数名:INT8U halSpiReadReg(INT8U addr)
//输入:地址
//输出:该状态寄存器当前值
//功能描述:SPI读状态寄存器
//*****************************************************************************************
INT8U halSpiReadStatus(INT8U addr)
{
    INT8U value,temp;
 temp = addr | READ_BURST;  //写入要读的状态寄存器的地址同时写入读命令
    CSN = 0;
    while (MISO);
    SpiTxRxByte(temp);
 value = SpiTxRxByte(0);
 CSN = 1;
 return value;
}
//*****************************************************************************************
//函数名:void halRfWriteRfSettings(RF_SETTINGS *pRfSettings)
//输入:无
//输出:无
//功能描述:配置CC1100的寄存器
//*****************************************************************************************
void halRfWriteRfSettings(void)
{
 halSpiWriteReg(CCxxx0_FSCTRL0,  rfSettings.FSCTRL2);//自已加的
    // Write register settings
    halSpiWriteReg(CCxxx0_FSCTRL1,  rfSettings.FSCTRL1);
    halSpiWriteReg(CCxxx0_FSCTRL0,  rfSettings.FSCTRL0);
    halSpiWriteReg(CCxxx0_FREQ2,    rfSettings.FREQ2);
    halSpiWriteReg(CCxxx0_FREQ1,    rfSettings.FREQ1);
    halSpiWriteReg(CCxxx0_FREQ0,    rfSettings.FREQ0);
    halSpiWriteReg(CCxxx0_MDMCFG4,  rfSettings.MDMCFG4);
    halSpiWriteReg(CCxxx0_MDMCFG3,  rfSettings.MDMCFG3);
    halSpiWriteReg(CCxxx0_MDMCFG2,  rfSettings.MDMCFG2);
    halSpiWriteReg(CCxxx0_MDMCFG1,  rfSettings.MDMCFG1);
    halSpiWriteReg(CCxxx0_MDMCFG0,  rfSettings.MDMCFG0);
    halSpiWriteReg(CCxxx0_CHANNR,   rfSettings.CHANNR);
    halSpiWriteReg(CCxxx0_DEVIATN,  rfSettings.DEVIATN);
    halSpiWriteReg(CCxxx0_FREND1,   rfSettings.FREND1);
    halSpiWriteReg(CCxxx0_FREND0,   rfSettings.FREND0);
    halSpiWriteReg(CCxxx0_MCSM0 ,   rfSettings.MCSM0 );
    halSpiWriteReg(CCxxx0_FOCCFG,   rfSettings.FOCCFG);
    halSpiWriteReg(CCxxx0_BSCFG,    rfSettings.BSCFG);
    halSpiWriteReg(CCxxx0_AGCCTRL2, rfSettings.AGCCTRL2);
 halSpiWriteReg(CCxxx0_AGCCTRL1, rfSettings.AGCCTRL1);
    halSpiWriteReg(CCxxx0_AGCCTRL0, rfSettings.AGCCTRL0);
    halSpiWriteReg(CCxxx0_FSCAL3,   rfSettings.FSCAL3);
 halSpiWriteReg(CCxxx0_FSCAL2,   rfSettings.FSCAL2);
 halSpiWriteReg(CCxxx0_FSCAL1,   rfSettings.FSCAL1);
    halSpiWriteReg(CCxxx0_FSCAL0,   rfSettings.FSCAL0);
    halSpiWriteReg(CCxxx0_FSTEST,   rfSettings.FSTEST);
    halSpiWriteReg(CCxxx0_TEST2,    rfSettings.TEST2);
    halSpiWriteReg(CCxxx0_TEST1,    rfSettings.TEST1);
    halSpiWriteReg(CCxxx0_TEST0,    rfSettings.TEST0);
    halSpiWriteReg(CCxxx0_IOCFG2,   rfSettings.IOCFG2);
    halSpiWriteReg(CCxxx0_IOCFG0,   rfSettings.IOCFG0);   
    halSpiWriteReg(CCxxx0_PKTCTRL1, rfSettings.PKTCTRL1);
    halSpiWriteReg(CCxxx0_PKTCTRL0, rfSettings.PKTCTRL0);
    halSpiWriteReg(CCxxx0_ADDR,     rfSettings.ADDR);
    halSpiWriteReg(CCxxx0_PKTLEN,   rfSettings.PKTLEN);
}
//*****************************************************************************************
//函数名:void halRfSendPacket(INT8U *txBuffer, INT8U size)
//输入:发送的缓冲区,发送数据个数
//输出:无
//功能描述:CC1100发送一组数据
//*****************************************************************************************
void halRfSendPacket(INT8U *txBuffer, INT8U size)
{
 halSpiWriteReg(CCxxx0_TXFIFO, size);
    halSpiWriteBurstReg(CCxxx0_TXFIFO, txBuffer, size); //写入要发送的数据
    halSpiStrobe(CCxxx0_STX);  //进入发送模式发送数据
    // Wait for GDO0 to be set -> sync transmitted
    while (!GDO0);
    // Wait for GDO0 to be cleared -> end of packet
    while (GDO0);
 halSpiStrobe(CCxxx0_SFTX);
 delay(20);
}

void setRxMode(void)
{
    halSpiStrobe(CCxxx0_SRX);  //进入接收状态
}
/*
// Bit masks corresponding to STATE[2:0] in the status byte returned on MISO
#define CCxx00_STATE_BM                 0x70
#define CCxx00_FIFO_BYTES_AVAILABLE_BM  0x0F
#define CCxx00_STATE_TX_BM              0x20
#define CCxx00_STATE_TX_UNDERFLOW_BM    0x70
#define CCxx00_STATE_RX_BM              0x10
#define CCxx00_STATE_RX_OVERFLOW_BM     0x60
#define CCxx00_STATE_IDLE_BM            0x00
static INT8U RfGetRxStatus(void)
{
 INT8U temp, spiRxStatus1,spiRxStatus2;
 INT8U i=4;// 循环测试次数
    temp = CCxxx0_SNOP|READ_SINGLE;//读寄存器命令
 CSN = 0;
 while (MISO);
 SpiTxRxByte(temp);
 spiRxStatus1 = SpiTxRxByte(0);
 do
 {
  SpiTxRxByte(temp);
  spiRxStatus2 = SpiTxRxByte(0);
  if(spiRxStatus1 == spiRxStatus2)
  {
   if( (spiRxStatus1 & CCxx00_STATE_BM) == CCxx00_STATE_RX_OVERFLOW_BM)
   {
               halSpiStrobe(CCxxx0_SFRX);
      return 0;
   }
      return 1;
  }
   spiRxStatus1=spiRxStatus2;
 }
 while(i--);
 CSN = 1;
    return 0; 
}
 */
INT8U halRfReceivePacket(INT8U *rxBuffer, INT8U *length)
{
    INT8U status[2];
    INT8U packetLength;
 INT8U i=(*length)*4;  // 具体多少要根据datarate和length来决定
    halSpiStrobe(CCxxx0_SRX);  //进入接收状态
 //delay(5);
    //while (!GDO1);
    //while (GDO1);
 delay(2);
 while (GDO0)
 {
  delay(2);
  --i;
  if(i<1)
     return 0;     
 }
    if ((halSpiReadStatus(CCxxx0_RXBYTES) & BYTES_IN_RXFIFO)) //如果接的字节数不为0
 {
        //LED2 = 0;
  packetLength = halSpiReadReg(CCxxx0_RXFIFO);//读出第一个字节,此字节为该帧数据长度
        //if (packetLength <= *length)   //如果所要的有效数据长度小于等于接收到的数据包的长度
  if(packetLength == 0x08)
  {
            //halSpiReadBurstReg(CCxxx0_RXFIFO, rxBuffer, packetLength); //读出所有接收到的数据
   halSpiReadBurstReg(CCxxx0_RXFIFO, rxBuffer, 8); //读出所有接收到的数据
            *length = packetLength;    //把接收数据长度的修改为当前数据的长度
       
            // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
            //halSpiReadBurstReg(CCxxx0_RXFIFO, status, 2);  //读出CRC校验位
   halSpiStrobe(CCxxx0_SFRX);  //清洗接收缓冲区
  // delay(2);
  // halSpiStrobe(CCxxx0_SRX);  //进入接收状态
  // delay(20);
   //delay(200);
   return 1;
            //return (status[1] & CRC_OK);   //如果校验成功返回接收成功
        }
   else
  {
            *length = packetLength;
            halSpiStrobe(CCxxx0_SFRX);  //清洗接收缓冲区
  // delay(2);
  // halSpiStrobe(CCxxx0_SRX);  //进入接收状态
  // delay(20);
  // LED2 = 1;
            return 0;
        }
    }
  return 0;
}

void main(void)
{
 unsigned char key1_flag = 0;
 bit key2_flag = 0;
 unsigned int key1_scan_cnt = 400;
 unsigned int key2_scan_cnt = 300;
 INT8U i = 0;
 INT8U leng =0;
 INT8U tf =0;
 INT8U TxBuf[8]={1,2,3,4,5,6,7,8};  // 8字节, 如果需要更长的数据包,请正确设置
 INT8U RxBuf[8]={0}; 
 CpuInit();
 POWER_UP_RESET_CC1100();
 halRfWriteRfSettings();
 halSpiWriteBurstReg(CCxxx0_PATABLE, PaTabel, 8);
 //halSpiStrobe(CCxxx0_SRX);  //进入接收状态
 //setRxMode();
 while(1)
 {
     //setRxMode();
  delay(10);
     if(KEY1 == 0)
    {
   key1_scan_cnt--;
   if(!key1_scan_cnt)
   {   
    key1_scan_cnt = 300;
    if(key1_flag == 0)//判断按键是否第1次按下
    {
     key1_flag = 1;//按键第1次按下标志位 
    }
   }
     }
  else
  {
   key1_scan_cnt = 300;
   if(key1_flag == 1)//判断是否第一次按键动作松开
   {
    led1 = 0;
    led0 = 0;
    key1_flag = 2;
    key1_scan_cnt = 3;
    TxBuf[0] = 0x77;//第1个字节为0x77的数据帧,接收方收到后不需要返回应答
    while(1)
    {        
     halRfSendPacket(TxBuf,8); // Transmit Tx buffer data
     delay(100);    
     if(KEY1 == 0)//检测按键是否第2次按下
     {
      key1_scan_cnt--;
      if(!key1_scan_cnt)
      {
       key1_flag = 3;//按键第2次按下
       key1_scan_cnt = 300;
       led1 = 1;
       led0 = 1;
       break;//当按键再次按下时退出长发状态
      }
     }
     else//没有第2次的按键动作
     {
      key1_scan_cnt = 3;
     }
    }
   }
   else if(key1_flag == 3)//是否为第2次的按键动作松开
   {
    key1_flag = 0;
   }
  }
 
     if(KEY2 == 0)
    {
   key2_scan_cnt--;
   if(!key2_scan_cnt)//确认按键正常按下
   {   
    key2_scan_cnt = 300;    
    key2_flag = 1;//按键第1次按下标志位   
   }
     }
  else
  {
   key2_scan_cnt = 300;
   if(key2_flag)//按键弹起
   {
    LED1 = 0;
    key2_flag = 0;
    delay(1000);
    TxBuf[0] = 0x88;        
    halRfSendPacket(TxBuf,8);// Transmit Tx buffer data    
    LED1 = 1;   
   }
    }
  leng =8; // 预计接受8 bytes
     if(halRfReceivePacket(RxBuf,&leng))
 // if(!GDO0)
  {      
  // leng =8; // 预计接受8 bytes
  // if(halRfReceivePacket(RxBuf,&leng))
   {
    if(RxBuf[0] == 0x77)//接收到的数据不需要返回应答
    {
     LED2 = ~LED2;
    }
    else if(RxBuf[0] == 0x88)//判断接收到的数据是否需要返回应答
    {
     LED2 = 0;//接收数据正确,开接收指示灯
     LED1 = 0;//准备发送应答,开发送指示灯
     delay(1000);
     TxBuf[0] = 0x99;
     halRfSendPacket(TxBuf,8); // Transmit Tx buffer data  返回应答
     LED2 = 1;
     LED1 = 1;
    }
    else if(RxBuf[0] == 0x99)//应答数据
    {
     LED2 = 0;
     delay(1000);
     LED2 = 1;
    }
   }
  }
 } 
}
关闭窗口

相关文章