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

📄 cc1000if.c

📁 The CC1000 RF transceiver is very easy to interface with a microcontroller. The chip is configured
💻 C
字号:
/****************************************************************************/
/* Application note AN009                                                   */
/* CC1000 MCU Interfacing                                                   */
/*                                                                          */
/* File:    cc1000if.c                                                      */
/*                                                                          */
/* Microcontroller:                                                         */
/*          Microchip PIC16F876 (written for the IAR C compiler)            */
/*                                                                          */
/* Note that all RF setting constants in this file are for 868.3MHz default */
/* settings. Use SmartRF(R) Studio to calculate the settings for your       */
/* specific application                                                     */
/*                                                                          */
/* Several comments specifying wait routines has been inserted into this    */
/* file. As it is impossible to provide this routine without knowing        */
/* the compiler and crystal frequency used for the MCU, these comments must */
/* be replaced with wait routines by the user of this code.                 */
/*                                                                          */
/* Author:  Karl H. Torvmark, Field Applications Engineer, Chipcon          */
/*                                                                          */
/* Contact: Chipcon AS +47 22 95 85 44                                      */
/*          wireless@chipcon.com                                            */
/****************************************************************************/

#include "io16f876.h"
#include "inpic.h"
#include "CC1000.h"
#include <stdio.h>

/* Pin usage definitions */
#define PDATA       RC0
#define PCLK        RC1
#define PALE        RC2
#define DIO         RC3
#define DCLK        RB0
#define CHP_OUT     RC5


/* The location of the interrupt handler vector. Must be changed for */
/* different PIC MCUs */
#define INTERRUPT_VECTOR 0x04 


/* Configuration values for registers other than MAIN */
/* Replace these values with new values calculated by */
/* SmartRF(R) Studio for your application */

short Config[28] = 
  {0x0262, 0x0400, 0x0600, 0x0862, 0x0A03, 0x0C6A, 0x0E03, 0x1055, 
   0x128F, 0x1432, 0x16FF, 0x1828, 0x1A10, 0x1C25, 0x1E8D, 0x2061,
   0x2222, 0x2420, 0x2601, 0x281C, 0x2A16, 0x2C10, 0x2E0A, 0x3006,
   0x3203, 0x3401, 0x360D, 0x3800};
   
/* Contents of CURRENT register for TX and RX, use SmartRF(R) Studio */
/* to find values for your application */   
 
#define TX_CURRENT 0xF3
#define RX_CURRENT 0x8C

/****************************************************************************/
/*  This routine sends new configuration data to the CC1000                 */
/****************************************************************************/

void ConfigureCC1000(char Count, short Configuration[])
{
  char  BitCounter;
  char  WordCounter;
  union {     /* This union is used to easily access the most significant */
              /* bit of the configuration data */
              
              /* Note : This assumes that the C compiler stores bit-fields */
              /* with the first field going into the LSB. If this is not the */
              /* case, move the MSB definition to the first bit */
    unsigned short Data;
    struct
    {
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short :1;
      unsigned short MSB :1;
     };
  };
  
  PALE=1;
  
  for (WordCounter=0;WordCounter<Count;WordCounter++)
  {
    Data=Configuration[WordCounter];
    PALE=0;
    
    /* Send address bits */
    for (BitCounter=0;BitCounter<7;BitCounter++)
    {
      PCLK=1;
      PDATA=MSB;
      Data=Data<<1;
      PCLK=0;
    }
    /* Send read/write bit */
    /* Ignore bit in data, always use 1 */
    
    PCLK=1;
    PDATA=1;
    PCLK=0;
    Data=Data<<1;
    PCLK=1;
    PALE=1;
    
    /* Send data bits */
    
    for (BitCounter=0;BitCounter<8;BitCounter++)
    {
      PCLK=1;
      PDATA=MSB;
      Data=Data<<1;
      PCLK=0;
     }
  PCLK=1;
  }   /* Finished with word */   
}

/****************************************************************************/
/*  This routine writes to a single CC1000 register                         */
/****************************************************************************/

void WriteToCC1000Register(char addr, char data)
{
  short val;
  
  val=(addr&0x7F)<<9 | (data&0xFF);
  ConfigureCC1000(1,&val);
}

/****************************************************************************/
/*  This routine reads from a single CC1000 register                        */
/****************************************************************************/

char ReadFromCC1000Register(char addr)
{
  char BitCounter;
  
  union {     /* This unit is used to easily access the most significant */
              /* bit of the configuration data */

              /* Note : This assumes that the C compiler stores bit-fields */
              /* with the first field going into the LSB. If this is not the */
              /* case, switch the MSB and LSB definitions */
    unsigned char Data;
    struct
    {
      unsigned char LSB :1;
      unsigned char :1;
      unsigned char :1;
      unsigned char :1;
      unsigned char :1;
      unsigned char :1;
      unsigned char :1;
      unsigned char MSB :1;
     };
  };
  
  PALE=1;
  
  Data=addr<<1;
  PALE=0;
    
  /* Send address bits */
  for (BitCounter=0;BitCounter<7;BitCounter++)
  {
    PCLK=1;
    PDATA=MSB;
    Data=Data<<1;
    PCLK=0;
  }
  /* Send read/write bit */
  /* Ignore bit in data, always use 0 */
  
  PCLK=1;
  PDATA=0;
  PCLK=0;
 
 
  PCLK=1;
  PALE=1;
    
  /* Receive data bits */
  
  PDATA=1;
   
  TRISC|=0x01; /* Set up PDATA as an input */
    
  for (BitCounter=0;BitCounter<8;BitCounter++)
  {
    PCLK=0;
    Data=Data<<1;
    LSB=PDATA;
    PCLK=1;
  }
  
  
  TRISC&=~0x01; /* Set up PDATA as an output again */
  
  return Data;
}
  
/****************************************************************************/
/*  This routine resets the CC1000, clearing all registers.                 */
/****************************************************************************/  

void ResetCC1000(void)
{
  char MainValue;
  
  MainValue=ReadFromCC1000Register(CC1000_MAIN);
  WriteToCC1000Register(CC1000_MAIN,MainValue & 0xFE);         /* Reset CC1000 */
  WriteToCC1000Register(CC1000_MAIN,MainValue | 0x01);         /* Bring CC1000 out of reset */
}


/* Configures CC1000 according to values in Config[] array */
void SetupCC1000All(void)
{ 

  ConfigureCC1000(28,Config);
}

/****************************************************************************/
/*  This routine calibrates the CC1000                                      */
/****************************************************************************/

void CalibrateCC1000(void)
{
  char PAVal;
  

  PAVal=ReadFromCC1000Register(CC1000_PA_POW);  /* Store PA settings */
  WriteToCC1000Register(CC1000_PA_POW,0x00); /* Turn off PA to avoid spurs */
                                             /* during calibration in TX mode */
  WriteToCC1000Register(CC1000_CAL,0xA5); /* Start calibration */
  
  while((ReadFromCC1000Register(CC1000_CAL)&0x08)==0);  /* Wait until calibration finished */
  
  WriteToCC1000Register(CC1000_CAL,0x25); /* End calibration */
  WriteToCC1000Register(CC1000_PA_POW,PAVal); /* Restore PA setting */
}

/****************************************************************************/
/*  This routine puts the CC1000 into RX mode (from TX). When switching to  */
/*  RX from PD, use WakeupC1000ToRX first                                   */
/****************************************************************************/


void SetupCC1000RX(void)
{
  WriteToCC1000Register(CC1000_MAIN,0x31);    /* Switch into RX, switch to freq. reg A */
  WriteToCC1000Register(CC1000_CURRENT,RX_CURRENT); /* Program VCO current for RX */
  /* Insert 150us wait here */
  
  WriteToCC1000Register(CC1000_MAIN,0x11);    /* Switch RX part of CC1000 on */
}

/****************************************************************************/
/*  This routine puts the CC1000 into TX mode (from RX). When switching to  */
/*  TX from PD, use WakeupCC1000ToTX first                                  */
/****************************************************************************/

void SetupCC1000TX(void)
{
  WriteToCC1000Register(CC1000_MAIN,0xF1);    /* Switch into TX, switch to freq. reg B */
  WriteToCC1000Register(CC1000_CURRENT,TX_CURRENT); /* Program VCO current for TX */
  /* Insert 150us wait here */
                                              
  WriteToCC1000Register(CC1000_MAIN,0xA1);    /* Switch TX part of CC1000 on */
}

/****************************************************************************/
/*  This routine puts the CC1000 into power down mode. Use WakeUpCC1000ToRX */
/*  followed by SetupCC1000RX or WakeupCC1000ToTX followed by SetupCC1000TX */
/*  to wake up from power down                                              */
/****************************************************************************/

void SetupCC1000PD(void)
{
  WriteToCC1000Register(CC1000_MAIN,0x3F);  /* Put CC1000 into power-down */
}

/****************************************************************************/
/*  This routine wakes the CC1000 up from PD mode to RX mode, call          */
/*  SetupCC1000RX after this routine is finished.                           */
/****************************************************************************/

void WakeUpCC1000ToRX(void)
{
  WriteToCC1000Register(CC1000_MAIN,0x3B);  /* Turn on xtal oscillator core */
  
  WriteToCC1000Register(CC1000_CURRENT,RX_CURRENT); /* Program VCO current for RX */
  
  /* Insert wait routine here, must wait for xtal oscillator to stabilise, */
  /* typically takes 2-5ms. */
  
  WriteToCC1000Register(CC1000_MAIN,0x39);  /* Turn on bias generator */
  
  /* Insert 200us wait here */
  
  WriteToCC1000Register(CC1000_MAIN,0x31);  /* Turn on frequency synthesiser */
  
  /* Insert 250us wait here */
}

/****************************************************************************/
/*  This routine wakes the CC1000 up from PD mode to TX mode, call          */
/*  SetupCC1000TX after this routine is finished.                           */
/****************************************************************************/

void WakeUpCC1000ToTX(void)
{
  WriteToCC1000Register(CC1000_MAIN,0xFB);  /* Turn on xtal oscillator core */
  
  WriteToCC1000Register(CC1000_CURRENT,TX_CURRENT); /* Program VCO current for TX */
  
  /* Insert wait routine here, must wait for xtal oscillator to stabilise, */
  /* typically takes 2-5ms. */
  
  WriteToCC1000Register(CC1000_MAIN,0xF9);  /* Turn on bias generator */
  
  /* Insert 200us wait here */
  
  WriteToCC1000Register(CC1000_MAIN,0xF1);  /* Turn on frequency synthesiser */
  
  /* Insert 250us wait here */
}


void AverageManualLockCC1000(void)
{
  WriteToCC1000Register(CC1000_MODEM1,0x19);
}

void AverageFreeRunCC1000(void)
{
  WriteToCC1000Register(CC1000_MODEM1,0x09);
}

void AverageAutoLockCC1000(void)
{
  WriteToCC1000Register(CC1000_MODEM1,0x01);
}

void ReadCurrentCalibration(char *val1, char *val2)
{
  *val1=ReadFromCC1000Register(CC1000_TEST0);
  *val2=ReadFromCC1000Register(CC1000_TEST2);
}

void OverrideCurrentCalibration(char val1, char val2)
{
  WriteToCC1000Register(CC1000_TEST5,(val1&0x0F)|0x10);
  WriteToCC1000Register(CC1000_TEST6,(val2&0x1F)|0x20);
}

void StopOverridingCalibration(void)
{
  WriteToCC1000Register(CC1000_TEST5,0x00);
  WriteToCC1000Register(CC1000_TEST6,0x00);
}
  


char last;

/****************************************************************************/
/*  Interrupt routine which writes new data to the DIO pin each time the    */
/*  external interrupt occurs. This is an example of how a program can      */
/*  provide data in TX mode.                                                */
/****************************************************************************/

#pragma vector=INTERRUPT_VECTOR
__interrupt void InterruptHandler(void)
{
  /* Time to write DIO */
  
  if (last==0) {
    last=1;
    DIO=1;
  } else {
    last=0;
    DIO=0;
  }
  
  INTF=0;
  
  
}

/* Main program starts here */

void main(void)
{

  /* Set up the MCU registers */
  
  PORTC=0x00;
  TRISC=0xA0;
  
  PORTB=0x00;
  TRISB=0xF9;
  
  PORTA=0x00;
  TRISA=0x0B;  
  ADCON1=0x84;
  
  TXSTA=0x24;
  RCSTA=0x90;
  SPBRG=129;
  PORTA=0xFF;
  
  PIE1=0x00;
  T1CON=0x00;
  
  OPTION=0x00;
  

  /* Start of recommended power-up routine */
  
  SetupCC1000PD();                /* Initialise MAIN register */
  
  ResetCC1000();                  /* Reset CC1000 */

  SetupCC1000All();               /* Set up CC1000 registers */
  
  /* Calibrate both RX and TX */
  
  WakeUpCC1000ToRX();             /* Wake up CC1000 to RX mode */
  
   
  SetupCC1000RX();                /* Put CC1000 into RX mode */
  CalibrateCC1000();              /* Calibrate CC1000 */
  
  SetupCC1000TX();                /* Put CC1000 into TX mode */
  CalibrateCC1000();              /* Calibrate CC1000 */
  
  SetupCC1000PD();                /* Put CC1000 into PD mode */
  
  /* Wake up into TX mode */
  
  WakeUpCC1000ToTX();             /* Wake up CC1000 from PD */
  SetupCC1000TX();                /* Put CC1000 into TX mode */
  
  /* Enable external interrupt */
  INTCON=0xD0;
  
  while(1==1) {  
  /* Infinite loop, insert your code here */
  }
    

  
}

⌨️ 快捷键说明

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