Hi Leute, bin rel. neu im Bereich der µC-Programmierung und hoffe bei euch ein bissl Unterstützung zu finden :) Muss für meinen Opa die Steuerelektronik für seinen Treppenlift reparieren und habe daher leider nicht die Zeit alles (netz, Literatur) zu durchstöbern und mir selbst anzueignen. kommt aber alles noch... :) Habe folgendes Problem: Möchte am PORTB die Bits 0-3 abfragen und je nachdem wie sie geschaltet sind in PORTA die Bits 0-3 schalten. Arbeite mit dem ATMEGA16 und benutze das AVR ISP mkII als Programmierschnittstelle. Habe unten meinen Code gepostet. Da seht ihr bestimmt direkt den Mist den ich verzapft hab ;) Vielen Dank schonmal im Vorraus. #include <avr/io.h> #include <stdint.h> int main (void) { DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (1 << DDA3); // PortA auf Ausgang DDRB = (0 << DDB0) | (0 << DDB1) | (0 << DDB2) | (0 << DDB3); // PortB auf Eingang while (1) { // solange PINB0 und PINB1 == HIGH sollen PINA0, PINA1 und PINA3 HIGH sein while (PINB & (1<<PINB0 & 1<<PINB1)) { PORTA |= (1<<PORTA0 & (1<<PORTA1 & 1<<PORTA3); }; while ( PINB & (1<<PINB0 & 1<<PINB3) ) { PORTA |= (0<<PORTA0 & 0<<PORTA3); }; while ( PINB & (1<<PINB2 & 1<<PINB3) ) { PORTA |= (1<<PORTA0 & (1<<PORTA2 & 1<<PORTA3); }; }; return 0; }
Andyloco wrote: > // solange PINB0 und PINB1 == HIGH sollen PINA0, PINA1 und PINA3 HIGH > sein > while (PINB & (1<<PINB0 & 1<<PINB1)) { > PORTA |= (1<<PORTA0 & (1<<PORTA1 & 1<<PORTA3); > }; Laut Kommentar ist die Logikabfrage so zu machen while (PINB & ((1<<PINB0) | (1<<PINB1))) { PORTA |= ((1<<PORTA0) | ((1<<PORTA1) | (1<<PORTA3)); }; Die anderen Bedingungen habe ich nicht geprüft, weil keine Kommentare da sind und ich nicht weiss, was du machen willst.
Du weißt aber schon, daß ein while (a) {x} x erst verläßt, wenn a unwahr ist? Damit dürften Deine anderen 'whiles' erst abgearbeitet werden, wenn das vorherige while unwahr ist. Das wird so nix ;-) Grüße, Freakazoid
Vielen Dank für eure schnelle Hilfe!!! @Stefan "stefb" B. Habe deine Überarbeitung meines Codes ausprobiert, aber egal ob ich die Spannung an den beiden Pins anlege oder nicht ändert das nichts an den Ausgangspins, die bleiben auf 5V. Oder habe ich einen kompletten Denkfehler in der Struktur meines Programmes??? Das Programm soll nur die Zustände an den 4 Eingangspins prüfen und wenn eine der vorgegebenen Kombinationen (durch die unteren 3 while Bedingungen gegeben) eintritt die Ausgänge entsprechend schalten. @Freakazoid >Du weißt aber schon, daß ein while (a) {x} x erst verläßt, wenn a unwahr >ist? aber "a" wird doch durch die Spannung an den pins vorgegeben. Ich hatte mir gedacht, solange die Spannung an beiden Pins anliegt, dann soll die Bedingung erfüllt sein und sobald einer der beiden Pins LOW ist sollte die Bedingung nicht mehr erfüllt sein. Oder kann man das nicht auf diese Weise machen? Vielen Dank
> Oder habe ich einen kompletten Denkfehler in der Struktur meines > Programmes??? Yes! Wie oben beschrieben kann ich zum Rest nichts schreiben, weil du nicht angibst, was die Ausgangspins machen sollen, wenn die Bedingung nicht erfüllt ist. Ich schlage vor, dass du alle Zustände, die seine Steuerung annehmen kann zunächst mit Worten beschreibst. Beispiel: 1/ Lift wartet unten 2/ Lift fährt hoch 3/ List wartet oben 4/ Lift fährt runter 5/ Lift wartet mitten auf der Treppe 6/ Lift stoppt sofort ... Ein Schaltplan ist auch nützlich, in dem steht, wo welche Taster angeschlossen sind und welche PORTPINS zur Steuerung welcher Funktion benutzt werden. Daraus lässt sich ein Zustandsdiagramm (state machine) machen, bei dem exakt festgelegt ist, wie man mit welchen Aktionen von einem Zustand in den anderen kommt. Beispiel: A/ 6/ wenn nicht mindestens zwei Tasten gedrückt B/ Von 1/ nach 2/, wenn Taste PINB0 UND PINB1 gedrückt ... Erst wenn das steht, kann man eigentlich ein sinnvolles und sicheres Programm für alle denkbaren Zustände machen.
Die Ausgangspins sollen auf LOW sein. Wenn eine Bedingung erfüllt ist sollen die entsprechenden Pins auf HIGH geschaltet werden bis die Bedingung nicht mehr erfüllt ist. PB0..3 sollen die Eingänge sein PA0..3 sollen die Ausgänge sein Bed.1: PB0 und PB1 gehen beide auf HIGH => PA0, PA1 und PA3 sollen daraufhin auf HIGH gehen Bed.2: PB0 und PB3 gehen beide auf HIGH => PA0 und PA3 sollen auf HIGH gehen Bed.3: PB2 und PB3 gehen beide auf HIGH => PA0, PA2 und PA3 sollen auf HIGH gehen @Stefan "stefb" B. Kommt diese Aufstellung Deiner Vorstellung näher? MfG
Andyloco wrote: > Wenn eine Bedingung erfüllt ist sollen die entsprechenden Pins auf HIGH > geschaltet werden bis die Bedingung nicht mehr erfüllt ist. > > PB0..3 sollen die Eingänge sein > PA0..3 sollen die Ausgänge sein Formuliere deine Bedingungen in der Programmiersprache im ersten Anlauf in der Langversion > > Bed.1: PB0 und PB1 gehen beide auf HIGH Aha: Also genau dann, wenn PB0 auf High ist UND PB1 auf Hight ist. In C if( ( PINB & ( 1 << PB0 ) ) && ( PINB & ( 1 << PB1 ) ) { } Deine bisherigen Abfragen while (PINB & (1<<PINB0 & 1<<PINB1)) { bzw. while (PINB & (1<<PINB0 | 1<<PINB1)) { sind andere Abfragen. Im ersten Fall kann die Bedingung überhaupt nie erfüllt werden, weil ( 1 << PINB0 & 1 << PINB1 ) immer den Wert 0 ergibt. Im zweiten Fall ist das immer noch eine andere Abfrage, weil es hier bereits reicht, wenn einer der beiden Eingänge entweder PINB0 oder PINB1 oder beide 1 sein können, damit die Bedingung wahr ergibt. -> Formuliere deine Logik zunächst mal einfach und überlege dir welche Verknüpfung (und oder oder) du brauchst. Wenn du dir nicht sicher bist, dann stell dir Tabellen auf, in denen du alle Möglichkeiten der Eingangspins aufschreibst und dann den Ausdruck auswertest > // solange PINB0 und PINB1 == HIGH sollen Das ist die falsche Denkweise. Deine Bedingungen sind grundsätzlich immer von dieser Natur Variable == Wert aber nicht Variable und eine andere Variable == Wert statt dessen muss es lauten: Variable == Wert UND andere Variable == Wert und genau so musst du es auch programmieren.
Habe mein Programm erstmal vereinfacht, weil (so denke ich)in der Bedingung irgendwo ein Fehler steckt. Ich habe eure Verbesserungen ausprobiert aber hat nicht so funktioniert wie ich das gerne hätte. Das Programm reagiert nicht so auf Änderungen der Eingangspins wie ich das vorgesehen habe. Die if-Bedingung soll prüfen ob PINB0 UND PINB1 HIGH sind und dann PORTA0 UND PORTA1 UND PORTA3 auf HIGH schalten ansonsten PORTA auf LOW. Das Ergebnis dieser Programmierung ist allerdings, dass wenn der Taster am Eingang nicht gedrückt ist (es ist nur ein Taster angeschlossen sonst nix; also keine 5V anliegen) die 3 Ausgänge schon auf HIGH sind und sich auch nicht ändern wenn die Eingänge auf HIGH gesetzt werden. Dagegen wenn einer der beiden Eingänge auf Masse gelegt wird dann gehen die Ausgänge auf LOW... Kann ich leider überhaupt nicht nachvollziehen... Ich hoffe einer von euch kann mir da weiterhelfen. Vielen Dank. MfG Andyloco #include <avr/io.h> #include <stdint.h> int main (void) { DDRA = 0xff; // alle Pins von Port A als Ausgang DDRB = 0x00; // alle Pins von Port B als Eingang PORTB = 0xff; // interne Pull-Ups an allen Port-Pins // aktivieren while (1) { if( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB1)) ) PORTA |= (1<<PORTA0) | (1<<PORTA1) | (1<<PORTA3); else PORTA = 0x00; } return 0; }
Andyloco wrote: > Die if-Bedingung soll prüfen ob PINB0 UND PINB1 HIGH sind und dann > PORTA0 UND PORTA1 UND PORTA3 auf HIGH schalten ansonsten PORTA auf LOW. > Das Ergebnis dieser Programmierung ist allerdings, dass wenn der Taster > am Eingang nicht gedrückt ist (es ist nur ein Taster angeschlossen sonst > nix; also keine 5V anliegen) Die Taster schalten also nach Masse. Das heist aber auch: Ist keine Taste gedrückt, dann liegt an diesem Eingang eine 1 an. Wird dies Taste gedrückt, dann liegt an diesem Eingang eine 0 an. die 3 Ausgänge schon auf HIGH sind und sich > auch nicht ändern wenn die Eingänge auf HIGH gesetzt werden. > Dagegen wenn einer der beiden Eingänge auf Masse gelegt wird dann gehen > die Ausgänge auf LOW... > Kann ich leider überhaupt nicht nachvollziehen... Ja. Ist logisch. Das ist genau das erwartete Verhalten, wenn die Tasten nach Masse durchschalten.
1 | > #include <avr/io.h> |
2 | > #include <stdint.h> |
3 | >
|
4 | >
|
5 | > int main (void) |
6 | > { |
7 | >
|
8 | > DDRA = 0xff; // alle Pins von Port A als Ausgang |
9 | > DDRB = 0x00; // alle Pins von Port B als Eingang |
10 | > PORTB = 0xff; // interne Pull-Ups an allen Port-Pins |
11 | > // aktivieren |
12 | >
|
13 | > while (1) |
14 | > { |
15 | > if( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB1)) ) |
16 | |
17 | if( !(PINB & (1<<PINB0)) && !( PINB & (1<<PINB1)) ) |
Jetzt wird der if Teil nur dann genommen, wenn beide Taster geschaltet sind, also beide Eingangspins eine 0 liefern.
Andyloco wrote:
> Kommt diese Aufstellung Deiner Vorstellung näher?
Nicht wirklich. Du bist schon am Dachdecken, aber die Fundamente sind
noch nicht betoniert ;-)
So habs fertig gekriegt so wie es mir vorgestellt habe. Funzt erste Sahne ;) zumindest wenn man davon absieht das ich an den Ausgängen nur 3,3V bzw 2,1V habe... :( Muss wohl noch n bissl an meiner Hardware basteln (ohne angeschlossene Relais waren es 5V). Hatte auch das mit den Widerständen für Active-High-Schaltung mit Taster noch nicht verstanden gehabt... Dachte die internen Pull-Down Widerstände würden reichen. Ich möchte euch noch mal sehr für eure Hilfe danken!!! Ihr habt mir sehr geholfen!!! MfG Andyloco #include <avr/io.h> #include <stdint.h> int main (void) { DDRA = 0xff; /* alle Pins von Port A als Ausgang */ DDRB = 0x00; /* alle Pins von Port B als Eingang */ PORTB = 0x00; /* interne Pull-Ups an allen Port-Pins aktivieren */ while (1) { if( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB1)) ) { PORTA |= (1<<PORTA0) | (1<<PORTA1) | (1<<PORTA3); PORTA &= ~(1<<PORTA2); } if( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB3)) ) { PORTA |= (1<<PORTA0) | (1<<PORTA3); PORTA &= (~(1<<PORTA1) | ~(PORTA2)); } if( (PINB & (1<<PINB2)) && ( PINB & (1<<PINB3)) ) { PORTA |= (1<<PORTA0) | (1<<PORTA2) | (1<<PORTA3); PORTA &= ~(1<<PORTA1); } if( !( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB1)) ) || !( (PINB & (1<<PINB0)) && ( PINB & (1<<PINB3)) ) || !( (PINB & (1<<PINB2)) && ( PINB & (1<<PINB3)) ) ) PORTA = 0; } return 0; }
Andyloco wrote: > So habs fertig gekriegt so wie es mir vorgestellt habe. Funzt erste > Sahne ;) zumindest wenn man davon absieht das ich an den Ausgängen nur > 3,3V bzw 2,1V habe... :( > Muss wohl noch n bissl an meiner Hardware basteln (ohne angeschlossene > Relais waren es 5V). Du wirst doch nicht die Relais direkt an die Pins geschaltet haben? > Hatte auch das mit den Widerständen für Active-High-Schaltung mit Taster > noch nicht verstanden gehabt... Dachte die internen Pull-Down > Widerstände würden reichen. Das sind keine Pull-Downs. Im AVR sind Pull-Ups integriert. Sie sorgen dafür, dass der Eingangspin definiert auf 1 gezogen wird, solange der Taster nicht geschlossen ist. > #include <avr/io.h> > #include <stdint.h> > > > int main (void) > { > > DDRA = 0xff; /* alle Pins von Port A als Ausgang */ > DDRB = 0x00; /* alle Pins von Port B als Eingang */ > PORTB = 0x00; /* interne Pull-Ups an allen Port-Pins aktivieren */ Der Kommentar stimmt nicht. Die Pullups sind hier deaktiviert. Dein resltiches Programm stimmt damit überein, dass du keine Pull-Ups brauchst. Dann brauchst du aber externe Pull-down Widerstände. Ein auf Eingang geschalteter Pin darf niemals einfach nur offen sein! Du fängst dir sonst an diesem Pin jede Menge Störungen ein. Es muss also so aussehen: +--------------o +5V | / / Taster / | | PB0 --------+ | --- | | | | 10k | | --- | GND --------+---------------o GND Und sieh dir an, wie man ein Relais korrekt an einen µC anschliesst. Sonst wird dein Opa nicht lange Freude an deiner Elektronik haben. http://www.mikrocontroller.net/articles/Relais_mit_Logik_ansteuern
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.