Dear All I have done some coding on FRDM-KL25Z platform from freescal to use it’s 16bit ADC, But I will get very unstable results, I have attached PE20 of the board to an 5K external pot which is connected to the 3.3V power and ground,PE0 is ADC channel zero, the readings are very unstable, do you have any Idea?
ADC codes [code] void ADC_Init(void) { //Turn on ADC SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; //bus clock/2 & singled-ended 16bit mode & div by 4 ADC0->CFG1 = ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(3) | ADC_CFG1_ADIV(2); //select channel A & high speed mode ADC0->CFG2 = !ADC_CFG2_MUXSEL_MASK;// | ADC_CFG2_ADHSC_MASK; //hardware trigger & VREFH/VREFL ADC0->SC2 = ADC_SC2_REFSEL(0); //ADC_SC2_ADTRG_MASK | ADC_SC2_REFSEL(0); //single shot mode ADC0->SC3 &= ~ADC_SC3_ADCO_MASK; //hardware average 32 sample //ADC0->SC3 |= ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3); }
uint8_t Calibrate_ADC(void) {
uint16_t cal_temp;
ADC_Init();
ADC0->SC3 |= ADC_SC3_CALF_MASK; // clear any existing calibration failed flag ADC0->SC3 |= ADC_SC3_CAL_MASK; // Start Calibration
while(ADC0->SC3 & ADC_SC3_CAL_MASK); // wait for calibration to finish
if(ADC0->SC3 & ADC_SC3_CALF_MASK) // There was a fault during calibration return 1;
// Initialize (clear) a 16b variable in RAM. cal_temp = 0;
//Add the following plus-side calibration results CLP0, CLP1, CLP2, CLP3, CLP4, CLPS and CLPD to the variable. cal_temp += ADC0->CLP0; cal_temp += ADC0->CLP1; cal_temp += ADC0->CLP2; cal_temp += ADC0->CLP3; cal_temp += ADC0->CLP4; cal_temp += ADC0->CLPS;
// Divide the variable by two. cal_temp = cal_temp >> 1; // Set the MSB of the variable. cal_temp |= 0x8000;
// Store the value in the plus-side gain calibration registers ADCPG ADC0->PG = cal_temp;
// Repeat procedure for the minus-side gain calibration value. // Initialize (clear) a 16b variable in RAM. cal_temp = 0;
//Add the following minus-side calibration results CLM0, CLM1, CLM2, CLM3, CLM4, CLMS and CLMD to the variable. cal_temp += ADC0->CLM0; cal_temp += ADC0->CLM1; cal_temp += ADC0->CLM2; cal_temp += ADC0->CLM3; cal_temp += ADC0->CLM4; cal_temp += ADC0->CLMS;
// Store the value in the minus-side gain calibration registers ADCMG ADC0->MG = cal_temp;
return 0; }
void adc_start_conversion(uint8_t channel) { ADC0->SC1[0] = !ADC_SC1_AIEN_MASK | ADC_SC1_DIFF_MASK | ADC_SC1_ADCH(channel); }
uint16_t adc_read(uint8_t channel) {
ADC0->SC1[0] = !ADC_SC1_AIEN_MASK | ADC_SC1_DIFF_MASK | ADC_SC1_ADCH(channel) ; // start conversion while((ADC0->SC1[0] & ADC_SC1_COCO_MASK)!= 0){}; return ADC0->R[0]; } [/code]
Main loop codes [code] int main (void) { static int calc=0; char buff[100]; SystemCoreClockUpdate(); /* Get Core Clock Frequency */ uart0_init(); ADC_Init(); Calibrate_ADC(); uart0_puts("Hello world\r\n"); while(1) {
sprintf(buff,"adc %d\r",adc_read(0)); uart0_puts(buff); for(int i=0;i<1000000;i++); } } [/code]
Are _you_ able to read the code in that post?
If you see some issues reading the code, then it might be an idea to take a closer look at the very clear instructions how to post source code to this forum...
The quality of code consultants post is for sure going downhill.
When oh when will Keil do something about un-formatted code?!?! The comments and re-posts associated with this painful issue consume so much bandwidth...
Not if you're in the habit of watching streamed video.
It's all relative.
It's not just Keil.
Keil's forum does seem to manage to make the worst mess of un-tagged (or mis-tagged) code - but I don't know of any forum that can "auto-detect" code and apply appropriate formats.
There are even some forums that don't have any facility at all to properly format code!
How should I post code in here, in most forums we use [code] [/code] to place code!
Exactly as it tells you in the instructions!
Look at the picture: www.danlhenry.com/.../keil_code.png
Read the Tips for Posting Messages: http://www.keil.com/forum/tips.asp
There's one person around here who seems to spend an awful lot of time monitoring Keil and other forums.
void ADC_Init(void) { //Turn on ADC SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; //bus clock/2 & singled-ended 16bit mode & div by 4 ADC0->CFG1 = ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(3) | ADC_CFG1_ADIV(2); //select channel A & high speed mode ADC0->CFG2 = !ADC_CFG2_MUXSEL_MASK;// | ADC_CFG2_ADHSC_MASK; //hardware trigger & VREFH/VREFL ADC0->SC2 = ADC_SC2_REFSEL(0); //single shot mode ADC0->SC3 &= ~ADC_SC3_ADCO_MASK; } uint8_t Calibrate_ADC(void) { uint16_t cal_temp; ADC_Init(); ADC0->SC3 |= ADC_SC3_CALF_MASK; // clear any existing calibration failed flag ADC0->SC3 |= ADC_SC3_CAL_MASK; // Start Calibration while(ADC0->SC3 & ADC_SC3_CAL_MASK); // wait for calibration to finish if(ADC0->SC3 & ADC_SC3_CALF_MASK) // There was a fault during calibration return 1; // Initialize (clear) a 16b variable in RAM. cal_temp = 0; //Add the following plus-side calibration results CLP0, CLP1, CLP2, CLP3, CLP4, CLPS and CLPD to the variable. cal_temp += ADC0->CLP0; cal_temp += ADC0->CLP1; cal_temp += ADC0->CLP2; cal_temp += ADC0->CLP3; cal_temp += ADC0->CLP4; cal_temp += ADC0->CLPS; // Divide the variable by two. cal_temp = cal_temp >> 1; // Set the MSB of the variable. cal_temp |= 0x8000; // Store the value in the plus-side gain calibration registers ADCPG ADC0->PG = cal_temp; // Repeat procedure for the minus-side gain calibration value. // Initialize (clear) a 16b variable in RAM. cal_temp = 0; //Add the following minus-side calibration results CLM0, CLM1, CLM2, CLM3, CLM4, CLMS and CLMD to the variable. cal_temp += ADC0->CLM0; cal_temp += ADC0->CLM1; cal_temp += ADC0->CLM2; cal_temp += ADC0->CLM3; cal_temp += ADC0->CLM4; cal_temp += ADC0->CLMS; // Divide the variable by two. cal_temp = cal_temp >> 1; // Set the MSB of the variable. cal_temp |= 0x8000; // Store the value in the minus-side gain calibration registers ADCMG ADC0->MG = cal_temp; return 0; } void adc_start_conversion(uint8_t channel) { ADC0->SC1[0] = !ADC_SC1_AIEN_MASK | ADC_SC1_DIFF_MASK | ADC_SC1_ADCH(channel); } uint16_t adc_read(uint8_t channel) { ADC0->SC1[0] = !ADC_SC1_AIEN_MASK | ADC_SC1_DIFF_MASK | ADC_SC1_ADCH(channel) ; // start conversion while((ADC0->SC1[0] & ADC_SC1_COCO_MASK)!= 0){}; return ADC0->R[0]; }
Main loop codes
int main (void) { static int calc=0; char buff[100]; SystemCoreClockUpdate(); /* Get Core Clock Frequency */ uart0_init(); ADC_Init(); Calibrate_ADC(); uart0_puts("Hello world\r\n"); while(1) { sprintf(buff,"adc %d\r",adc_read(0)); uart0_puts(buff); for(int i=0;i<1000000;i++); } }
Dear Ali,
This is an old thread. Am curious though, how did you resolve the fluctuating ADC result?