Hallo Leute Ich habe folgendes Problem ich muss eine Alarmsteuerung programmieren und im Avr ausführen doch das Programm hat einen Fehler: Hier mal die Angabe damit ihr versteht wie es aussehen soll. Angabe vom Lehrer. Es gibt: a) Eingänge Störmeldung: Sto //steigende Flanke bedeutet Störung Taste: Ta //-----------//---- Taste gedrückt b) Ausgänge: Sirene S=0 // bedeutet Sirene ist an Lampe L=0 // bedeutet Lampe ist an c) Zustände: B // Betrieb A // Alarm W // Wartung Hier ist das Programm: #include <avr/stdio.h> #include <avr/interupt.h> #include <util/delay.h> #define F_CPU 12000000UL // definiere Frequenz #define B 0 // definiere Pin #define A 1 // definiere Pin #define W 2 // definiere Pin #define STO 2 // definiere Pin #define Ta 3 // definiere Pin #define S 0 // definiere Pin #define L 1 // definiere Pin volatile uint8_t eingang; // gilt für alle Funktionen volatile uint8_t zustand; // gilt für alle Funktionen int main() // Hauptfunktion { uint8_t ausgang[3]; while(1) // endlosschleife { switch(zustand) { case B; if(eingang&(1<<STO) == (1 << STO)) { zustand=A; } break; case A; if(eingang&(1<<Ta) == (1 << Ta)) { zustand=W; } break; case W; if(eingang& (1<<Ta) | (1 << STO) == (1 <<Ta)) { zustand=B; } break; } PORTC |= ausgang[zustand]; ausgang[0] |= (1<<L) | (1 << S); ausgang[1] &=~((1<<L) | (1<<S)); ausgang[2] = ausgang[2] &~ ((1<<S) | (1<<L)); Das Programm funktioniert leider nicht ich suche den Fehler aber finde ihn nicht. Ich bin nicht so gut aber es haut einfach nicht hin. Ich hoffe ihr hab ideen. Die Angabe ist vom Lehrer.
Argh, hab wohl gerade beim Tippen die "Schnellabschalteschließfunktion" von FF gefunden. Also zum Zweiten: Mike E. schrieb: > Ich habe folgendes Problem ich muss eine Alarmsteuerung programmieren Kein Problem. > und im Avr ausführen doch das Programm hat einen Fehler: Das Programm ist unvollständig, gehört in [c ]-Tags oder sollte als separate Datei angehängt werden (Endung .c). > volatile uint8_t eingang; // gilt für alle Funktionen > volatile uint8_t zustand; // gilt für alle Funktionen > uint8_t ausgang[3]; Wozu dieser ganze Zirkus? > ausgang[0] |= (1<<L) | (1 << S); > ausgang[1] &=~((1<<L) | (1<<S)); > ausgang[2] = ausgang[2] &~ ((1<<S) | (1<<L)); Sehr kunstvoll aber irgendwie unübersichtlich und vor allem komplett unnötig. Was du brauchst ist ein klassischer Zustandsautomat, eigentlich mehr eine VHDL-Aufgabe. (Lothar wo bist du? ;-)) Wir machen hier nicht deine Hausaufgaben, aber ein paar Tipps gibts natürlich.
1 | typedef enum {z_standby, z_alarm, ... } zustand_t; |
2 | |
3 | ....
|
4 | |
5 | int main(void) |
6 | {
|
7 | zustand_t zustand; //DEUTLICH besser als ein uint8_t, der könnte nämlich ungewünschte Werte annehmen. |
8 | |
9 | ....
|
10 | |
11 | while(1) |
12 | {
|
13 | //Erstmal die Übergangsbedingungen zwischen den Zuständen prüfen
|
14 | switch(zustand) |
15 | {
|
16 | case z_standby: |
17 | if(...) |
18 | zustand=....; |
19 | break; |
20 | case z_.... |
21 | ....
|
22 | }
|
23 | //Jetzt die Ausgänge anpassen
|
24 | switch(zustand) |
25 | {
|
26 | case z_standby: |
27 | //Ausgänge passend setzen
|
28 | break; |
29 | ...
|
30 | }
|
31 | ...
|
32 | }
|
33 | }
|
So ungefähr würde ich das machen. Man kann alles in einen switch packen, wird dann u.U. aber unübersichtlich.
Ach übrigens:
1 | #define B 0 // definiere Pin
|
2 | #define A 1 // definiere Pin
|
3 | #define W 2 // definiere Pin
|
4 | #define STO 2 // definiere Pin
|
5 | #define Ta 3 // definiere Pin
|
6 | #define S 0 // definiere Pin
|
7 | #define L 1 // definiere Pin
|
definiert erstmal keine Pins sondern nur Textbausteine für den Präprozessor. Wenn man 100 Zeilen später auf ein einzelndes 'B' stößt weiß keiner mehr was gemeint war. Soll heissen: Man sollte nur kommentieren wenn es wirklich nötig ist, auch wenn Lehrer gerne das Gegenteil behaupten. Auch sollte man nicht schreiben was man macht ("setze PORTB0 auf '1'" ist vollkommen sinnlos, das sieht man) sondern wieso man es macht oder wie genau. Im Idealfall erklärt sich der Code von selbst und die einzigen Kommentare sind der Name vom Autor usw. Dazu tragen auch klare Variablennamen und Präprozessormakros bei.
1 | #define SIRENE 0
|
2 | #define TASTER 5
|
3 | |
4 | #define PORT_SIRENE PORTB
|
5 | #define PIN_TASTER PINC
|
6 | |
7 | ...
|
8 | |
9 | if(PIN_TASTER & (1<<TASTER)) |
10 | PORT_SIRENE|=(1<<SIRENE); |
Alles klar?
Aufpassen
1 | if(eingang&(1<<STO) == (1 << STO)) |
gemäss den C Regeln wird das gelesen als (Ich ergänze mal Klammern um anzuzeigen, wie die Dinge zusammen gehören.
1 | if( eingang & ( (1<<STO) == (1 << STO) )) |
Manchmal, und ganz speziell in C, ist weniger einfach mehr
1 | if( eingang & (1<<STO) ) |
2 | {
|
3 | Code
|
4 | }
|
Der Code wird ausgeführt, wenn der Ausdruck
1 | eingang & (1<<STO) |
nicht 0 ergibt. Die einzige Möglichkeit, dass dieser Ausdruck nicht 0 sein kann, besteht darin, dass da das Bit STO gesetzt ist. Du musst hier nicht extra noch fordern, dass das Ergebnis der & Operation wieder 1<<STO sein muss. Es kann gar nichts anderes sein (oder 0). Aber wenn du das schon machst, dann musst du es richtig machen
1 | if( ( eingang & (1<<STO) ) == (1 << STO) ) |
aber eigentlich ist das unnötig und daher: weniger ist mehr. Das hier
1 | if(eingang& (1<<Ta) | (1 << STO) == (1 <<Ta)) |
geht so gar nicht. Der Zustand wird verlassen, wenn * Taster auf 1 ist UND * Störung auf 0 Solange du mit Operator-Precendence noch auf Kriegsfuss stehst, schreib das dann auch genau so hin und künstle nicht rum.
1 | if( ( eingang & (1 << Ta) ) && // Taster muss gesetzt sein |
2 | !( eingang & (1 << STO) ) ) // Störung darf nicht gesetzt sein |
Das Schema ist immer gleich. Die Pinabfrage lautet port & ( 1 << pin ) Sicherheitshalber kann man das in eine Klammer einschliessen, damit man bei Verknüpfungen keine Überraschungen erlebt. Und wenn man fordert, dass der Pin nicht gesetzt sein darf, dann kommt eben ein NICHT in Form eines ! vor den Ausdruck. Und natürlich all das was Feldinhalt schon angesprochen hat.
Karl Heinz Buchegger schrieb: > Das Schema ist immer gleich. Die Pinabfrage lautet > > port & ( 1 << pin ) Sorry für die Erbsenzählerei Karl Heinz, aber sonst kommt gleich das nächste Problem: Man spricht zwar von "Ports", um den logischen Wert abzufragen der am Eingang anliegt muss man beim AVR aber das entsprechende PIN-Register auslesen. Also NICHT PORTB & ... sondern PINB & ...
Feldinhalt schrieb: > Sorry für die Erbsenzählerei Wo du rechts hast, hast du recht. Das ist doch keine Erbsenzählerei :-)
Karl Heinz Buchegger schrieb: > Wo du rechts hast, hast du recht. Das ist doch keine Erbsenzählerei :-) ^^^^^^ Und wenn ich links habe? :-) Sorry, just kidding... Ich hab Kopfweh und geh gleich ins Bett, gute Nacht.
Es war soooo klar. Nachdem es keine fertige Lösung inkl. Doku gibt verschwindet der TO einfach ohne sich für die Mühe die Karl Heinz und ich uns gemacht haben zu bedanken. Ich HASSE solche Leute!
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.