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

📄 cc1020pic.c

📁 cc1020操作源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif
  
/****************************************************************************/
/*  This routine resets the CC1020, clearing all registers.                 */
/****************************************************************************/  

void ResetCC1020(void)
{
  // Reset CC1020
  WriteToCC1020Register(CC1020_MAIN, 0x0F&~0x01);

  // Bring CC1020 out of reset
  WriteToCC1020Register(CC1020_MAIN, 0x1F);
}


/****************************************************************************/
/*  This routine calibrates the CC1020                                      */
/*  Returns 0 if calibration fails, non-zero otherwise. Checks the LOCK     */
/*  to check for success.                                                   */
/****************************************************************************/

char CalibrateCC1020(char PA_POWER)
{
  volatile int TimeOutCounter;
  volatile int nCalAttempt;

  // Turn off PA to avoid spurs during calibration in TX mode
  WriteToCC1020Register(CC1020_PA_POWER,0x00);

  // Calibrate, and re-calibrate if necessary:
  for (nCalAttempt = CAL_ATTEMPT_MAX; (nCalAttempt>0); nCalAttempt--) {

    // Start calibration
    WriteToCC1020Register(CC1020_CALIBRATE,0xB4);

    // Monitor actual calibration start (ref. Errata Note 04 - CC1020)
    for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x80)&&(TimeOutCounter>0); TimeOutCounter--);
    // Important note:
    // In active mode the CC1020 should theoretically initiate an internal action/process more or less
    // instantly upon receiving any command from e.g. an MCU. However, upon sending a [calibration start]
    // command to CC1020, tests shows that the [STATUS.CAL_COMPLETE]-signal sometimes remains asserted
    // (or idle) close to 100 usec after the command has been originally issued. Consequently this process
    // must be carefully monitored to avoid premature PLL LOCK monitoring; do not proceed with subsequent
    // PLL LOCK monitoring before the calibration has actually completed inside the CC1020! Errata Note 04
    // suggests that [calibration start] should be monitored by a fixed timeout > 100 usec. However, the
    // above method implements an adaptive monitoring of [calibration start], which basically waits for the
    // [STATUS.CAL_COMPLETE]-signal to initialise/deassert (indicating calibration has actually started)
    // before proceeding with monitoring calibration complete and PLL LOCK. Chipcon considers both methods
    // safe, and thus leaves it up to the user, which one to use.

    // Monitor calibration complete
    for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);

    // Monitor lock
    for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);

    // Abort further recalibration attempts if successful LOCK
    if((ReadFromCC1020Register(CC1020_STATUS)&0x10) == 0x10) {
      break;
    }
  }

  // Restore PA setting
  WriteToCC1020Register(CC1020_PA_POWER, PA_POWER);

  // Return state of LOCK_CONTINUOUS bit
  return ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10);
}

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

char SetupCC1020RX(char RXANALOG, char PA_POWER)
{
  volatile int TimeOutCounter;
  char lock_status;

  // Switch into RX, switch to freq. reg A
  WriteToCC1020Register(CC1020_MAIN,0x11);

  // Setup bias current adjustment
  WriteToCC1020Register(CC1020_ANALOG,RXANALOG);

  // Monitor LOCK
  for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);

  // If PLL in lock
  if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
    // Indicate PLL in LOCK
    lock_status = LOCK_OK;
  // Else (PLL out of LOCK)
  }else{
    // If recalibration ok
    if(CalibrateCC1020(PA_POWER)){
      // Indicate PLL in LOCK
      lock_status = LOCK_RECAL_OK;
    // Else (recalibration failed)
    }else{
      // Indicate PLL out of LOCK
      lock_status = LOCK_NOK;
    }
  }

  // Switch RX part of CC1020 on
  WriteToCC1020Register(CC1020_MAIN,0x01);

  // Return LOCK status to application
  return (lock_status);
}

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

char SetupCC1020TX(char TXANALOG, char PA_POWER)
{
  volatile int TimeOutCounter;
  char lock_status;

  // Turn off PA to avoid frequency splatter
  WriteToCC1020Register(CC1020_PA_POWER,0x00);

  // Setup bias current adjustment
  WriteToCC1020Register(CC1020_ANALOG,TXANALOG);

  // Switch into TX, switch to freq. reg B
  WriteToCC1020Register(CC1020_MAIN,0xC1);

  // Monitor LOCK
  for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);

  // If PLL in lock
  if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
    // Indicate PLL in LOCK
    lock_status = LOCK_OK;
  // Else (PLL out of LOCK)
  }else{
    // If recalibration ok
    if(CalibrateCC1020(PA_POWER)){
      // Indicate PLL in LOCK
      lock_status = LOCK_RECAL_OK;
    // Else (recalibration failed)
    }else{
      // Indicate PLL out of LOCK
      lock_status = LOCK_NOK;
    }
  }

  // Restore PA setting
  WriteToCC1020Register(CC1020_PA_POWER,PA_POWER);

  // Turn OFF DCLK squelch in TX
  WriteToCC1020Register(CC1020_INTERFACE,ReadFromCC1020Register(CC1020_INTERFACE)&~0x10);

  // Return LOCK status to application
  return (lock_status);
}

/****************************************************************************/
/*  This routine puts the CC1020 into power down mode. Use WakeUpCC1020ToRX */
/*  followed by SetupCC1020RX or WakeupCC1020ToTX followed by SetupCC1020TX */
/*  to wake up from power down                                              */
/****************************************************************************/

void SetupCC1020PD(void)
{
  // Put CC1020 into power-down
  WriteToCC1020Register(CC1020_MAIN,0x1F);

  // Turn off PA to minimise current draw
  WriteToCC1020Register(CC1020_PA_POWER,0x00);
}

/****************************************************************************/
/*  This routine wakes the CC1020 up from PD mode to RX mode                */
/****************************************************************************/

void WakeUpCC1020ToRX(char RXANALOG)
{
  volatile int i;

  // Turn on xtal oscillator core
  WriteToCC1020Register(CC1020_MAIN,0x1B);

  // Setup bias current adjustment
  WriteToCC1020Register(CC1020_ANALOG,RXANALOG);

  // Insert wait routine here, must wait for xtal oscillator to stabilise, 
  // typically takes 2-5ms.
  for (i=0x0260; i > 0; i--);

  // Turn on bias generator
  WriteToCC1020Register(CC1020_MAIN,0x19);

  // Wait for 150 usec
  for (i=0x0010; i > 0; i--);

  // Turn on frequency synthesiser
  WriteToCC1020Register(CC1020_MAIN,0x11);
}

/****************************************************************************/
/*  This routine wakes the CC1020 up from PD mode to TX mode                */
/****************************************************************************/

void WakeUpCC1020ToTX(char TXANALOG)
{
  volatile int i;

  // Turn on xtal oscillator core
  WriteToCC1020Register(CC1020_MAIN,0xDB);

  // Setup bias current adjustment
  WriteToCC1020Register(CC1020_ANALOG,TXANALOG);

  // Insert wait routine here, must wait for xtal oscillator to stabilise, 
  // typically takes 2-5ms.
  for (i=0x0260; i > 0; i--);

  // Turn on bias generator
  WriteToCC1020Register(CC1020_MAIN,0xD9);

  // Wait for 150 usec
  for (i=0x0010; i > 0; i--);

  // Turn on frequency synthesiser
  WriteToCC1020Register(CC1020_MAIN,0xD1);
}

/****************************************************************************/
/*  This routine acquires the average RSSI level in dBm                        */
/****************************************************************************/
int ReadRSSIlevelCC1020(void){
  char i;
  unsigned char RSSI[5];
  unsigned char FILTER;
  int RSSI_dBm;

  // RSSI formula based on CC1020 datahseet and application note 30:
  // P = 1.5 x RSSI - 3 x VGA_SETTING - RSSI_Offset [dBm]

  /*
  VGA_SETTING based on SmartRF Studio - CC1020, v5.3.0.0
  Note: these settings could be subject to optimisation.
  
  434MHz range:
  -------------------------------------------------
  12.5 => VGA3 = 0x31 => VGA_SETTING = 0x11 = 17dec
  25   => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
  50   => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
  100  => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
  150  => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
  200  => VGA3 = 0x32 => VGA_SETTING = 0x12 = 18dec
  500  => VGA3 = 0x33 => VGA_SETTING = 0x13 = 19dec
  
  868MHz range:
  -------------------------------------------------
  12.5 => VGA3 = 0x2F => VGA_SETTING = 0x0F = 15dec
  25   => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
  50   => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
  100  => VGA3 = 0x2D => VGA_SETTING = 0x0D = 13dec
  150  => VGA3 = 0x2E => VGA_SETTING = 0x0E = 14dec
  200  => VGA3 = 0x30 => VGA_SETTING = 0x10 = 16dec
  500  => VGA3 = 0x34 => VGA_SETTING = 0x14 = 20dec
  */

  // Get current channel spacing
  FILTER = ReadFromCC1020Register(CC1020_FILTER)&0x7F;

  // Calculate average RSSI in dBm (initially without offset):
  for(i = 0; i < 5; i++) {
    RSSI[i] = ReadFromCC1020Register(CC1020_RSSI);
  }
  RSSI_dBm = (int)((((unsigned int)RSSI[0]+(unsigned int)RSSI[1]+(unsigned int)RSSI[2]+(unsigned int)RSSI[3]+(unsigned int)RSSI[4])*3)/(2*5));
  RSSI_dBm = ((RSSI_dBm*3) - (3*(int)(ReadFromCC1020Register(CC1020_VGA3)&0x1F)*2)) / 2;

  // Calculate average RSSI in dBm with offset, according to frequency band:
  // Active frequency is in 800 MHz band
  if( (ReadFromCC1020Register(CC1020_ANALOG)&0x80) == 0x80 ) {
    switch ( FILTER ) {
      case 0x58://12.5 kHz spacing
      case 0x3F://12.5 kHz spacing, optimal sensitivity
        RSSI_dBm = RSSI_dBm - 95;
        break;
      case 0x2F://25 kHz spacing
        RSSI_dBm = RSSI_dBm - 96;
        break;
      case 0x2B://50 kHz spacing
        RSSI_dBm = RSSI_dBm - 95;
        break;
      case 0x25://100 kHz spacing
        RSSI_dBm = RSSI_dBm - 96;
        break;
      case 0x22://150 kHz spacing
        RSSI_dBm = RSSI_dBm - 99;
        break;
      case 0x01://200 kHz spacing
        RSSI_dBm = RSSI_dBm - 99;
        break;
      case 0x00://500 kHz spacing
        RSSI_dBm = RSSI_dBm - 101;
        break;
    }
  // Active frequency is in 434 MHz band
  } else {
    switch ( FILTER ) {
      case 0x38://12.5 kHz spacing
      case 0x2F://25 kHz spacing
        RSSI_dBm = RSSI_dBm - 102;
        break;
      case 0x2B://50 kHz spacing
        RSSI_dBm = RSSI_dBm - 100;
        break;
      case 0x25://100 kHz spacing
        RSSI_dBm = RSSI_dBm - 99;
        break;
      case 0x22://150 kHz spacing
        RSSI_dBm = RSSI_dBm - 101;
        break;
      case 0x01://200 kHz spacing
        RSSI_dBm = RSSI_dBm - 102;
        break;
      case 0x00://500 kHz spacing
        RSSI_dBm = RSSI_dBm - 103;
        break;
      }
  }

  return(RSSI_dBm);
}

⌨️ 快捷键说明

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