Noté un comportamiento extraño, por lo que no puedo encontrar ninguna confirmación documentada. En mi programa mido dos canales ADC:
- ADC0
- Referencia de intervalo de banda interna de 1.1 V (para conocer el valor de la tensión de alimentación aplicada VCC)
Mido estos dos canales por sondeo. Parece que cuando mido un canal siempre obtengo el valor de el canal medido anterior al principio. Para obtener el valor correcto real, tengo que esperar un tiempo (retraso) y volver a medir. ¿Por qué es esto? Este es mi código para leer los valores de ADC.
Leyendo ADC0 :
ADCSRA &= ~(1<<ADEN); /* ADC ausschalten */
/* Set VCC as reference for ADC */
ADMUX &= ~(1<<REFS1);
ADMUX &= ~(1<<REFS0);
/* Measure PA0 (ADCSRB[MUX5] = 0b0; ADMUX[MUX4-MUX0] = 0b00000)*/
ADCSRB &= ~(1<<MUX5);
ADMUX &= ~((1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0));
ADCSRA |= (1<<ADEN) | (1<<ADSC); /* Enable ADC and start conversion */
while((ADCSRA & (1<<ADIF)) == 0); /* Wait until conversion done */
ADCSRA |= (1<<ADIF); /* Reset ADC interrupt flag */
/* At this point I read a wrong value (from previous channel) */
/* My current workaround starts here */
_delay_us(50); /* Wait some time */
/* Measure again */
ADCSRA |= (1<<ADSC); /* Start conversion */
while((ADCSRA & (1<<ADIF)) == 0); /* Wait until conversion done */
ADCSRA |= (1<<ADIF); /* Reset ADC interrupt flag */
/* Now I got my correct value */
ADCSRA &= ~(1<<ADEN); /* Turn off adc */
Al leer el intervalo de banda de 1.1 V , lo único que cambio del código anterior es:
/* Measure 1V1 bandgap reference (ADCSRB[MUX5] = 0b0; ADMUX[MUX4-MUX0] = 0b11110)*/
ADCSRB &= ~(1<<MUX5);
ADMUX |= (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1);
ADMUX &= ~(1<<MUX0);
Tengo que leer el valor incorrecto, luego esperar y luego leer de nuevo. Cuando omito uno de estos pasos, ya no funciona.
Mi microcontrolador de destino es el ATTiny861V y uso avr-gcc en Windows 10 para compilar.