Ich habe einige Probleme, mich darum zu kümmern, und es könnte nur irgendwo ein kleiner Fehler sein, den ich immer wieder übersehe Code wird ausgeführt.
Zu Übungszwecken versuche ich einfach, eine LED an PD4 im Abstand von 1 Sekunde zu blinken.
Ich habe die folgende Formel verwendet, um den Prescaler und den Wert des Output Compare Register A (OCR1A) zu bestimmen:
Mit einem Prescaler von 256 erhalte ich einen Wert für OCR1A von 62499:
Wenn ich mir die Register TCCR1A und TCCR1B im Datenblatt ansehe, setze ich die Waveform Generation Mode-Bits (WGM) auf die Verwendung von CTC und die Clock Select-Bits auf die Verwendung des 256 Prescalers.
Jetzt beginne ich in meiner Hauptfunktion, indem ich die LED einschalte und dann meine Funktion aufrufe, die den Timer starten soll. Dann überprüfe ich, ob das Überlauf-Flag in TIFR1 gesetzt wurde, und wenn ja, schalte ich die LED aus und schreibe eine logische 1 an TOV1, um das Überlauf-Flag zurückzusetzen.
int main(void) {
DDRD = 0xFF;
PORTD = 0x00;
while (1) {
// Turn on LED at PD4
PORTD |= (1 << PD4);
oneSecondDelay();
// Checking to see if the overflow flag has been set
if (TOV1 == 1) {
// Turn off LED at PD4
PORTD &= ~(1 << PD4);
// Set 1 in the Output Compare A Flag to reset the overflow flag
TIFR1 = (1 << TOV1);
}
}
return 0;
}
In meiner Funktion beginne ich damit, OCR1A auf den Wert zu setzen, den ich zuvor berechnet habe. Ich setze dann die Bits im TCCR1B-Register, die für die Verwendung des spezifischen Vorteilers und des CTC-Modus gesetzt werden müssen, und erstelle dann eine Schleife, während ich auf das Überlaufereignis warte; was ich mir vorstelle, sollte eine Sekunde dauern.
void oneSecondDelay() {
// Set the target value to 62499
OCR1A = 0xF423;
// Set prescaler to 256 and start the timer
TCCR1B |= (1 << WGM12) | (1 << CS12);
// Waiting for the overflow event
while ((TIFR1 & (1 << OCF1A))) {
}
}
TLDR: Jetzt ist das Problem, dass, egal was ich mir ausdenken kann, die LED einfach ständig eingeschaltet ist und ich nicht sicher bin, ob ich die falschen Werte in den Registern einstelle oder ob ich nur ein paar Gehirnfurze habe?
void oneSecondDelay() {
Das Konstrukt dieser Funktion ist nicht besonders optimal. Sie hätten leicht einen Parameter verwenden können, um die Länge der Verzögerung zu bestimmen, ganz zu schweigen von anderen Problemen.
Eine schnelle Lösung wäre so etwas - es hat immer noch Probleme, ist aber zumindest praktikabel.
//create a user-specified delay
//dly-duration in timer ticks
//timer1 presummed running, running at 256:1 prescaler
void myDelay(uint16_t dly) {
// Set the target value to 62499
OCR1A = TCNT1 + dly - 1; //0xF423;
// Set prescaler to 256 and start the timer
//TCCR1B |= (1 << WGM12) | (1 << CS12);
TCCR1B = (TCCR1B &~0x07) | (TMR1_PS256x & 0x07); //set timer1 prescaler to 256:1
// Waiting for the overflow event
while ((TIFR1 & (1 << OCF1A)) == 0) {
}
TIFR1 |= (1<<OCF1A); //clear the flag
}
dieses Stück Code in Aktion, wenn TMR1_PS100ms als Parameter zugeführt wird:
Das Ziel beim Schreiben von Code ist, dass Sie ihn nicht noch einmal schreiben müssen. Auf diese Weise ist alles, was Sie schreiben, eine Investition, keine Ausgabe.
G36
Bence Kaulics
Michael Nissen
Andy
PORTD ^= 1 << PD4;
Michael Nissen