Hallo alle miteinander, ich soll von der Schule aus einen ATmega32 programmieren, dabei soll ausdrücklich mit Interrupts gearbeitet werden. Am Port A sind ganz klassisch 8 LEDs angebracht. Die erste Aufgabe lautet den Port A für 1 Sekunde lang ansteuern und dann alle LEDs ausschalten und in einer endlos Warteschleife enden. Dazu habe ich mal meinen Sourcecode hochgeladen würde mich über Feedback freuen. Die zweite Aufgabe ist eine Interruptserviceroutine zu schreiben, die abhängig vom aktuellen Zustand(0-7) die Leuchtdioden im Sekundentakt umschaltet, sodass sie ein Lauflicht von rechts nach links ergeben. Dabei soll wieder der Timer 1 verwendet werden. Für den Zustand soll eine variable vom Typ unsigned char verwendet werden. Komme bei der zweiten Aufgabe einfach nicht weiter hättet ihr dazu irgendwelche Ideen wie man das umsetzen kann? Schon im voraus vielen Dank für eure Hilfe. Gruß Paul
@ Karl Heinz Danke für das Feedback habe den Code nochmal überarbeitet und eingekürzt hoffe er läuft noch richtig. Wäre nett wenn da jemand mal drüber schauen könnte. Gruß Paul
Hallo alle miteinander habe mich jetzt auch mal am zweiten Aufgabenteil versucht. Bin mir nicht sicher ob es funktioniert. Leider bekomme ich es nicht hin das der Simulator im avr studio 6 mir anzeigt ob das Programm das macht was es soll. Hätte jemand einen Tipp? Gruß Paul
Hallo Ich denke das ist noch "größerer Unfug". Eine ISR sollte möglichst fix abgearbeitet werden und nur den zwingend notwendigen Code enthalten. Daran musst du dein Problem ausrichten. Wenn noch nichts zu schalten ist musst du ganz fix wieder raus aus der ISR.
1 | for(z=0;z<8;z++) |
2 | {
|
3 | PORTA=(1<<z); |
4 | }
|
Die for-Schleife läuft mit maximaler Geschwindigkeit (vielleicht 1Mhz), sie steht auch noch innerhalb der while-Schleife und wird ständig ausgeführt, sobald auch nur ein Mal die ISR aufgerufen wird. Beim ersten "tick" läuft also dauerhaft deine Schleife durch, womit es so aussehen wird als ob durchgängig alle LEDs leuchten. Du brauchst weder die while, noch die for Schleife. Aus Gründen der Übersicht könntest du statt
1 | TCCR1B=1<<WGM12; //Timer 1 mode auf CTC setzen mit Vergleichsregister OCR1A |
2 | TCCR1B|=1<<CS12; //Prescaller setzen auf 1024 |
3 | TCCR1B|=1<<CS10; |
auch
1 | TCCR1B = (1<<WGM12) | (1<<CS10) | (1<<CS12); |
schreiben.
Danke für die Hilfe. Das Problem mit der For Schleife habe ich verstanden. Wenn ich nun aber die While und For Schleife raus nehme, habe ich aber doch kein Lauflicht mehr. Wie realisiere ich das Lauflicht denn sonst? Gruß Paul
> Wie realisiere ich das Lauflicht denn sonst?
Deine ISR wird sekündlich aufgerufen, das ist dann deine Schleife mit
definierter Durchlaufzeit.
Wie in den meisten anderen Schleifen auch, kannst du nun eine Variable
hochzählen und sie benutzen:
1 | #define LEDS 8
|
2 | |
3 | // ...
|
4 | |
5 | ISR(...) { |
6 | static int z=0; // static: zahl bleibt für den nächsten schleifendurchlauf erhalten, steht an fester speicherstelle. |
7 | |
8 | if(++z >= LEDS) {z=0;} // z wird zuerst erhöht, dann mit LEDS verglichen |
9 | // wenn du bei der letzten LED angekommen bist, wieder zur ersten springen.
|
10 | |
11 | // benutze das z !
|
12 | |
13 | }
|
@ paulnothu (Gast) > mc1fertig.c (1 KB, 5 Downloads) | Codeansicht Eine Endlosschleife im Interrupt? Nicht wirklich ;-) >Danke für die Hilfe. Das Problem mit der For Schleife habe ich >verstanden. Glaub ich nicht. >Wenn ich nun aber die While und For Schleife raus nehme, >habe ich aber doch kein Lauflicht mehr. Dann muss man es halt anders machen. >Wie realisiere ich das Lauflicht denn sonst? Siehe mein vorheriges Posting. Und lies den Artikel LANGSAM und MEHRFACH, denk drüber nach. Ist eigentlich nicht so schwer, das Prinzip zu verstehen.
Die while(1) Schleife wird trotzdem benötigt, da das main-Programm nie enden darf! Also while(1) Schleife leer lassen und im Timer Interrupt den Pin weiterschalten.
Ich habe jetzt versucht den Vorschlag von Adrian(vielen Dank dafür) in meinen Code zu integrieren. Bin mir aber nicht sicher das er auch das Lauflicht mit einer Sekunde unterbrechung realisiert. Im avr studio Simulator zeigt er mir das zu mindestens nicht an. Ist der Source Code so richtig? Gruß Paul
paulnothu schrieb: > Bin mir aber nicht sicher das er auch das Lauflicht mit einer Sekunde > unterbrechung realisiert. Tut er nicht ;) Die Stelle "// benutze das z !" in meinem Code war durchaus ernst gemeint :) Du musst nur noch den Pin Z am gewünschten Port schalten. Mir ist auch nicht ganz klar, wozu du dein "enum LED" brauchst, es scheint keine Verwendung zu finden. Dir scheint es noch etwas am Grundverständnis zu fehlen, ich kann sehr das AVR-Turorial hier empfehlen, es hat mir oft geholfen.
Mit dem enum hast du recht stammt noch aus einem früheren Lösungsversuch. Jetzt erfüllt es tatsächlich keinen Nutzen mehr. Bin mir nicht sicher wie du das mit dem Pin schalten meinst. Würde das so lösen: z = PORTB | ( 1<<PB0 ); ist das so richtig? Weiß aber nicht wo das in den Code eingebaut gehört. Könnte jemand meinen Sourcecode vielleicht ergänzen; sodass ich das Programm mal durch den Simulator laufen lassen kann. Bräuchte mal wieder ein Erfolgserlebnis. Gruß Paul
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.