Hi everybody,
I'm facing a serious problem with calibration of ADC on Kinetis K60. I configure output mode differential 16 bits, Vdda=3,3 V, Voltage reference select Valt = 3V, bus clock = 50 Mhz, internal clock ADCK = 50/4 = 12,5 MHz (Registers CFGx config is the same with exemple ADC_demo of Fresscale).
I use also calibration routine of this exemple:
int ADC_Cal(int Num_adc)
{
unsigned short cal_var;
ADC_MemMapPtr adcmap;
if(Num_adc==ADC0)
{
adcmap = ADC0_BASE_PTR;
}
else if(Num_adc==ADC1)
{
adcmap = ADC1_BASE_PTR;
}
// Turn on the ADC0 and ADC1 clocks
SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK );
SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK );
ADC_SC2_REG(adcmap) &= ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process
ADC_SC3_REG(adcmap) &= (~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK); // set single conversion, clear avgs bitfield for next writing
ADC_SC3_REG(adcmap) |= (ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(AVGS_32)); // Turn averaging ON and set at max value ( 32 )
ADC_CFG1_REG(adcmap)&= (~ADC_CFG1_ADIV(ADIV_4)& ~ADC_CFG1_ADICLK(ADICLK_BUS)); // Clear fADCK initiated
ADC_CFG1_REG(adcmap)|= ADC_CFG1_ADIV(ADIV_8)|ADC_CFG1_ADICLK(ADICLK_BUS_2); // fADCK = 50/2/8
ADC_SC2_REG(adcmap) &= ~ADC_SC2_REFSEL(REFSEL_ALT); // Clear Vrefh initiated
ADC_SC2_REG(adcmap) |= ADC_SC2_REFSEL(REFSEL_EXT); // Vrefh = VDDA
ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ; // Start CAL
while ((ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT); // Wait calibration end
if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL )
{
return 1; // Check for Calibration fail error and return
}
// Calculate plus-side calibration
cal_var = 0x00;
cal_var = ADC_CLP0_REG(adcmap);
cal_var += ADC_CLP1_REG(adcmap);
cal_var += ADC_CLP2_REG(adcmap);
cal_var += ADC_CLP3_REG(adcmap);
cal_var += ADC_CLP4_REG(adcmap);
cal_var += ADC_CLPS_REG(adcmap);
cal_var = cal_var/2;
cal_var |= 0x8000; // Set MSB
ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
// Calculate minus-side calibration
cal_var = 0x00;
cal_var = ADC_CLM0_REG(adcmap);
cal_var += ADC_CLM1_REG(adcmap);
cal_var += ADC_CLM2_REG(adcmap);
cal_var += ADC_CLM3_REG(adcmap);
cal_var += ADC_CLM4_REG(adcmap);
cal_var += ADC_CLMS_REG(adcmap);
cal_var = cal_var/2;
cal_var |= 0x8000; // Set MSB
ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var);
ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
return 0;
}
But when i make a conversion, after eache reset, results vary greatly with a gap of 80 points(ex input DADP3 = 2,18 V, DADM3 = 0,82 V, output (before reset 15137, after reset 15050)). I tried looking values of registers ADCx_CLPD and ADCx_CLMD and write these values in the calib function in order to these registers don't change after each reset. Therefore, output value don't vary.
How can I fix this don't write registers ADCx_CLPD and ADCx_CLMD ?
Many thanks
LE Quang Huy
Sorry, i'm recently so busy. Now, i work with another ADC, AD7793(Delta-Sigma ADC) because of the accurancy of the ADC on K60. I will return this intern ADC after finished the Delta-Sigma ADC.
Thanks Rastislav Pavlanin, it's useful with us.
Quang Huy
Hello LE!
Were this suggestions helpful?
Keep us posted, we'd like to know :smileywink:
Best regards,
Monica
Hi Le,
not sure I will help but the accurancy of ADC measurement is dependent on many features like:
- on ADC clock + sampling time + total conversion time + averaging use/or not,
- on your external component design (if the external impedance is too high it can also degradate accurancy) etc.
Some recomendations :
- the maximum recommended ADC clock for 16-bit mode is 12MHz (you use clock slightly higher which can also decrease accurancy),
- see the ENOB value in datasheet (ENOB represents effective number of bits for specified ADC configuration)
- if you use 16-bit ADC mode it does not mean the accurancy you can get, it only means that SAR ADC will make16 "aproximations" till the conversion done (16 active bits used in result register).
- also improtant value in datasheet is TUE (total unadjusted error).
I do not think you faceing a problem with calibration process, this look ok from my point of view.
hope I helped.
Rastislav