Attiny no funciona después de la conversión ADC

0

Estoy tratando de conseguir que un simple sensor IR funcione en mi attiny85. Para hacer esto, primero escribí un código para configurar el ADC y para realizar una operación basada en el resultado. Debido a que el código no funcionó como se esperaba, decidí probar si algún código donde simplemente hago una conversión de ADC y luego enciendo un LED funciona. Sin embargo, esto no funcionó. La causa de esto parece ser que el attiny deja de ejecutar código después de la conversión de ADC. Estoy ejecutando el attiny en el reloj interno de 8Mhz y el ADC está conectado a tierra a través de una resistencia de 200 ohmios.

El siguiente código no activa el pin en PB0:

#include <avr/io.h>
#include <util/delay.h>

int main(void) {

DDRB |= _BV(DDB0); //set PB0 to output

ADMUX = _BV(ADLAR) | _BV(MUX1); //set ADC 2, left adjust result
ADCSRA = _BV(ADPS1) | _BV(ADPS2); //prescaler 64
ADCSRA |= _BV(ADEN); //enable ADC

while(1) {

    ADCSRA |= _BV(ADSC); //start conversion
    while (ADCSRA & _BV(ADSC)); //wait for conversion to end
    uint8_t adc_result = ADCH; //adc results (should be 0)

    PORTB |= _BV(PORTB0); //set PB0 to high


}

return(0);
}

Cuando yo, sin embargo, pongo el "PORTB | = _BV (PORTB0);" línea al comienzo del bucle, así que antes de la conversión de ADC, la línea se ejecuta y el LED en PB0 se enciende.

También comentando la línea "ADCSRA | = _BV (ADSC);" hace que el código se ejecute bien y hace que PB0 vaya alto. Así que estoy bastante seguro de que la atención de alguna manera se bloquea al ejecutar esa línea.

La desactivación de interrupciones usando "cli ()" tampoco resuelve el problema.

    
pregunta SjoerdvdBelt

2 respuestas

1

No tengo ningún Attiny85 pero utilicé su código y lo escribí en Attiny13.

El código que utilicé:

#include <avr/io.h>

uint8_t adc_result = 0;

int main( void ) {

    DDRB |= ( 1 << DDB0 ); //set PB0 to output
    ADMUX  |= ( 1 << ADLAR ) | ( 1 << MUX1 ); //set ADC 2 (PB4), left adjust result
    ADCSRA |= ( 1 << ADEN ); //enable ADC
    ADCSRA |= ( 1 << ADPS1 ) | ( 1 << ADPS2 ); //prescaler 64

    while ( 1 ) {

        ADCSRA |= ( 1 << ADSC ); //start conversion

        while ( ADCSRA & ( 1 << ADSC ) );//wait for conversion to end

        adc_result = ADCH; //adc results (should be 0)

        PORTB ^= ( 1 << PB0 ); //Toggle LED at PB0 

    }

    return( 0 );
}   

Como puede ver, modifiqué ligeramente el código porque los compiladores de My C no reconocen la macro _BV, así que lo reemplacé con (1 < < x). Y también toco el led (PB0).

Y la señal en el pin PB0 se ve así:

Note que la frecuencia de la señal es de alrededor de 5.2MHz.

Entonces es muy interesante por qué este código no funciona en attiny85.

    
respondido por el G36
1

Así que resolví el problema.

Por alguna razón, el código comenzó a funcionar cuando cambié la configuración de los fusibles para dividir el reloj interno entre 8, de modo que tengo un reloj interno de 1 Mhz en lugar de 8 Mhz. No sé por qué, pero por alguna razón esto causó que el ADC no se bloquee.

Nuevos ajustes de fusibles: -U lfuse: w: 0x62: m -U hfuse: w: 0xdf: m -U efuse: w: 0xff: m

Configuración de fusibles antiguos: -U lfuse: w: 0xe2: m -U hfuse: w: 0xdf: m -U efuse: w: 0xff: m

    
respondido por el SjoerdvdBelt

Lea otras preguntas en las etiquetas