Hello all!
I was using a routine to read the ADC, it worked for several hours/days without any problem.
I decided to add a Watchdog vector interrupt to read the ADC with an interval of 250ms (the timers doesn't have so long delay interval). After installing the routine I start seeing it was running 2, 3 or five minutes and stops at the ADC reading routine.
The code I have is the following:
ADC setup:
// ADC Enable ADCSRA |=(1<<ADEN); ADCSRA |=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADMUX |=(1<<REFS0); DIDR0 =0b00011111;
The ADC reading routine I had is the following:
uint16_t Read_ADC(uint8_t adc_adr) { uint16_t adc_value =0; ADMUX = (adc_adr); ADCSRA |=(1<<ADSC); while (!(ADCSRA & (1<<ADIF))) {} adc_value=ADCL; adc_value+=(ADCH<<8); ADCSRA|=(1<<ADIF); return adc_value; }
The watchdog timer setup is the following:
void WDT_on(void) { //_watchdog_reset(); MCUSR &= ~(1<<WDRF); WDTCSR |=(1<<WDCE) | (1<<WDE); // set prescaller to 0.250ms WDTCSR= (0<<WDE)|(1<<WDIE) | (1<<WDP2); }
The watchdog ISR routine is the following:
/**************************************************************** * This is a timer Watchdog interrupt routine with 0.25 ms interrupt interval * The ADC4 is readed to measure 4 times the currente and the total added.*/ ISR(WDT_vect) { sbi(PORTD, 6);// to test the time to measure the current if (I_status<=3) { current_avg += Read_ADC(4+64); // +64 is the REFS= bit, AVCC with external capacitor at AREF pin I_status++; cbi(PORTD, 6);// to test the time to measure the current } else { GPS_data[43]=(uint8_t)(current_avg>>8); GPS_data[44]=(uint8_t)(current_avg); current_avg=0; I_status=0; } }
The above was the first setup. After looking in the forum a tutorial I saw a different approach to read the ADC, that is the following:
/**************************************************************** * This routine is to read the ADC. The ADC is going to read the * motor battery voltage, receiver battery voltage, temperature and * air speed. */ uint16_t Read_ADC(uint8_t adc_adr) { uint16_t adc_value =0; ADMUX = (adc_adr); ADCSRA |=(1<<ADSC); while(ADCSRA & (1<<ADSC)); {} // this was modified adc_value=ADCL; adc_value+=(ADCH<<8); ADCSRA|=(1<<ADIF); return adc_value; }
Instead of looking for the "ADIF: ADC Interrupt Flag" was changed to "Bit 6 "“ ADSC: ADC Start Conversion".
This doesn't make sense to me according to the device manual Atmega644P.
The fact is: i changed it and it has been running without problems.
Can some one explain me what is wrong in the first version?
Thanks.
Manuel