Hardware averaging of internal temperature sensor gives random values.

cancel
Showing results for 
Search instead for 
Did you mean: 

Hardware averaging of internal temperature sensor gives random values.

636 Views
larsl
Contributor II

Hi!

I'm currently running a set of prototypes on the MKL04Z32xxx4 MCU. I've written some code for the ADC in order to be able to read a set of different channels. All used channels are working fine when hardware averaging is turned on, except the internal chip temperature one. The code is set up to use 12-bit measurements, and looks does this after calibration:

ADC0_SC1A |= ADC_SC1_AIEN_MASK; //Enable interrupt
ADC0_CFG1 |= ADC_CFG1_MODE(1); // Set 12 bit mode
//ADC0_SC3  &= (uint8_t)(~ADC_SC3_AVGE_MASK); //Averaging disabled when this line is run.
ADC0_SC3  = ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(0); //4 samples enabled with this.

I can get a proper reading on the chip temp when hardware averaging is turned off (un-commented line above), but not when the code runs as above. I've recorded twenty samples over a period of 20 seconds. As you can see the one with HW averaging acts in a random fashion...

//4 HW samples:

array[0]    uint16_t    1216  

array[1]    uint16_t    941  

array[2]    uint16_t    783  

array[3]    uint16_t    850  

array[4]    uint16_t    822  

array[5]    uint16_t    928  

array[6]    uint16_t    903  

array[7]    uint16_t    980  

array[8]    uint16_t    958  

array[9]    uint16_t    807  

array[10]    uint16_t    717  

array[11]    uint16_t    906  

array[12]    uint16_t    821  

array[13]    uint16_t    793  

array[14]    uint16_t    821  

array[15]    uint16_t    806  

array[16]    uint16_t    1102  

array[17]    uint16_t    822  

array[18]    uint16_t    906  

array[19]    uint16_t    643  

//With averaging disabled:

array[0]    uint16_t    1412  

array[1]    uint16_t    1412  

array[2]    uint16_t    1412  

array[3]    uint16_t    1412  

array[4]    uint16_t    1412  

array[5]    uint16_t    1412  

array[6]    uint16_t    1412  

array[7]    uint16_t    1412  

array[8]    uint16_t    1412  

array[9]    uint16_t    1412  

array[10]    uint16_t    1412  

array[11]    uint16_t    1412  

array[12]    uint16_t    1412  

array[13]    uint16_t    1412  

array[14]    uint16_t    1412  

array[15]    uint16_t    1412  

array[16]    uint16_t    1412  

array[17]    uint16_t    1412  

array[18]    uint16_t    1412  

array[19]    uint16_t    1412

Does anybody know what might be going on? This problem is driving me nuts..

Thanks!

/Lars

Labels (1)
0 Kudos
2 Replies

55 Views
Paul_Tian
NXP Employee
NXP Employee

Hi, Larsl

Would you please help to show your complete ADC initial code? I would like to check it for you. Thanks a lot. Have a nice day.

Best Regards

Paul

0 Kudos

55 Views
larsl
Contributor II

Hi Paul,

Thanks for the fast reply. My calibration function looks like this:

static uint32_t adc_calibrate(void)

{

  uint32_t ad_calib = 0;

  irq_disableInt(irq_ADC); //Disable the interrupt while calibrating

  ADC0_SC3 &= ~ADC_SC2_ADTRG_MASK;   // Enable Software Conversion Trigger for Calibration Process

  ADC0_SC3 &= (~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK);   // set single conversion, clear avgs bitfield for next writing

  ADC0_SC3 |= (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3)); // Turn averaging ON and set at max value ( 32 )

  ADC0_SC3 |= ADC_SC3_CAL_MASK; // Start CAL

  while ((ADC0_SC1A & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK)

  ; // Wait until calibration ends

  if ((ADC_SC3_REG(ADC0_BASE_PTR) & ADC_SC3_CALF_MASK) == ADC_SC3_CALF_MASK)

  {

    return(FALSE); //Calibration failed.

  }

  ad_calib = ADC0_CLP0; // Add results

  ad_calib += ADC0_CLP1; // Add results

  ad_calib += ADC0_CLP2; // Add results

  ad_calib += ADC0_CLP3; // Add results

  ad_calib += ADC0_CLP4; // Add results

  ad_calib += ADC0_CLPS; // Add results

  ad_calib /= 2; // divide by 2

  ad_calib |= 0x8000; // Set MSB

  ADC0_PG = ad_calib;

  ADC_SC3_REG(ADC0_BASE_PTR) &= ~ADC_SC3_CAL_MASK; /* Clear CAL bit */

  return(TRUE); //Calibration successful

}

The remaining setup code calls this calibration function as below:

  if(adc_calibrate()) //If we have a successful calibration

  {

    ADC0_SC1A |= ADC_SC1_AIEN_MASK; //Enable interrupt

    ADC0_CFG1 |= ADC_CFG1_MODE(1); // Set 12 bit mode

    ADC0_SC3  &= (uint8_t)(~ADC_SC3_AVGE_MASK); //Disable averaging

    //ADC0_SC3  = ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(0); //4 samples

  }

After this the conversion is started with:

ADC0_SC1A = ( CHANNEL_TO_MEASURE & ADC_SC1_ADCH_MASK) | ADC_SC1_AIEN_MASK; //Start next conversion!

The result is extracted from the interrupt with

value = ADC0_RA;

I hope this was what you were looking for. In case it makes any difference, the MCU runs on 3.3V, and the analog reference voltage is 2.048V.

Thanks for the help!

Kind regards

Lars

0 Kudos