Schönen guten Tag, ich bin seit knapp einer Woche am µC programmieren und wollte nun einen Interrupt bei jedem Übergang von Timer0 (8-bit) auslösen. Funktion des Programms und Aufbau sind eigentlich sehr simpel: Eine LED (PortE am PIN4) soll vom Interrupt immer wieder eingeschaltet werden. int main(void) {DDRE= (1<<DDE4); TCCR0A= (1<<CS02) | (0<<CS01) | (1<<CS00); //Prescaler 1024 TCNT0= 0x00; //Zähler auf 0 gesetzt TIMSK0= (1<<TOIE0); //Timer0 wird aktiviert sei(); while(1) { PORTE= (1<<PE4); } } ISR(TIMER0_OVF_vect) { PORTE = (0<<PE4); } Allerdings geht es das Programm gar nicht in den Interrupt und die LED bleibt dauerhaft aus. Mittlerweile habe ich das Datenblatt schon 100x durchwühlt, mit anderen Codes verglichen etc... Ich muss irgendwie an einer Stelle ein riesiges Brett vorm Kopf haben :) Liebe Grüße, Alex
Also was zunächst mal auffällt, du willst die LED mit "0" einschalten und mit "1" ausschalten? Zudem wirst du das, was die ISR macht gar nicht bemerken, da sofort deine Hauptschleife die LED wieder auf "1" setzt: >while(1) > { > PORTE= (1<<PE4); > }
Alles klar, vielen Dank. Das stimmt natürlich! Jetzt steht in der while-Schleife nichts und im ISR Folgendes: ISR(TIMER0_OVF_vect) { if (PORTE & (0<<PE4)) { PORTE = (1<<PE4); } if (PORTE & (1<<PE4)) { PORTE = (0<<PE4); } Anfangs habe ich PE4 im Main auf 0 gestzt. Die LED leuchtet dauerhaft und geht immer noch nicht in den ISR Ich muss den Pin zum Einschalten der LED auf 0 setzen, damit er auf Masse gezogen wird.
Hi > PORTE = (1<<PE4); > } > if (PORTE & (1<<PE4)) > { > PORTE = (0<<PE4); > } Rate mal was die if-Anweisung macht, wenn du vorher PR4 auf 1 gesetzt hat? MfG spess
Am einfachsten kannst du den Pin mit einem XOR toggeln: PORTE ^= (1<<PE4); Angenommen, PE4 = 0: 0 XOR 1 = 1 analog PE4 = 1: 1 XOR 1 = 0 Dein µC sollte auch ein PINE4 = 1 zum toggeln verwenden können. Allgemein ist auch die Schreibweise ~(1<<PE4) verbreiteter als (0<<PE4).
> Allgemein ist auch die Schreibweise ~(1<<PE4) verbreiteter als (0<<PE4).
'verbreiteter' ist gut gesagt.
Man könnte auch so sagen, dass (0<<PE4) einfach nur Unsinn ist, auch
wenn es in diesem konkreten Programm keine Rolle spielt, weil nur 1 Pin
am Port benutzt wird.
Wenn schon, dann könnte man auch so sagen, dass ein simples 0
verbreiteter ist als (0<<PE4). Denn
1 | PORTE = (0<<PE4); |
ist in allen Belangen identisch zu
1 | PORTE = 0; |
das Erwähnen von PE4 dient hier nur der "Ablenkung" (freundlich ausgedrückt). Bitmanipulation Der Teil muss im übrigen aus dem FF sitzen, wenn du zu Timern voranschreitest. Bits gezielt setzen, löschen und abfragen zu können ist Grundfertigkeit in der µC-Programmierung. Das muss auch nach durchzechter Nacht um 6 Uhr früh aus dem Stegreif fehlerfrei und wie aus der Pistole geschossen funktionieren.
Ja ihr hattet Recht. Habe jetzt das mit der Bitmanipulation noch einmal gründlichst studiert und so weit es geht verinnerlicht...Übung macht den Meister :) Allerdings leuchtet die LED immer noch dauerhaft, obwohl ich jetzt Pin4 im Interrupt toggeln lasse. Habt ihr vielleicht noch andere Ansätze was falsch gehen könnte? Gruß, Alex
Alexander schrieb: > Allerdings leuchtet die LED immer noch dauerhaft, obwohl ich jetzt Pin4 > im Interrupt toggeln lasse. Das würden wir gerne alles mal sehen. Wie immer gilt: Wenn du Hilfe zu einem Programm willst - zeig dein Programm. Und zwar so, wie es jetzt ist. Was du gestern programmiert hast, gilt alles nichts mehr, denn in der Zwischenzeit hast du Veränderungen am Programm gemacht. Auf dieser Seite des Monitors kann aber keiner riechen, welche Veränderungen du vorgenommen hast. Im übrigen: Hast du schon mal durchgerechnet, wie schnell deine LED eigentlich blinken sollte?
> Im übrigen: Hast du schon mal durchgerechnet, wie schnell deine LED > eigentlich blinken sollte? Ja das sollte bei meinem 16MHz Prozessor, dem 8-bit Timer und dem Prescaler von 1024 so um die 30Hz sein. Ich denke, man erkennt dann wenigstens ein Flackern der LED. Hier der Code:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | int main(void) |
5 | {DDRE= (1<<DDE4); |
6 | PORTE= (1<<PE4); |
7 | TIMSK0= (1<<TOIE0); |
8 | TCCR0A= (1<<CS02) | (0<<CS01) | (1<<CS00); |
9 | TCNT0= 0x00; |
10 | |
11 | sei(); |
12 | |
13 | while(0) |
14 | {
|
15 | }
|
16 | }
|
17 | |
18 | ISR(TIMER0_OVF_vect) |
19 | {
|
20 | PORTE ^= (1<<PE4); |
21 | }
|
mach dir das leben doch nicht so schwer... entweder setzt du dir einen breakpoint, um festzustellen ob die die ISR routine erreichst... oder du setzt den PIN einfach HIGH... sobald die LED leuchtet weißt du die ISR wurde erreicht.. durch das fehlerhafte bit shifting und vielleicht auch fehlerhafte timing bekommst du nie das vor augen was du gerne hättest... fang doch erst mal klein an ;-)
Alexander schrieb: > Ja das sollte bei meinem 16MHz Prozessor, dem 8-bit Timer und dem > Prescaler von 1024 so um die 30Hz sein. Ich denke, man erkennt dann > wenigstens ein Flackern der LED. Darauf würde ich nicht wetten.
1 | uint8_t cnt; |
2 | |
3 | ....
|
4 | |
5 | ISR(TIMER0_OVF_vect) |
6 | {
|
7 | cnt++; |
8 | |
9 | if( cnt == 20 ) { |
10 | cnt = 0; |
11 | PORTE ^= (1<<PE4); |
12 | }
|
13 | }
|
Jetzt müsstest du das Blinken auf jeden Fall sehen.
So habe jetzt mal zur Sicherheit den 16-bit Timer genommen und den Pin toggeln lassen. Jedenfallf funktioniert es jetzt und ich danke recht herzlich für die Hilfe! Gruß, Alex
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.