ZigBee CC2530 HalAdcRead ADC读取误差偏大

使用CC2530,以及TI提供的Z-Stack协议栈程序。
直接调用它协议栈里面的函数HalAdcRead,发现AD值读取出来误差很大,上下0.02V的波动(固定电压)。
感觉难以接受,然后就翻了它底层的程序。

有一个设置参考电压的地方感觉不对,修改了一下,误差基本在0.004V左右。
改动如下。


//  adctemp &= ~(HAL_ADC_CHN_BITS | HAL_ADC_DEC_BITS | HAL_ADC_REF_BITS);
  adctemp &= ~(HAL_ADC_CHN_BITS | HAL_ADC_DEC_BITS | HAL_ADC_REF_AVDD);
/**************************************************************************************************
 * @fn      HalAdcRead
 *
 * @brief   Read the ADC based on given channel and resolution
 *
 * @param   channel - channel where ADC will be read
 * @param   resolution - the resolution of the value
 *
 * @return  16 bit value of the ADC in offset binary format.
 *
 *          Note that the ADC is "bipolar", which means the GND (0V) level is mid-scale.
 *          Note2: This function assumes that ADCCON3 contains the voltage reference.
 **************************************************************************************************/
uint16 HalAdcRead (uint8 channel, uint8 resolution)
{
  int16  reading = 0;

#if (HAL_ADC == TRUE)

  uint8   i, resbits;
  uint8   adctemp;
  volatile  uint8 tmp;
  uint8  adcChannel = 1;
  uint8  reference;

  /* store the previously set reference voltage selection */
  reference = ADCCON3 & HAL_ADC_REF_BITS;

  /*
  * If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled.  The code
  * does NOT disable the pin at the end of this function.  I think it is better to leave the pin
  * enabled because the results will be more accurate.  Because of the inherent capacitance on the
  * pin, it takes time for the voltage on the pin to charge up to its steady-state level.  If
  * HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage
  * than actuality because the pin did not have time to fully charge.
  */
  if (channel < 8)
  {
    for (i=0; i < channel; i++)
    {
      adcChannel <<= 1;
    }
  }

  /* Enable channel */
  ADCCFG |= adcChannel;

  /* Convert resolution to decimation rate */
  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      resbits = HAL_ADC_DEC_064;
      break;
    case HAL_ADC_RESOLUTION_10:
      resbits = HAL_ADC_DEC_128;
      break;
    case HAL_ADC_RESOLUTION_12:
      resbits = HAL_ADC_DEC_256;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      resbits = HAL_ADC_DEC_512;
      break;
  }

  /* read ADCL,ADCH to clear EOC */
  tmp = ADCL;
  tmp = ADCH;

  /* Setup Sample */
  adctemp = ADCCON3;
//  adctemp &= ~(HAL_ADC_CHN_BITS | HAL_ADC_DEC_BITS | HAL_ADC_REF_BITS);
  adctemp &= ~(HAL_ADC_CHN_BITS | HAL_ADC_DEC_BITS | HAL_ADC_REF_AVDD);
  adctemp |= channel | resbits | (reference);

  /* writing to this register starts the extra conversion */
  ADCCON3 = adctemp;

  /* Wait for the conversion to be done */
  while (!(ADCCON1 & HAL_ADC_EOC));

  /* Disable channel after done conversion */
  ADCCFG &= (adcChannel ^ 0xFF);

  /* Read the result */
  reading = (int16) (ADCL);
  reading |= (int16) (ADCH << 8);

  /* Treat small negative as 0 */
  if (reading < 0)
    reading = 0;

  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      reading >>= 8;
      break;
    case HAL_ADC_RESOLUTION_10:
      reading >>= 6;
      break;
    case HAL_ADC_RESOLUTION_12:
      reading >>= 4;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      reading >>= 2;
    break;
  }
#else
  // unused arguments
  (void) channel;
  (void) resolution;
#endif

  return ((uint16)reading);
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/kangweijian/article/details/79990743