Hallo zusammen, ich nutze die AVR STK500-Versuchsplatiene. Hier reagieren die Ein- und Ausgangs-Ports reziprok zu den tatsächlichen Ansteuerungen, durch Pull-Up am Eingang und Transistor-Stufe am Ausgang. Ich finde das in der Praxis (als Anfänger) sehr verwirrend! Kann man das STK500 umstellen? Muss ich eine externe "Controller-Leiterplatte" für den 10-pol Eingangs- und 10-pol Ausgangsport bauen, um einfacher und somit Fehlerfreier arbeiten zu können? Ich freue mich über Stimmen aus der Praxis!
__Son´s Bersi__ schrieb: > Hier reagieren die Ein- und Ausgangs-Ports reziprok zu den tatsächlichen > Ansteuerungen, durch Pull-Up am Eingang und Transistor-Stufe am Ausgang. Gewöhn' dich dran, das ist gängige Praxis. Erstens haben die Eingangspins auch eingebaute Pullups, weshalb man externe Taster gern nach Masse verschaltet. Zweitens gab und gibt es viele Mikrocontroller, deren "unterer" (n-Kanal-)Transistor in der Ausgangsstufe deutlich stromergiebiger ist als der "obere" (p-Kanal). Das ist physikalisch bedingt, ein p-Kanal-Transistor gleicher Stromergiebigkeit ist deutlich größer als der vergleichbare n-Kanal-Typ. (Außerdem gab's dann noch die 8051, die gleich mal ausschließlich n-Kanal-Transistoren hatten und Pullups für die "obere Hälfte".) > Kann man das STK500 umstellen? Nein. > Muss ich eine externe "Controller-Leiterplatte" für den 10-pol Eingangs- > und 10-pol Ausgangsport bauen, um einfacher und somit Fehlerfreier > arbeiten zu können? Nein, musst du nicht. Du musst dich lediglich dran gewöhnen, dass man in der Ausgabe eine Negation (~ in C) voranstellt und in der Eingabe auf "low" abfragt. Software ist da anpassungsfähig. ;-)
Jörg Wunsch schrieb: > Du musst dich lediglich dran gewöhnen Ich arbeite ausschließlich mit ATmega und ATtiny, Programmiere in C und baue gerne sehr kleine Schaltungen ohne Pull-Up auf. Daher muss ich nach der Prüfung mit dem STK500, in der Programmierung die PORTs dauernd umstellen. Bsp: zum Test via STK500> PORTA=0b11110000 danach auf PORTA0b00001111 umstellen. Hier sind irgend wann Fehler "vorprogrammiert"!
Das kann man so machen
1 | // z.B. in main.h
|
2 | |
3 | #define STK500
|
4 | |
5 | // im Programm z.B. main.c
|
6 | |
7 | #ifdef STK500
|
8 | PORTA = 0b11110000; |
9 | #else
|
10 | PORTA = 0b00001111; |
11 | #endif
|
__Son´s Bersi__ schrieb: > Ich arbeite ausschließlich mit ATmega und ATtiny, Programmiere in C > und baue gerne sehr kleine Schaltungen ohne Pull-Up auf. Dann schließt du externe Pull-down-Widerstände an die Eingänge, um die Taster auf Vcc legen zu können? Was für eine Verschwendung ... > Daher muss ich nach der Prüfung mit dem STK500, in der Programmierung > die PORTs dauernd umstellen. Kann man mit einem #ifdef machen. > Bsp: zum Test via STK500> PORTA=0b11110000 danach auf PORTA0b00001111 > umstellen. Dafür gibt's den Operator ~. Versteckt man in einem Makro. Ist gewissermaßen der Anfang zu einem HAL (hardware abstraction layer). Man könnte natürlich auch die eigenen Schaltungen so bauen, dass die Ausgänge low-aktiv sind ... Auch bei AVRs gibt es durchaus Exemplare mit unterschiedlichen Stromergiebigkeiten zwischen p- und n-Kanal- Treibern.
__Son´s Bersi__ schrieb: > Jörg Wunsch schrieb: >> Du musst dich lediglich dran gewöhnen > > Ich arbeite ausschließlich mit ATmega und ATtiny, Programmiere in C > und baue gerne sehr kleine Schaltungen ohne Pull-Up auf. Das ist doch dann erst recht ein Grund, die im AVR verbauten Pullup-Widerstände zu benutzen! Noch kleiner als eine im IC eingebaute Komponente zu benutzen geht ja gar nicht mehr. Auf die Art können Taster direkt an den µC-Pin angeschlossen werden, OHNE dass es zu einer Fehlfunktion wegen offenem Pin bei nicht gedrücktem Taster kommt. Und der Preis dafür, dass sich die Programmlogik dadurch scheinbar umdreht ... nach deinem 5-ten Programm merkst du das gar nicht mehr. > Daher muss ich nach der Prüfung mit dem STK500, in der Programmierung > die PORTs dauernd umstellen. Aber geh. Da macht man sich ein paar Makros und die Sache ist gegessen. Kommt dann auch der Programmqualität zu gute.
Jörg Wunsch schrieb: > (Außerdem gab's dann noch die 8051, die gleich mal ausschließlich > n-Kanal-Transistoren hatten und Pullups für die "obere Hälfte".) Fast richtig. Port 0 hat einen echten "Gegentakt" Ausgang, die anderen Ports schalten für 2 Taktperioden einen niederohmigen Pull-Up ein und haben dann stationär einen hochohmigen (einige Kiloohm) Pull-Up.
DANKE, für die zahlreichen Tips! Mal sehen ob ich mich im laufe der Zeit daran gewöhnen kann. ZZ. ist es noch ein dauerndes umständliches Umdenken.
__Son´s Bersi__ schrieb: > DANKE, für die zahlreichen Tips! > > Mal sehen ob ich mich im laufe der Zeit daran gewöhnen kann. ZZ. ist es > noch ein dauerndes umständliches Umdenken.
1 | #define LED_ON(Port,Pin) (Port) |= (1<<(Pin))
|
2 | #define LED_OFF(Port,Pin) (Port) &= ~(1<<(Pin))
|
3 | |
4 | #define SWITCH_PRESSED(Port,Pin) !((Port) & (1<<Pin))
|
5 | |
6 | |
7 | #define LED_PORT PORTB
|
8 | #define LED_DDR DDRB
|
9 | #define ERROR_LED PB2
|
10 | #define READY_LED PB5
|
11 | |
12 | #define SWITCH_PORT PORTB
|
13 | #define SWITCH_PIN PINB
|
14 | #define SWITCH_DDR DDRB
|
15 | #define UP_SWITCH PB4
|
16 | #define DOWN_SWITCH PB0
|
17 | |
18 | |
19 | int main() |
20 | {
|
21 | // Die Ports für die LED auf Ausgang schalten
|
22 | LED_DDR |= (1<<ERROR_LED) | (1<<READY_LED); |
23 | |
24 | // Die Ports für die Taster auf Eingang schalten und Pullup ein
|
25 | SWITCH_DDR &= ~((1<<UP_SWITCH) | (1<<DOWN_SWITCH)); |
26 | SWITCH_PORT |= (1<<UP_SWITCH) | (1<<DOWN_SWITCH); |
27 | |
28 | LED_ON( LED_PORT, READY_LED ); |
29 | LED_OFF( LED_PORT, ERROR_LED ); |
30 | |
31 | while( 1 ) { |
32 | |
33 | if( SWITCH_PRESSED( SWITCH_PIN, UP_SWITCH ) ) { |
34 | LED_ON( LED_PORT, READY_LED ); |
35 | LED_OFF( LED_PORT, ERROR_LED ); |
36 | }
|
37 | |
38 | if( SWITCH_PRESSED( SWITCH_PIN, DOWN_SWITCH ) ) { |
39 | LED_OFF( LED_PORT, READY_LED ); |
40 | LED_ON( LED_PORT, ERROR_LED ); |
41 | }
|
42 | }
|
43 | }
|
Sieh dir mal den wichtigsten Teil des Programmes an - die Hauptschleife in main(). Das liest sich fast wie ein kompletter englischer Satz! Da brauch ich nichts überlegen und mir um 0 oder 1 Bits den Kopf zu zerbrechen. Wenn da steht LED_OFF, dann ist das eindeutig: die LED wird ausgeschaltet. Welche LED? Auch das steht dort: ERROR_LED - die LED die dem Benutzer eine Fehlersituation anzeigt. Was da drann ist jetzt umständlich? Ja, die Makros muss man sich erst mal zurecht legen und das muss man mal machen. Aber wenn es gemacht ist, dann wird der eigentlich wichtige Teil, nämlich die Programmierung in der Hauptschleife zu einem Kinderspiel. Da ist dann nichts mehr umständlich oder schwer zu verstehen. Wenn da steht SWITCH_PRESSED dann ist das eindeutig! Wenn "die Taste gedrückt ist". Steht doch genau so an der relevanten Stelle im Quelltext. Was muss ich da groß überlegen, was hier wohl passieren bzw. abgefragt werden könnte und ob das bedeutet, dass die Taste gelöst oder gedrückt ist? Und ich hätte noch weiter gehen können und das ganze noch einfacher zu lesen (und zu SCHREIBEN, das sollte man nicht unterschätzen!) machen können, indem ich noch mehr Details aus dem Blickfeld der Hauptschleife 'rausoperiere'. Und das beste am ganzen: Wenn ich beim Platinenfertigen drauf komme, dass es layouttechnisch doch besser wäre, denn die beiden Taster nebeneinander am Port angeschlossen werden, dann ändere ich einfach ...
1 | #define UP_SWITCH PB4
|
... um in ...
1 | #define UP_SWITCH PB1
|
... und um die Verteilung dieser Änderung an die relevanten Stellen im Code kümmert sich der Compiler/Präprozessor. C gibt dir alles in die Hand, damit du deine Programme einfach lesbar machen kannst. Du musst es nur benutzen! Und das wiederrum liegt in deiner Hand. Mach nicht die Programmiersprache oder die Hardware dafür verantwortlich, dass du von den Möglichkeiten deiner Programmiersprache nur 20% kennst und benutzt, weil du sie nie richtig gelernt hast.
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.