I'd like to use the internal AD converter. But it doesn't work correctly.
I connected a continue voltage on PTB 0 labeled as ADC0/SE8 adc channel.(using FRDMKL27)
I follow the data sheet just to start the module but the register R it is always at the value of 65535.
If I break at ADC0 interrupr handler I see this.
The ADc is triggered from a timer every 500 ms.
What's miss on my code ?
Any suggestion ?
Thanks in advance.
Attilio
void ADC0_IRQHandler(void)
{
static UINT32 value = 0;
value = ADC0->R[0];
}
BOOL Adc_Calibration(void)
{
UINT16 cal_data;
ADC_Type *adc;
adc = ADC0; // just to see the register in the debug window
adc->CFG1 |= ADC_CFG1_ADICLK(0x01) + // adc input clock = busclk/ 2 --> (24 Mhz / 2) = 12 Mhz
ADC_CFG1_ADIV(2) + // adc division = 8 --> adc clock = 12 Mz / 8 = 1Mhz
ADC_CFG1_ADLPC(0) + // no low power
ADC_CFG1_ADLSMP(0x01) + // long sample time
ADC_CFG1_MODE(0x03); // with DIFF = 0 --> 16 bit single ended
adc->SC2 = 0x00; // software trigger selected
// compare function disabled
// DMA transfert disabled
// voltage ref is default ref (vrefh / vrefl)
adc->SC3 |= ADC_SC3_AVGE_MASK + // enable hw average
ADC_SC3_AVGS(3) + // set for 32 samples
ADC_SC3_CAL_MASK; // start calibration
while(adc->SC3 & ADC_SC3_CAL_MASK); // wait for calibration end
if(adc->SC3 & ADC_SC3_CALF_MASK) // check calibration success ?
return FALSE; // calibration was fault
// compute & store calibration data
cal_data = 0;
cal_data += adc->CLPS + adc->CLP4 + adc->CLP3 +
adc->CLP2 + adc->CLP1 + adc->CLP0;
cal_data >>= 1;
cal_data |= 0x8000;
adc->PG = cal_data;
cal_data = 0;
cal_data += adc->CLMS + adc->CLM4 + adc->CLM3 +
adc->CLM2 + adc->CLM1 + adc->CLM0;
cal_data >>= 1;
cal_data |= 0x8000;
adc->MG = cal_data;
adc->SC3 &= ~ADC_SC3_CAL_MASK; // clear CAL bit
return TRUE;
}
void InitAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // adc0 clock gating
if(Adc_Calibration() == FALSE)
{
ErrorTrap(); // just for debug
}
// change adc config after calibration
ADC0->CFG1 |= ADC_CFG1_ADICLK(0x01) + // adc input clock = busclock --> 24 Mhz
ADC_CFG1_ADIV(0) + // adc division = 1 --> adc clock = 24 Mz
ADC_CFG1_ADLPC(0) + // no low power
ADC_CFG1_ADLSMP(0x01) + // long sample time
ADC_CFG1_MODE(0x03); // with DIFF = 0 --> 16 bit single ended
ADC0->SC1[0] |= ADC_SC1_ADCH(0x1F); // disable ADC module
ConnectInterruptToCortex(ADC0_IRQn); // set ADC0 interrupts
}
void TriggerAdc(void)
{
ADC0->SC1[0] = ADC_SC1_ADCH(8) | ADC_SC1_AIEN_MASK;
}
void main(void)
{
InitAdc();
ENABLE_INTERRUPTS;
while(1)
{
}
}