El retardo no funciona (avr attiny 26, delay.h)

0

Estoy tratando de aprender cómo escribir programas en el microcontrolador, y comencé con cosas muy simples como el parpadeo del LED con una frecuencia determinada o controlado por un botón. Sin embargo, tengo problemas con el uso de _delay_ms () de delay.h. Como entendí, para el correcto trabajo de esta función, la optimización debe estar activada . Cuando escribo un programa en el microcontrolador, en lugar de parpadear el LED, el LED se enciende constantemente con bajo brillo. Cuando intenté simplemente encenderlo sin demoras, el brillo es mucho mayor, así que por alguna razón el microcontrolador da un poco de voltaje intermedio, me pregunto por qué y cuál podría ser el problema. A continuación describo exactamente lo que estaba haciendo. El código (main.c) se ve así (estoy usando attiny26, y supongo que funciona a 1MHz).

#define F_CPU 1000000UL // 1 MHz clock speed
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
     DDRA |= (1<<PA0);  //A0 as output
     while(1) //infinite loop
     {
          PORTA |= (1<<PA0);// LED at A0 ON
          _delay_ms(1000); // 1 second delay
          PORTA &= ~(1<<PA0); //LED at A0 OFF
          _delay_ms(1000); // 1 second delay
          }
 }

Hago un archivo de objeto con

avr-gcc -mmcu=attiny26 -O1 -c main.c

donde -O1 es para el nivel 1 de optimización. Entonces

avr-objcopy -O ihex main.o main.hex

y escriba al microcontrolador:

sudo avrdude -c usbasp -p t26 -B 100 -U flash:w:main.hex:i

Todos los pasos fueron completamente sin ningún error o advertencia. Como dije antes, el comportamiento resultante es extraño: el LED está encendido constantemente con brillo bajo de litio. Mientras tanto, si escribo en el programa del microcontrolador, donde simplemente enciendo el LED (eliminar todos los retrasos), el LED se encenderá con el brillo completo. Estaba pensando si la optimización en sí misma puede ser un problema, pero en el régimen sin demoras, el programa funciona correctamente en cualquier caso, con optimización o sin.

Controlar cualquier cosa con el botón requeriría el desalojo, y la misma función _delay_ms (), que no funciona para mí.

UPD : comentar #define F_CPU 1000000UL o aumentar el argumento de _delay_ms() no ayuda. Pero aumentar el tiempo de retardo al hacer la iteración for (i=0; i<100000; i++) {_delay_ms(1000);} hace que el LED se encienda constantemente con brillo total. Los tiempos de iteración más pequeños probados (10, 100, 1000, 10000) no proporcionan el brillo total del LED.

    
pregunta Antonio

2 respuestas

1

El problema es que está creando un archivo de objeto, pero no lo está vinculando. Sin vincular, las instrucciones de bifurcación en el código de la máquina no se rellenan con las direcciones de destino requeridas, por lo que el código simplemente se ejecuta de forma lineal hasta que "cae del final" a la memoria no asignada. Finalmente, llega al final de la memoria y se ajusta a cero para ejecutar su código nuevamente. El resultado final es que el LED parpadea con un ciclo de trabajo muy bajo.

La solución más simple es simplemente eliminar la opción -c de su comando de compilación, es decir: -

avr-gcc -mmcu=attiny26 -O1 main.c

Esto crea un archivo ELF llamado 'a.out' que convierte a HEX con: -

avr-objcopy -O ihex a.out main.hex
    
respondido por el Bruce Abbott
0

El retraso máximo que puede obtener con _delay_ms () no debe exceder los 262.14 ms / F_CPU en MHz. Lo que es 262.14ms en tu caso. Mira

void _delay_ms(double __ms)

en este enlace para obtener más información.

Una solución es demorar por un período de tiempo más corto, varias veces.

Por ejemplo:

for(int i=0; i<5; i++)
   delay_ms(200);
    
respondido por el Majid_L

Lea otras preguntas en las etiquetas