Hallo, ich bin noch Anfänger in Sachen Atmel. Ich habe ein Testprogramm geschrieben (Ampelschaltung nach einer Projektvorgabe). Nun zum Problem: Es funktioniert auch soweit, bloß manchmal scheint der Timer zu hängen. In der "Nachtschaltung" sollten die LEDs mit 0,5Hz blinken doch manchmal scheinen diese zu hängen als wenn einmal vergessen wird , den Blinktakt umzuschalten. Verwendet ist ein Atmega8, ich habe mich schaltungstechnisch an dem LCD2USB-Projekt orientiert (Grundschaltung ohne USB), die Dioden verwenden alle eine gemeinsame Anode. Externer Takt mit 12MHz-Quarz. Was ist falsch? Gruß, Sven
Okay, das habe ich aus dem Tutorial übernommen... Daran soll es liegen? Was immer das auch heißen mag...
Daran muss nicht alles liegen, aber das ist zumindest ein Grund, warum es nicht sauber funktionieren dürfte. Du möchtest Dich über den Qualifier „volatile“ im Zusammenhang mit Übergaben vom und zum Interrupt informieren. Die Suchfunktion dürfte Dir weiterhelfen, denn es ist ein, wenn nicht der Standardfehler.
Danke erst einmal für die Hilfe. Naja wie gesagt, das steht so im Tutorial und als ich gesucht habe, bin ich nicht drauf gestoßen. Es sieht schon wesentlich besser aus, auch wenn ich nun das Gefühl habe, dass er ggf. zwischendurch 1-2x etwas zu schnell blinkt, aber das kann auch eine Täuschung sein. Morgen ggf. mal ein Oszilloskop dranhängen, dann sehe ich ja, wie "sauber" das Signal ist. So, während ich das geschrieben habe, hat die Schaltung 4x hintereinander schneller geblinkt. Okay, die "Hänger" sind weg, aber der Timer ist noch unregelmäßig.
mizch schrieb: > volatile mizch meinte damit daß du z.B. vergessen hast den Struct "x" als volatile zu deklarieren. (Gilt für alle Variable die sowohl im Hauptprogramm als auch im Interrupt verwendet werden). Bei der Optimierung rechnet der Compiler sonst nicht damit daß sich die Variable ändern könnte. Er liest sie dann ggf. nur ein einziges Mal und dann nie wieder. Die volatile -Deklaration verhindert diese Optimierung. Gruß Anja
Okay Danke, ich hatte natürlich volatile komplett gelöscht, da ich das so verstanden habe. Aber: Mit volatile habe ich die Hänger, ohne volatile läufts ab und an schneller.
Nein gemeint ist, dass du zb x.ein sowohl in der ISR als auch im Hauptprogramm benutzt. Daher sollte das auch volatile sein
Allerdings bin ich nicht wirklich davon überzeugt, das das hier konkret das Problem ist. Deine Statemaschine ist so dermassen unübersichtlich und kompliziert, das Problem wird wohl dort irgendwo zu suchen sein. Die struct die du hast: wirf sie raus. SIe erfüllt keinen sinnvollen Zweck. Mach da normale Variablen draus und die die es brauchen zusätzlich auch noch volatile. Sinnvoll wäre eine struct, die einen Zustand deiner Statemachine beschreibt. Ein derartiger Zustand ist gekennzeichnet durch auszugebende Bitmuster an Port B auszugebende Bitmuster an Port C auszugebende Bitmuster an Port D Zeitdauer des Zustands Nummer des nächsten Zustands was du sonst noch brauchst Da könntest du eien struct sinnvoll einsetzen. Deine Statemachine ist dann einfach nur ein Array aus derartigen Strukturen. Und dein Hauptprogramm wird sehr einfach werden. Die ganze Logik der Zustandsmaschine steckt einzig in den Daten im Array. Dort ist der Ablauf kodiert.
Also falls mit Statemaschine die Zählerstandsabfrage gemeint sein sollte: Diese wird ja im sog. Nachtbetrieb nicht verwendet. Ursprünglich wollte ich auch nur die Ausgänge ändern, die sich bei einer Zählerstandsänderung ändern, aber da das Blinken gestört ist, hatte ich die Befürchtung, dass er sich ggf. verzählt und das wäre fatal, wenn nachher alle gleichzeitig grün hätten oder so.
Hey danke, das Problem war echt das struct. Aber wie könnte ich das denn mit dem struct lösen bezüglich Übersichtlichkeit? Kann ich dann z.B. sagen: "PORTB=x"?
1 | struct state |
2 | {
|
3 | uint8_t BitsB; |
4 | uint8_t BitsC; |
5 | uint8_t BitsD; |
6 | uint8_t nextState; |
7 | };
|
8 | |
9 | struct state Ampel[] = |
10 | {
|
11 | // Bits an B (BitsB)
|
12 | // Bits an C (BitsC)
|
13 | // Bits an D (BitsD)
|
14 | // nächster Zustand (nextState)
|
15 | { 0x00, 0x00, 0x00, 1 }, |
16 | { 0xFF, 0x00, 0x00, 2 }, |
17 | { 0x00, 0xFF, 0x00, 3 }, |
18 | { 0x00, 0x00, 0xFF, 0 }, |
19 | };
|
20 | |
21 | int main() |
22 | {
|
23 | ...
|
24 | |
25 | zustand = 0; |
26 | while( 1 ) { |
27 | |
28 | |
29 | PORTB = Ampel[ zustand ].BitsB; |
30 | PORTC = Ampel[ zustand ].BitsC; |
31 | PORTD = Ampel[ zustand ].BitsD; |
32 | |
33 | zustand = Ampel[ zustand ].nextState; |
34 | |
35 | _delay_ms( 500 ); |
36 | }
|
37 | }
|
> Kann ich dann z.B. sagen: "PORTB=x"?
Schön langsam werde ich es müde, immer und immer wieder denselben Satz
stereotyp vorzubeten:
Kauft euch Literatur!
Ihr laboriert an 'Problemen' rum, die in jedem noch so grindigen
C-Lehrbuch ausführlich und erschöpfend erklärt werden.
Manchmal hasse ich die "Ich such mir im Internet mein Halbwissen
zusammen weil Buch lesen so uncool ist"-Generation.
Sorry, Bücher habe ich hier auch schon zwei und ich brauche das Teil bis übermorgen also habe ich nicht die Zeit diese 1000-Seiten durchzulesen. Mein Hauptproblem war halt, wie ich ein struct den Ports zuweisen kann. Auf dieses Doppelstructungetüm bin ich nun mal nicht gekommen. 2. Problem: An Port B+C hängen Taster und ich war mir nicht sicher, ob ich dann einfach zuweisen darf ansonsten hätte ich Bitmuster zugewiesen (0b00011111 oder dergleichen). Okay, das Codebeispiel würde so nicht klappen, aber ich wüsste nun, wie ich das umsetzen müsste. Danke. Auflage ist das exakte Timingdiagramm so wie verwendet (Zähler von 0-30). Mit delay möchte ich auch ungerne arbeiten, damit ich Blinktakt (Nachtschaltung) und Zähltakt trennen kann. Außerdem müsste der Zähltakt erniedrigt werden, wenn die Schaltung unter "realen" Bedingungen laufen soll und da wäre ein delay von 10s hinderlich bzgl. Tastendruck.
Also mit dem struct geht es nicht - es passiert das, was ich befürchtet hatte: Die Taster (Eingänge) versagen den Dienst!
das hat doch mit dem struct nichts zu tun, du musst bei der Zuweisung zum Port nur dafür sorgen, das nur die Ausgangsbits geändert werden. mal angenommen PB0 und PB1 sind Tastereingänge alt: > PORTB = Ampel[ zustand ].BitsB; neu: > uint8_t temp; > .... > .... > temp = PORTB & 3; * nur Bits die nicht verändert werden dürfen (taster) > PORTB = temp | (Ampel[ zustand ].BitsB & 252); * und die neuen Ausgangsbits dazu > .... > .... deine Wartezeit packst du einfach noc in den struct mit rein, und die Tag/Nacht-schaltung realisierst du in dem du in dem struct 2 Bereich verwendest, die mit dem nextState in sich geschlossen sind aber über deinen taster oder wie auch immer umschaltbar sind. z.B. 0 bis 25 Tag (bei 25 Rücksprung zu 0) Nacht -> Umschaltung auf 26 26 bis 35 Nacht (bei 36 Rücksprung auf 26) Sascha
Hmm okay, werde es mal testen, danke Nein, die Auflage war, ein festes Taktdiagramm zu verwirklichen eigentlich per SPS. Das Atmel-Board dient dazu zu zeigen, dass es auch anderweitig geht, wir uns aber dagegen entschieden haben. Naja und der C++-Kurs beginnt erst in ein paar Monaten, leider. Ich habe die Schaltung aber soweit hinbekommen mit Ablauf, indem ich gesagt habe, wann die nächste Änderung stattfindet und wenn der Zähler dahinspringt, hüpft er nun eine Zeile weiter. Das mit der Bit-Einschränkung werde ich mal antesten. Ich kann zwar etwas Java und auch C, aber dieses struct-Gerippe ist für mich doch recht komplex gewesen, auch wenn ich es nun verstehe, aber hey, das ist mein erstes Projekt mit dem Atmel, also das erste Programm, welches ich selber schreibe. Ich hatte zuvor nur ein paar Schaltungen aus dem Netz nachgebaut. Eigentlich wollte ich mit was simplen anfangen wie: Ich drücke einen Taster und ein Licht geht an und aus... Naja ich packe den Code mal in den Anhang, allerdings ist das struct-Gerippe auskommentiert, da es ja (noch) nicht läuft... Gruß, Sven
Ich bekomme langsam eine Krise... Der Trick funktioniert zwar, allerdings nur für einen Durchlauf. Wenn die Position zurückgesetzt wird, dann gehen alle Ausgänge auf null (und somit alle LEDs an), aber wieso?!
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.