Hallo, ich möchte Testweise zum Interrupt einen Atmega 168 Controller so Programmieren das auf dem Display von 100 nach oben gezählt wird. Folgenden Code habe ich programmiert, jedoch funktioniert mein gewünschtes Ergebnis nicht. Woran könnte das liegen? Die Interrupt Routine wird anscheinend nicht ausgeführt.
1 | volatile int i; |
und das 'int' solltest du dir nochmal ganz genau überlegen. Wenn es nicht notwendig ist, benutzt man kein int. Und in dem Fall schon gleich gar nicht, denn dann wird das Thema gleich nochmal komplizierter, weil dann zusätzlich auch noch atomarer Zugriff sicher gestellt sein muss. FAQ: Was hat es mit volatile auf sich
Und poste deinen Code nächstes mal als normale Programmdatei. Du kannst dein C-File ruhig problemlos hier anhängen. In deinem Programm sind nämlich noch ein paar andere Dinge. Nur hab ich jetzt ehrlich gesagt keine Lust, die aus dem Bild abzutippen. Postest du dein Programm als stink normalen Text, dann nehm ich Strg-C und Strg-V um mir die relevanten Teile rauszuschneiden. In Summe ist das für dich weniger Arbeit und für uns auch.
Kurz gesagt, dreht sich dein Problem darum, dass du zwar innerhalb des abhängigen Teils vom if die Ausgabe machst, dort dann aber auch immer i auf 100 setzt. Wird die Ausgabe gemacht (wegen dem if), dann nicht ohne vorher i auf 100 gesetzt zu haben. Lässt du aber das i in Ruhe (weil der vom if abhängige Teil nicht genommen wird), so dass die ISR den Wert hochzählen könnte, dann wird auch keine Ausgabe gemacht (weil ja der if-Teil nie genommen wird).
Okay, die if-Schleife ist in diesem Fall nicht notwendig. Aber wie kann ich die Variable so definieren das mit dem Interrupt gezählt werden kann?
Na ja ein bischen nachdenken musst du schon auch selber. Das sind 3 Baugruppen und ich stoss dich schon mit der Nase auf die Problemstellen. Du hast
1 | wiederhole |
2 | { |
3 | |
4 | wenn Taster gedrückt |
5 | { |
6 | setzte zaehler auf 100 |
7 | |
8 | gib zaehler aus |
9 | } |
10 | } |
Du willst aber
1 | wiederhole |
2 | { |
3 | |
4 | wenn Taster gedrückt |
5 | { |
6 | setze zaehler auf 100 |
7 | } |
8 | |
9 | gib zaehler aus |
10 | } |
denn die Ausgabe muss ja auch dann erfolgen, wenn der Taster nicht gedrückt ist. Schliesslich verändert ja die Interrupt Routine auch den Zaehler. Und das möchtest du ja auch auf der Anzeige sehen. Also darf die Ausgabe nicht davon abhängen, ob die Taste gedrückt ist oder nicht. Das die Variable volatile sein muss, hab ich dir ja schon gesagt. Also rann ans Werk und die Logik des Programms verändern.
Ich habe das Programm jetzt folgendermaßen geändert, der Interrupt funktioniert jedoch immer noch nicht :-(
> TCCR0A = (1<<CS02); //TIMER definieren Das CS02 Bit ist im Register TCCR0B und nicht TCCR0A. > der Interrupt funktioniert jedoch immer noch nicht :-( Schon wieder die falsche Diagnose. Dein Timer läuft nicht, weil du keinen Vorteiler gesetzt hast. Hat der Timer den erst mal, dann funktioniert der Interrupt wunderbar.
Okay, aber mit
> TCCR0B = (1<<CS02);
ist der Vorteiler gesetzt?
Funktioniert aber trotzdem leider nicht.
DPlöching schrieb: > Okay, aber mit >> TCCR0B = (1<<CS02); > > ist der Vorteiler gesetzt? Ähm. Schau halt ins Datenblatt. Dazu gibt es das ja. Da ist eine schöne Tabelle, in der die Vorteiler aufgeführt sind und welche Bits dafür jeweils zu setzen sind. Dann zu den Registern scrollen und nachsehen welches Bit in welchem Register sitzt. > Funktioniert aber trotzdem leider nicht. Bei mir in der Simulation aber schon. Gut, ich hab den LCD-Teil rausgeworfen, weil ich den hier nicht simulieren kann. Der Timer läuft, die ISR wird aufgerufen, die Variable i zählt hoch. Alles so wie es sein soll.
> if ( PINB & (1<<0))
Was hängt da eigentlich drann?
Wenn das ein Taster in der üblichen Verschaltung (Taster schaltet auf
Masse durch, interner Pullup aktiviert) ist, dann ist das klar. Bei
jedem Durchlauf durch die Hauptschleife wird i wieder auf 100 gesetzt.
Da wird sich die ISR schwer tun, die Variable hochzuzählen.
Ich kann dich nur warnen: Dinge wie Tastenabfragen musst du im Schlaf
beherrschen! Sonst kommst du nie weiter.
Schmeiss doch den ganzen Dreck mal raus. Alles was für deinen Test nicht
absolut notwendig ist, wirfst du aus dem Programm raus. Das sind alles
erst mal Fehlerquellen, in denen du Fehler einbaust, die du selbst nicht
mehr findest und korrigieren kannst. Brauchst du einen Taster um den
Timer, bzw. den Overflow Mechanismus zu testen? Nein, brauchst du nicht.
Also weg damit.
Und PS: Um einen unsigned Wert auszugeben (wie zb uint8_t) heißt die
Funktion dafür utoa und nicht itoa. OK; Spielt jetzt bei dir zufällig
keine große Rolle. Trotzdem ist es gut, da ein wenig sorgfältig zu sein.
1 | int main() |
2 | {
|
3 | |
4 | ....
|
5 | i = 100; |
6 | |
7 | while(1) |
8 | {
|
9 | char Buffer[20]; |
10 | utoa( i, Buffer, 10 ); |
11 | |
12 | lcd_setcursor( 0, 2 ); |
13 | lcd_string( Buffer ); //Ausgabe LCD |
14 | }
|
15 | }
|
Jetzt funktioniert das Zählen,
habe jetzt die zweite Ausgabe auf dem Display, also
> lcd_string("uSiemens");
rausgenommen und jetzt funktionierts.
Danke für die Hilfe!
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.