Wednesday, November 26, 2014

How to output PWM from CC2530/CC2541

Refer to CC253x/4x User's Guide. The following sample code can send PWM to P1_4.


  PERCFG &= (~(0x20)); // Select Timer 3 Alternative 1 location
  P2SEL |=0x20;
  P2DIR |= 0xC0;  // Give priority to Timer 1 channel2-3
  P1SEL |= BV(4);  // Set P1_4 to peripheral, Timer 1,channel 2
  P1DIR |= BV(4);

  T3CTL &= ~0x10;             // Stop timer 3 (if it was running)
  T3CTL |= 0x04;              // Clear timer 3
  T3CTL &= ~0x08;             // Disable Timer 3 overflow interrupts
  T3CTL |= 0x03;              // Timer 3 mode = 3 - Up/Down

  T3CCTL1 &= ~0x40;           // Disable channel 0 interrupts
  T3CCTL1 |= 0x04;            // Ch0 mode = compare
  T3CCTL1 |= 0x10;            // Ch0 output compare mode = toggle on compare

  T3CTL &= ~0xE0;   // Clear Prescaler divider value
  T3CTL |= 0xA0;    //Set Prescaler divider value = Tick frequency /32
  T3CC0 = 128;      //Set ticks = 128

  // Start timer
  T3CTL |= 0x10;

Then, the following example shows you how you output 6.5K PWM with 50% duty cycle to P1.1 with CC2530 Timer 1.

  PERCFG |= BV(6); // Select Timer 1 Alternative 2 location
  P2DIR = (P2DIR & ~0xC0) | 0x80; // Give priority to Timer 1
  P1SEL |= BV(1);  // Set P1_1 to peripheral

  T1CC0L = 0x3A;   // PWM signal period
  T1CC0H = 0x01;

  T1CC1L = 0x9D;  // PWM duty cycle
  T1CC1H = 0x00;

  T1CCTL1 = 0x1c;

  T1CTL |= (BV(2)|0x03); // divide with 128 and to do i up-down mode

How to do temperature monitoring using CC2530 with TI Z-Stack

The battery monitor can also be used to do some simple temperature monitoring in CC2530. When the battery monitor is connected to the internal temperature sensor instead of the supply voltage AVDD5.

The following readTemperature function provides capability to read temperature using CC2530 internal ADC and sensor. When first time call this function, you have to keep temperature at 22oC for calibration.

int8 readTemperature(void)
{
  static uint16 voltageAtTemp22;
  static uint8 bCalibrate=TRUE; // Calibrate the first time the temp sensor is read
  uint16 value;
  int8 temp;

  ATEST = 0x01;
  TR0  |= 0x01;
 
  /* Clear ADC interrupt flag */
  ADCIF = 0;

  ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_512 | HAL_ADC_CHN_TEMP);

  /* Wait for the conversion to finish */
  while ( !ADCIF );

  /* Get the result */
  value = ADCL;
  value |= ((uint16) ADCH) << 8;

  // Use the 12 MSB of adcValue
  value >>= 4;
 
  /*
   * These parameters are typical values and need to be calibrated
   * See the datasheet for the appropriate chip for more details
   * also, the math below may not be very accurate
   */
    /* Assume ADC = 1480 at 25C and ADC = 4/C */
  #define VOLTAGE_AT_TEMP_25        1480
  #define TEMP_COEFFICIENT          4

  // Calibrate for 22C the first time the temp sensor is read.
  // This will assume that the demo is started up in temperature of 22C
  if(bCalibrate) {
    voltageAtTemp22=value;
    bCalibrate=FALSE;
  }
 
  temp = 22 + ( (value - voltageAtTemp22) / TEMP_COEFFICIENT );
 
  // Set 0C as minimum temperature, and 100C as max
  if( temp >= 100)
  {
    return 100;
  }
  else if (temp <= 0) {
    return 0;
  }
  else {
    return temp;
  }
}