⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfmodem_cc1020.c

📁 无线射频收发芯片cc1020的校准程序代码
💻 C
字号:
/****************************************************************************/
/* Reference design : CC1020 RF Modem                                       */
/*                                                                          */
/* File:    rfmodem_cc1020.c                                                */
/*                                                                          */
/* Microcontroller:                                                         */
/*          Microchip PIC16F876                                             */
/*                                                                          */
/* Author:  Karl H. Torvmark, Field Applications Engineer, Chipcon          */
/*          Torgeir Sundet, FAE - Software                                  */
/*                                                                          */
/* Contact: Chipcon AS +47 22 95 85 44                                      */
/*          support@chipcon.com                                            */
/****************************************************************************/


/****************************************************************************/
/* Description:                                                             */
/*                                                                          */
/* This application note presents a software and hardware reference design  */
/* for the CC1020. This software can serve as a starting point for          */
/* developing custom software. A full protocol is implemented, with         */
/* provisions for addressing, error checking etc.                           */
/*                                                                          */
/* This software contains routines for detecting the preamble, searching    */
/* for the start-of-frame (SOF) marker and doing byte synchronisation,      */
/* and reading and handling header data such as the packet length.          */
/*                                                                          */
/* The software also contains all necessary routines to configure the       */
/* CC1020, and demonstrates how to read and write data to the data          */
/* interface. Configuration data is stored in non-volatile EEPROM memory,   */
/* so that changes are preserved even when power is removed. Easy           */
/* modification of parameters such as RF frequency and data rate is         */
/* supported through a configuration menu.                                  */
/*                                                                          */
/****************************************************************************/

/*                                                                           *
 * Revision history:                                                         *
 *                                                                           *
 * $Log: rfmodem_cc1020.c,v $
 * Revision 1.4  2005/11/22 14:30:24  tos
 * Mods:
 * - Tydied-up implementation of RSSI measurement.
 * - Removed obsolete code (AGC freeze).
 * - Made button monitor purely Timer-resource independant.
 *
 * Revision 1.3  2004/03/23 16:44:25  tos
 * Introduced RSSI measurement (based on algorithm in SmartRF Studio).
 *
 * Revision 1.2  2003/09/17 15:03:07  tos
 * Mod's:
 *   - introduced new menu option ('J'): access (w/r) CC1020 register.
 *   - update EEPROM variable+table upon register write access ('J').
 *   - introduced new configuration option ('I'): preamble length.
 *   - moved TX buffer initialisation after configuration.
 *   - corrected inconsistent number conversion funtion.
 *
 * Revision 1.1  2003/07/31 13:17:30  tos
 * Initial version in CVS.
 *
 *
 *                                                                           *
 ****************************************************************************/

#include "io16f876.h"
#include "inpic.h"
#include "CC1020.h"
#include "modemhw.h"
#include "configure.h"
#include "main.h"
#include "simpleio.h"
#include <stdio.h>

#define INTERRUPT_VECTOR 0x04

// The wrap-around functionality has been optimised by ANDing with a bit mask. 
// Please note that if RX_BUFFER_SIZE is to be changed, the lines of code which
// do this must also be changed.

// Variables

// Unit address is not used
extern __eeprom char UnitAddress;

// Union for shifting bits in or out of the CC1020
union {
  char ShiftReg;
  struct {
    unsigned char ShiftRegLSB :1;
    unsigned char :1;
    unsigned char :1;
    unsigned char :1;
    unsigned char :1;
    unsigned char :1;
    unsigned char :1;
    unsigned char ShiftRegMSB :1;
  };
};
                                 
// Buffers for transmitted and received data
// These are put into different banks so that they can be as large as possible
// The TX buffer is filled up with data to be sent in the next data packet
// The RX buffer is a ring buffer in which received data is stored waiting to be
// sent to the UART

volatile __bank1 char TXBuffer[TX_BUFFER_SIZE];
volatile __bank2 char RXBuffer[RX_BUFFER_SIZE];

// Index pointers for use with buffers 
volatile char TXBufferIndex;
char RXBufferReadIndex;
volatile char RXBufferWriteIndex;

// Counter variables
char PreambleCount;
char PreambleError;
char ByteCounter;
char BitCounter;

// Contains the total number of bytes to send in TX, including preamble and header
char BytesToSend;
// The number of bytes of data to receive in RX
char BytesToReceive;

// State variable stores the current state of the state machine
volatile enum StateType State;

// This variable stores the state to switch to
// It is updated by the interrupt routine, while the main program
// does the actual state switch
volatile enum StateType NextState;

// This struct stores various flags in a space-efficient manner
volatile struct
{
  unsigned char PreambleFound:1;
  unsigned char UI1Found:1;
  unsigned char LastPreambleBit:1;
  unsigned char LastDataBit:1;
};


// This routine initialises the TX buffer at startup
void InitializeTXBuffer(void)
{
  char i;

  // Put preamble into buffer
  for(i=0;i<PreambleLength;i++){
    TXBuffer[i]=PREAMBLE_BYTE;
  }

  TXBuffer[PreambleLength+0]=UI1;            // First byte of unique identifier
  TXBuffer[PreambleLength+1]=UI2;            // Second byte of unique identifier
  TXBuffer[PreambleLength+2]=UnitAddress;    // Unit address
  TXBuffer[PreambleLength+3]=0x00;           // Data length, default : no data
}


// This routine handles setup needed when changing states
void ChangeState(void)
{
  switch(NextState){
    case RX_STATE:
      if(State==TX_STATE){
        OPTION=0xC0;        // INT on rising edge
        TRISC|=0x02;        // Set DIO as input
        SetupCC1020RX(RXANALOG, PA_POWER);
      }

      State=RX_STATE;

      SET_RXLED(ON);
      SET_TXLED(OFF);
      READY=1;  // HW Handshake : Not Ready

      BitCounter=0;
      ByteCounter=0;
      break;

    case TX_STATE:
      if(State!=TX_STATE){
        OPTION=0x80;        // INT on falling edge
        TRISC&=~(0x02);     // Set DIO as output
        SetupCC1020TX(TXANALOG, PA_POWER);
      }

      State=TX_STATE;

      SET_RXLED(OFF);
      SET_TXLED(ON);
      READY=1;  // HW Handshake : Not Ready
      RCIE=0;   // Disable UART Interrupts

      BytesToSend=TXBufferIndex; // Number of bytes to send

      TXBuffer[PreambleLength+3]=BytesToSend-HEADER_SIZE-PreambleLength;

      LastDataBit = FALSE;
      TXBufferIndex=0;
      BitCounter=0;
      ShiftReg=TXBuffer[TXBufferIndex++];
      break;

    case IDLE_STATE:
      if(State==TX_STATE){
        OPTION=0xC0;        // INT on rising edge
        TRISC|=0x02;        // Set DIO as input
        SetupCC1020RX(RXANALOG, PA_POWER);
      }

      State=IDLE_STATE;

      SET_RXLED(OFF);
      SET_TXLED(OFF);
      READY=0;  // HW Handshake : Ready
      RCIE=1;   // Enable UART Interrupts

      TXBufferIndex=HEADER_SIZE+PreambleLength;
      PreambleCount=0;
      PreambleError=0;
      PreambleFound=FALSE;
      UI1Found=FALSE;
      break;
  }
}



// Main program
void main(void)
{
  char dummy;
  volatile int i = 0;
  volatile char PacketCount = 0;
  volatile int  button_monitor = BUTTON_TIMEOUT;
  volatile int rssi_dBm;

  PORTC=0x00;
  TRISC=0x92;

  PORTB=0x00;
  TRISB=0xFD;

  PORTA=0x00;
  TRISA=0x0B;

  ADCON0=0x89;  
  ADCON1=0x84;

  TXSTA=0x24;
  RCSTA=0x90;
  SPBRG=10;  // 10.0000MHz, 57600baud

  TMR1L=0x00;
  TMR1H=0x00;
  T1CON=0x31; // Enable timer 1

  #ifdef SPI
  // Configure SPI
  SetupCC1020ForSPI();
  #endif

  //PIE1=0x21; // UART and timer 1 enabled

  PIE1=0x00;

  // Timer 2 time-out value
  // Set to 10ms at 10MHz = 25000 instructions
  T2CON=0x4B;
  PR2=0xFF;

  PSEL=1;

  RXBufferReadIndex=0;
  RXBufferWriteIndex=0;

  SetupCC1020PD();
  ResetCC1020();

  SetupCC1020All();

  WakeUpCC1020ToTX(TXANALOG);
  OPTION=0x80;        // INT on falling edge
  TRISC&=~(0x02);     // Set DIO as output
  if (!CalibrateCC1020(PA_POWER))
    writeln("TX Calibration failed");
  // Calibration data is stored in the chip indexed by the selected frequency register 

  WakeUpCC1020ToRX(RXANALOG);
  OPTION=0xC0;        // INT on rising edge
  TRISC|=0x02;        // Set DIO as input
  if (!CalibrateCC1020(PA_POWER))
    writeln("RX Calibration failed");

  // Now the CC1020 is calibrated for both RX and TX, we do not need to recalibrate
  // unless the frequency is changed, the temperature changes by 40 degrees C
  // or if the supply voltage changes by more than 0.5V 

  // Force update
  State=TX_STATE;
  NextState=IDLE_STATE;

  // Set all buttons to light, if we want to turn them off, we set them as inputs to avoid
  // the output being shorted to VDD if a button is pressed
  CARRIER_LED=0;
  RD_LED=0;
  TD_LED=0;

  dummy=TRISA;
  TRISA|=0x24;
  if(BUTTON1==0){
  }
  if(BUTTON2==0){
    ConfigurationMode();
  }

  InitializeTXBuffer();

  TRISA=dummy;

  AWAKE=0;
  SYNC=0;

  LastDataBit = FALSE;
  
  // Startup message
  writeln("RF Modem ready");
  writestr("Compiled ");
  writestr(__DATE__);
  writestr(" ");
  writestr(__TIME__);
  writeln("");

  if((ReadFromCC1020Register(CC1020_ANALOG)&0x80)==0x80){
    writestr("804-940 MHz band");
  }else{
    writestr("402-470 MHz band");
  }

  writestr(", 4.8 kbit/s");
  if((ReadFromCC1020Register(CC1020_MODEM)&0x03)==0x01){
    writestr(", Manchester mode");
  }else{
    writestr(", NRZ mode");
  }

  writeln("");

  INTCON=0x90;

  // Monitor input from UART+RF+BUTTONS and select corresponding state:
  while(1){    
    // If new state requested, enter requested state
    if(State!=NextState){
      ChangeState();
    }

    // If received RF data, send it to the serial port
    if(RXBufferReadIndex!=RXBufferWriteIndex){

      if(RXBuffer[RXBufferReadIndex] != EOT){
        putchar(RXBuffer[RXBufferReadIndex]);
      }else{
        // Display RSSI level:
        VT100_CLEAR_LINE_RIGHT();
        rssi_dBm = ReadRSSIlevelCC1020();
        writestr("   RSSI = ");
        if(rssi_dBm < 0) {
          writestr("- ");
          writeint(-rssi_dBm);
        }else if(rssi_dBm > 0) {
          writestr("+ ");
          writeint(rssi_dBm);
        }else{
          writestr("  0");
        }
        writestr(" [dBm]");
        VT100_GO_START_LEFT();
      }

      //RXBufferReadIndex=(RXBufferReadIndex+1)%RX_BUFFER_SIZE;
      RXBufferReadIndex++;
      RXBufferReadIndex&=0x3F;
    }

    // If received UART data and RF in IDLE state, copy UART data into RF packet
    if(RCIF==1){
      if(State==IDLE_STATE){
        TMR2=0;   // Reset time-out timer
        TMR2ON=1; // Start time-out timer

        // TODO : Handle framing and overflow errors
        if(OERR){
          TXEN=0;
          TXEN=1;
          CREN=0;
          CREN=1;
        }
        if(FERR){
          dummy=RCREG;
          TXEN=0;
          TXEN=1;
        }

        // Read data from UART
        TXBuffer[TXBufferIndex++]=RCREG;

        // IMPORTANT:
        // We may have another interrupt or two occur before we can change mode.
        // Therefore, leave safety margin!
        if(TXBufferIndex>=(TX_BUFFER_SIZE-3)){
          NextState=TX_STATE;
        }

        RCIF=0;
      }
    }

    // If Timer-2 timeout (since received last UART data)
    if(TMR2IF==1){
      // Request TX state to send last UART data via RF
      TMR2ON=0;
      TMR2IE=0;
      NextState=TX_STATE;
      TMR2IF=0;
    }

    dummy=TRISA;
    TRISA|=0x24;  // Set port to read button status 

    if((State==IDLE_STATE) && ((BUTTON1 == 0) || (BUTTON2 == 0))){
      if(button_monitor-- < 0){
        button_monitor = BUTTON_TIMEOUT;
        PacketCount = ((PacketCount+1 > 9) ? 0 : (PacketCount+1));
        TXBuffer[TXBufferIndex++] = (BUTTON1 == 0) ? Button1Char:Button2Char;
        TXBuffer[TXBufferIndex++] = PacketCount+'0';
        TXBuffer[TXBufferIndex++] = EOT;
        NextState = TX_STATE;
      }
    }else{
      button_monitor = BUTTON_TIMEOUT;
    }

    TRISA=dummy;  // Set port back to LED operation 
    TMR1IF=0;

  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -