ATMEGA328p ADC sigue devolviendo 1023

3

Estoy tratando de configurar mi ATMEGA328p para medir la temperatura usando el sensor de temperatura TMP36GZ. Sin embargo, el ADC de 10 bits sigue devolviendo 1023. He intentado desconectar el sensor de temperatura (debería devolver 0 en este punto para la lectura de ADC), pero aún así devuelve 1023. No estoy exactamente seguro de lo que estoy haciendo mal en mi código:

volatile uint16_t TMP36_VoutADCReading = 0U;

void TMP36_Init( void )
{
   // Set the ADC prescaler to 128 (i.e., 16MHz/128 = 125KHz)
   ADCSRA |= ( 1 << ADPS2 ) | ( 1 << ADPS1 ) | ( 1 << ADPS0 );

   // Set the voltage reference from AVcc (i.e., 5V).
   ADMUX |= ( 1 << REFS0 );

   // Turn on the ADC.
   ADCSRA |= ( 1 << ADEN );

   // Do the initial conversion (i.e., the slowest conversion)
   // to ensure that everything is up and running.
   ADCSRA |= ( 1 << ADSC );
}

void TMP36_ADCRead( uint8_t channel )
{
   // Clear the previously read channel.
   // ADCSRA &= 0xf0;                      <-- This was causing the bug.
   ADMUX &= 0xf0;                          // <-- This is the fix. Thanks IgnacioVazquez-Abrams!

   // Select the ADC channel to be read.
   ADMUX |= channel;

   // Start a new conversion. By default, this conversion will
   // be performed in single conversion mode.
   ADCSRA |= ( 1 << ADSC );

   // Wait until the conversion is complete.
   // while( ADCSRA & ( 1 << ADSC ) );        <-- This is probably also correct.
   while( ADCSRA & ( 1 << ADIF ) );           // <-- Added. Thanks Adithya!

   // Obtain the ADC reading from Vout.
   TMP36_VoutADCReading = ADC;

   // Clear the ADIF flag.
   ADCSRA |= ( 1 << ADIF );                    // <-- Just added. Thanks Adithya!
}

int main( void )
{
   // Disable all interrupts for the time being.
   cli();

   // Initialize the TMP36GZ temperature sensor.
   TMP36_Init();

   // Enable all interrupts.
   sei();

   while( 1 )
   {
      // Compute the distance.
      uint8_t channel = 1;
      TMP36_ADCRead( channel ); // At this point, TMP36_VoutADCReading = 1023
   }
}

En términos de conexiones, estoy intentando leer el voltaje de salida del pin PC1 en el ATMEGA328p y tengo AVcc conectado a VCC y el pin 22 (es decir, GND) conectado a la GND del pin 8. He deshabilitado el ajuste de la referencia de voltaje de AREF, entonces AREF no esta conectado

Cualquier ayuda sería muy apreciada.

ACTUALIZACIÓN: Ignacio Vázquez-Abrams señaló que ADCSRA &= 0xf0; debería haber sido ADMUX &= 0xf0; . Desde entonces he modificado el código anterior. También, ¡gracias Adithya por la sugerencia que hiciste sobre la comprobación de la bandera de ADIF! Lo tomaré en consideración.

    
pregunta Justin

2 respuestas

4

La solución provista por IgnacioVázquez-Abrams fue correcta. Aparentemente, estaba borrando incorrectamente los 4 bits inferiores en ADCSRA cuando debería haberlo hecho con ADMUX. He actualizado el código anterior para reflejar esto y los errores que he cometido en el código se han comentado (todavía están allí como referencia).

    
respondido por el Justin
2

// Wait until the conversion is complete. while( ADCSRA & ( 1 << ADSC ) )

Esto está mal. Debe usar ADIF para verificar si la conversión está completa. Por lo tanto, el código sería

while(!(ADCSRA&(1<<ADIF)); 
 or
while(ADCSRA&(1<<ADIF)==0);

Esto espera a que se establezca el indicador ADIF una vez que se complete la conversión. Luego, debe borrar el indicador manualmente al configurar el indicador ADIF para que comience la siguiente conversión:

ADCSRA|=(1<<ADIF);

Dicho esto, ¿por qué no te limitas a los ISR? Eso haría la vida mucho más fácil.

    
respondido por el Adithya

Lea otras preguntas en las etiquetas