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
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
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