Vor kurzem habe ich begonnen, die Atmega328P in reinem c/C++ zu programmieren, ohne alle Arduino-Bibliotheken und Arduino-IDE. Ich möchte eine LED mit einer Rate von 1 Hz (1 Sek. Ein, 1 Sek. Aus) blinken lassen. Leider kann ich nur Timer0, einen 8-Bit-Timer verwenden. Das MCU hat eine Taktfrequenz von 16MHz und ich habe einen Vorskalierer von 1024 gewählt, um die Anzahl der Überläufe so gering wie möglich zu halten, um Jitter zu reduzieren, da eine Interruptroutine immer einen Overhead hat (das macht mehr Sinn, wenn Sie den Rest meiner Frage lesen) . Mit einfacher Mathematik, ich Schluss kam, dass nach 1 Sekunde, Timer0
61 mal übergelaufen ist und dass das TCNT0
Register gleich 8.enAVR 8-Bit-Timer - was tun, wenn der Vergleichswert nicht in das Register passt?
Dann kam ich mit dieser Lösung:
#define F_CPU 16000000ul
#include <avr/io.h>
#include <avr/interrupt.h>
#define bit(b) (1 << (b))
void initBlinkTimer()
{
//Timer0 with CTC Mode
TCCR0A |= bit(WGM01) | bit(WGM00);
//Compare TCNT0 with 8
OCR0B = 8;
//Interrupt at OCR0B compare match aka: execute interrupt when TCNT0 equals 8
TIMSK0 |= bit(OCIE0B);
//Set PB5 as output
DDRB |= bit(PB5);
//Set the prescaler to 1024
TCCR0B |= bit(CS02) | bit(CS00);
//Enable global interrupts, so that the interrupt routine can be executed upon the OCR0B compare match
sei();
}
//Keeps track of the number of overflows
volatile unsigned char nOverflows = 0;
ISR(TIMER0_COMPB_vect)
{
if(nOverflows >= 61)
{
//Toggle PB5
PORTB ^= bit(PB5);
//Reset timer
nOverflows = 0;
TCNT0 = 0;
}
else
{
nOverflows++;
}
}
int main()
{
initBlinkTimer();
while(1){}
}
Dieser Code initialisiert eine 8-Bit-CTC-Timer mit einem Prescaler von 1024. Eine Interrupt-Service-Routine (ISR) wird ausgeführt, wenn TCNT0 gleich OCR0B ist, was ich in meinem Code auf 8 gesetzt habe. In der ISR wird die nOverflows
Variable mit 61 verglichen. Wenn nOverflows
gleich 61 ist, ist eine Sekunde vergangen und der PB5 Pin wird umgeschaltet. Es führt auch eine Größer-als-Prüfung durch, falls der MCU den 61. Überlauf verfehlt hat (wenn das in diesem Fall irgendwie möglich ist). Der Timer und die Variable nOverflows
werden gelöscht, nachdem der Pin umgeschaltet wurde. Der Timer beginnt dann wieder bei Null.
Meine Frage ist: Ist dies eine gute Möglichkeit, eine LED bei 1Hz zu blinken, wenn nur ein 8-Bit-Timer verfügbar ist? Kann/sollte ein Teil davon in der Hardware statt in der Software implementiert werden?
Es ist so gut wie jeder ... –
Wenn ein Timer keine lange Zeitspanne hat, konfigurieren Sie es so, dass es zu einem Bruchteil der erforderlichen Zeit unterbricht, und erhöht einen statischen Zähler, so dass Wenn die erforderliche Zeit erreicht ist, invertieren Sie den LED-Status und setzen den Zähler zurück. –
@ user7353781 Ich dachte meine Antwort war ziemlich umfangreich, also bitte überlege, ob du das Häkchen anklickst, um es zu akzeptieren. –