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