Ich versuche zu lernen, wie man Programme auf Mikrocontroller schreibt, und begann mit sehr einfachen Dingen wie LED, die mit einer bestimmten Frequenz blinken oder per Taste gesteuert werden. Ich habe jedoch Probleme mit der Verwendung von _delay_ms() aus delay.h. Soweit ich verstanden habe, sollte für die korrekte Arbeit dieser Funktion die Optimierung eingeschaltet sein . Wenn ich ein Programm auf den Mikrocontroller schreibe, wird die LED nicht blinken, sondern ständig mit geringer Helligkeit eingeschaltet. Als ich versuchte, es einfach ohne Verzögerungen einzuschalten, ist die Helligkeit viel höher, also sieht es so aus, als ob der Mikrocontroller aus irgendeinem Grund eine mittelmäßige Niederspannung liefert, ich frage mich, warum und was das Problem sein könnte. Im Folgenden beschreibe ich, was ich genau gemacht habe. Code (main.c) sieht so aus (ich verwende attiny26 und gehe davon aus, dass es bei 1 MHz funktioniert).
#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
}
}
Ich mache Objektdatei mit
avr-gcc -mmcu=attiny26 -O1 -c main.c
wobei -O1 für Stufe 1 der Optimierung steht. Dann
avr-objcopy -O ihex main.o main.hex
und in den Mikrocontroller schreiben:
sudo avrdude -c usbasp -p t26 -B 100 -U flash:w:main.hex:i
Alle Schritte waren völlig ohne Fehler oder Warnungen. Wie ich oben sagte, ist das resultierende Verhalten seltsam: LED ist ständig an mit geringer Helligkeit. Wenn ich in der Zwischenzeit in ein Mikrocontroller-Programm schreibe, in dem ich nur die LED einschalte (alle Verzögerungen entfernen), wird die LED mit voller Helligkeit eingeschaltet. Ich habe überlegt, ob die Optimierung selbst ein Problem sein kann, aber im Regime ohne Verzögerungen funktioniert das Programm in jedem Fall korrekt - mit oder ohne Optimierung.
Die Steuerung von irgendetwas mit der Schaltfläche würde eine Entprellung und die gleiche _delay_ms () -Funktion erfordern, die bei mir nicht funktioniert.
UPD : Das Auskommentieren #define F_CPU 1000000UL
oder Erhöhen des Arguments von _delay_ms()
hilft nicht. Eine Erhöhung der Verzögerungszeit durch Iteration for (i=0; i<100000; i++) {_delay_ms(1000);}
führt jedoch dazu, dass die LED ständig mit voller Helligkeit eingeschaltet wird. Getestete kleinere Iterationszeiten (10, 100, 1000, 10000) ergeben keine volle LED-Helligkeit.
Das Problem ist, dass Sie eine Objektdatei erstellen, aber nicht verknüpfen. Ohne Verknüpfung werden Verzweigungsbefehle im Maschinencode nicht mit den erforderlichen Zieladressen gefüllt, sodass der Code einfach linear ausgeführt wird, bis er vom Ende in den nicht zugeordneten Speicher „fällt“. Schließlich erreicht es das Ende des Speichers und springt auf Null, um Ihren Code erneut auszuführen. Das Endergebnis ist, dass die LED mit einem sehr niedrigen Arbeitszyklus blinkt.
Die einfachste Lösung besteht darin, die -c
Option einfach aus Ihrem Kompilierungsbefehl zu entfernen, dh: -
avr-gcc -mmcu=attiny26 -O1 main.c
Dadurch wird eine ELF-Datei mit dem Namen "a.out" erstellt, die Sie in HEX konvertieren mit: -
avr-objcopy -O ihex a.out main.hex
Die maximale Verzögerung, die Sie mit _delay_ms() erreichen können, sollte 262,14 ms / F_CPU in MHz nicht überschreiten. Das sind in Ihrem Fall 262,14 ms. Ansehen
void _delay_ms(double __ms)
in diesem Link für weitere Informationen.
Eine Problemumgehung besteht darin, mehrere Male für eine kürzere Zeitspanne zu verzögern.
Zum Beispiel:
for(int i=0; i<5; i++)
delay_ms(200);
_delay_ms(1000);
eine Verzögerung von 100ms._delay_ms(65535);
DigitalNinja
#define F_CPU 1000000UL
?krambo
Bruce Abbott
Antonio
/usr/lib/avr/include/util/delay.h:90:3: warning: #warning "F_CPU not defined for <util/delay.h> [-Wcpp] # warning "F_CPU not defined for <util/delay.h>"
und es ändert nichts - ich sehe dieselbe gedimmte LED. Laut delay.h wäre die F_CPU sowieso standardmäßig gleich:#ifndef F_CPU /* prevent compiler error by supplying a default */ # warning "F_CPU not defined for <util/delay.h>" # define F_CPU 1000000UL #endif
Antonio
_delay_ms()
. Anstatt dem ein sehr großes Argument zu geben_delay_ms()
, habe ich versucht, es mit Iteration zu tun:for (i=0; i<100000; i++) {_delay_ms(1000);}
. Ich habe es auf 10, 100, 1000, 10000, 100000 Wiederholungen überprüft. Bei hohem Faktor 100000 wirkt die LED so hell wie ohne Verzögerung, aber immer noch eingeschaltet.Antonio
F_CPU
?Antonio
avrdude: safemode: Fuses OK (E:FF, H:F7, L:E1)
krambo