Habe folgendes Problem: Benutze STK500 mit Atmega16 Das Senden vom yC und Empfangen am PC funktioniert. Doch leider nicht richtig. Wenn ich die Taste am Stk500 drücke wird der Test für den Zustand gesendet und beim loslassen der zweite Text. Gewollt war, dass wenn Lampe an bzw. aus ist, der Zustand zum Pc gesendet wird. #include <stdlib.h> #include <avr/io.h> #define WARTEPIN PIND #define WARTEBIT PD0 void uart_init() { UCSRB |= (1<<TXEN); // UART TX einschalten UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1 #define F_CPU 8000000 /* Oszillator-Frequenz in Hz */ // Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt) #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1) #define UART_BAUD_RATE 9600 UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 ); UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ); } int main(void) { unsigned char taste0_vorher = 0; DDRB = 0xff; // PORTB alle AUSGANG PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH) DDRD = 0x00; // EINGANG while (1) { if ( (WARTEPIN & (1<<PD7)) ) { // Schalter PD0 jetzt offen if (taste0_vorher == 1) { // Schalter PD0 vorher geschlossen => LED umschalten (toggeln) PORTB ^= (1<<PB7); sprintf(text,"Licht an"); uart_puts(text); // neuen jetzt Zustand merken taste0_vorher = 0; } } else { // Schalter PD0 geschlossen if (taste0_vorher == 0) { // Schalter PD0 vorher offen => LED umschalten (toggeln) PORTB ^= (0<<PB7); sprintf(text,"Licht aus"); uart_puts(text); // neuen jetzt Zustand merken taste0_vorher = 1; } }//Taste 0 PD 0 Ende } uart_init() return 0; // never reached }
Schlecht formatierter Text. Und uart_init wird gar nicht ausgeführt. Warum du trotzdem was siehst, ist mir nicht klar. MW
Jürgen Dell wrote: > Habe folgendes Problem: > Benutze STK500 mit Atmega16 > Das Senden vom yC und Empfangen am PC funktioniert. Doch leider nicht > richtig. Soweit ich das sehen kann, funktioniert das tadellos. > Wenn ich die Taste am Stk500 drücke wird der Test für den > Zustand gesendet und beim loslassen der zweite Text. Jep. Genauso ist das auch programmiert. Also funktioniert das Senden über den UART komplett richtig. > Gewollt war, dass > wenn Lampe an bzw. aus ist, der Zustand zum Pc gesendet wird. dazu solltest du erst mal definieren, wann denn die Lampe ein bzw. ausgeschaltet werden soll. So wie es jetzt programmiert ist, passiert bei Drücken der Taste etwas und beim Loslassen der Taste auch und ich glaube das ist nicht das Verhalten, das du haben wolltest. Ich denke du wolltest haben, dass jedesmal beim Drücken der Taste der Zustand der Lampe umgeschaltet werden soll. Falls dem so ist, dann stell erst mal deine Programmformatierung, im Speziellen die Einrückungen, richtig. Dann siehst du relativ schnell, wo du dich vertan hast. Das ist allerdings nur die halbe Miete, denn du hast das Problem der prellenden Taster komplett ignoriert. Wenn du frische, neue Taster hast, mag es auch so gehen. Wenn du ältere Taster hast, die bereits prellen, dann werden die dich mit so einer Progrmmierung in den Wahnsinn treiben. PS: Beim nächsten mal poste bitte Code, der auch tatsächlich compiliert.
Kannst du mir da bischen Hilfestellung geben. Beschäftige mich erst seit paar Tagen mit dieser Materie.
Entprellen: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29 oder noch besser: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Habe es mit hilfe von Tutorial vesucht, bekomme es aber nicht hin wie ich es möchte. Passiert immer das was ich nicht wollte. Mir fällt das Programmmieren nicht einfach.
Kann ein Erfahrener meinen Code überfliegen und mir Ratschläge geben was man besser machen sollte.Das mit Formatierung muss ich mich noch angewöhnen. Der Code ist compiliert und zeigt keine Fehler. Auf Dem Stk500 verrichtet es die Arbeit, die ich mir vorgestellt hatte. #include <stdlib.h> #include <avr/io.h> #define WARTEBIT PD0 unsigned char text[10]; unsigned char taste0_vorher; // hier uart_init, uart_putc, uart_puts (s.o.) int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } UDR = c; /* sende Zeichen */ return 0; } void uart_puts (char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_putc(*s); s++; } } void uart_init() { UCSRB |= (1<<TXEN); // UART TX einschalten UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1 #define F_CPU 8000000 /* Oszillator-Frequenz in Hz */ // Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt) #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1) #define UART_BAUD_RATE 9600 UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 ); UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ); } int main(void) { DDRB = 0xff; // PORTB alle AUSGANG PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH) DDRD = 0x00; /* alle Pins von Port D als Eingang */ PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */ while (1) { if ( PIND & (1<<PD7)) { // Schalter PD0 jetzt offen if (taste0_vorher == 1) { // Schalter PD0 vorher geschlossen => LED umschalten (toggeln) PORTB ^= (1<<PB7); // neuen jetzt Zustand merken taste0_vorher = 0; //Wenn Lampe an ist->Zustand senden if( !(PINB & (1<<PINB7)) ) { uart_init(); uart_puts("Licht an"); } } } if ( !(PIND & (1<<PD7))) { // Schalter PD0 geschlossen if (taste0_vorher == 0) { // Schalter PD0 vorher offen => LED umschalten (toggeln) PORTB ^= (0<<PB7); // neuen jetzt Zustand merken taste0_vorher = 1; if( !(PINB & (1<<PINB7))) { uart_init(); uart_puts("Licht aus"); } } }//Taste 0 PD 0 Ende } return 0; // never reached }
Des weiteren muss die Initialisierung der UART nur ein mal durchgeführt werden, nämlich vor while(1). MW
> int main(void) > { > > DDRB = 0xff; // PORTB alle AUSGANG > PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH) > DDRD = 0x00; /* alle Pins von Port D als Eingang */ > PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */ > > while (1) > { > if ( PIND & (1<<PD7)) > { > // Schalter PD0 jetzt offen > if (taste0_vorher == 1) > { > // Schalter PD0 vorher geschlossen => LED umschalten > (toggeln) > PORTB ^= (1<<PB7); > // neuen jetzt Zustand merken > taste0_vorher = 0; > > //Wenn Lampe an ist->Zustand senden > if( !(PINB & (1<<PINB7)) ) > { > uart_init(); > uart_puts("Licht an"); > } > } > } > > if ( !(PIND & (1<<PD7))) > { > // Schalter PD0 geschlossen > if (taste0_vorher == 0) > { > // Schalter PD0 vorher offen => LED umschalten (toggeln) > PORTB ^= (0<<PB7); > // neuen jetzt Zustand merken > taste0_vorher = 1; > > if( !(PINB & (1<<PINB7))) > { > uart_init(); > uart_puts("Licht aus"); > } > } > }//Taste 0 PD 0 Ende > } > return 0; // never reached > } Vergleich mal diese beiden Ausschnitte, die in den beiden grossen ifs vorkommen: > if( !(PINB & (1<<PINB7)) ) > { > uart_init(); > uart_puts("Licht an"); > } und > if( !(PINB & (1<<PINB7))) > { > uart_init(); > uart_puts("Licht aus"); > } in beiden Fällen ist die Abfrage dieselbe. Etas soll passieren, wenn PINB7 am PortB 0 ist. Nur: In dem einen Fall behauptest du, dass die Lampe an ist und im anderen Fall behauptest du, dass sie aus ist. Das kann doch so nicht stimmen! Des Rätsels Lösung liegt darin, dass du zur Feststellung des Zustands das PIN Register benutzt. Das ist Unsinn. Das PIN Register wird nur dann benutzt, wenn du einen externen Zustand an einem µC Pin einlesen willst. Den Fall hast du aber nicht. Das Port Register ist auf Ausgang geschaltet und du willst einfach nur feststellen, welchen Zustand denn der Ausgangspin hat. In dem Fall benutzt du genauso das PORT Register um festzustellen was Sache ist. Der PIN Register kommt nur dann zum Einsatz, wenn der entsprechende Port-Pin auch tatsächlich auf Eingang geschaltet ist. (*) Das uart_init macht man nur ein einziges mal. Merken: Dinge werden nur einmal initialisiert. Da stellt man ein was eine Komonpente machen soll und lässt diese Konfiguration in Ruhe (es sei denn man möchte umkonfigurieren, aber das willst du ja nicht). Daher wird das uart_init rausgezogen und ganz am Programmanfang gemacht. Dies ist im übrigen kein Kavaliersdelikt sondern hat einen handfesten Grund. Wenn die UART noch mit Senden beschäftigt ist und du initialisierst sie neu, was denkst du wird dann passieren? Also: Beide Abfragen und die nachfolgende Ausgabe eines Textes können zusammengezogen werden: if( !(PORTB & (1<<PB7)) ) uart_puts("Licht an"); else uart_puts("Licht aus"); und da diese Abfrage und Ausgabe in beiden grossen if-Zweigen immer dieselbe ist, kann man die auch dort herausziehen. Das nächste ist, dass du im zweiten Fall versuchst, die LED zu toggeln mit > PORTB ^= (0<<PB7); das wird nichts. Egal wie oft man eine 0 nach links schiebt, sie bleibt trotzdem eine 0. D.h. da oben steht PORTB ^= 0; das ändert aber am Portzustand nichts. Code der nichts bewirkt kann und sollte auch wegfallen. Er verwirrt nur.
1 | int main(void) |
2 | {
|
3 | DDRB = 0xff; // PORTB alle AUSGANG |
4 | PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH) |
5 | DDRD = 0x00; /* alle Pins von Port D als Eingang */ |
6 | PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */ |
7 | |
8 | uart_init(); |
9 | |
10 | while (1) |
11 | {
|
12 | if( PIND & (1<<PD7) ) |
13 | {
|
14 | // Schalter PD0 jetzt offen
|
15 | if( taste0_vorher == 1 ) |
16 | {
|
17 | // Schalter PD0 vorher geschlossen => LED umschalten (toggeln)
|
18 | PORTB ^= (1<<PB7); |
19 | // neuen jetzt Zustand merken
|
20 | taste0_vorher = 0; |
21 | }
|
22 | }
|
23 | |
24 | else
|
25 | {
|
26 | taste0_vorher = 1; |
27 | }
|
28 | |
29 | if( !(PORTB & (1<<PB7)) ) |
30 | uart_puts("Licht an"); |
31 | else
|
32 | uart_puts("Licht aus"); |
33 | }
|
34 | |
35 | return 0; // never reached |
36 | }
|
Damit ist der Code aber schon um einiges kürzer und damit auch leichter zu durchschauen. Deine nächste Aufgabe: Mach dich über Entprellen schlau und hol dir aus dem angegebenen Artikel den entsprechenden Code. Den dann einbauen. (*) es gibt da bei neueren Prozessoren eine Ausnahme bei der man das PIN Register tatsächlich auch dann benutzt, wenn der Port auf Ausgang geschaltet ist. Aber das würde jetzt zu weit führen.
Danke für die Hilfe. Habe es versucht mit dem entprellen, funktioniert auch wohl, bloss es gibt bis jetzt noch ein anderes problem.
1 | while (1) |
2 | {
|
3 | if( PIND & (1<<PD7) ) |
4 | {
|
5 | // Schalter PD0 jetzt offen
|
6 | if( taste0_vorher == 1 ) |
7 | {
|
8 | // Schalter PD0 vorher geschlossen => LED umschalten (toggeln)
|
9 | PORTB ^= (1<<PB7); |
10 | // neuen jetzt Zustand merken
|
11 | taste0_vorher = 0; |
12 | }
|
13 | }
|
14 | |
15 | else
|
16 | {
|
17 | taste0_vorher = 1; |
18 | }
|
19 | |
20 | if( !(PORTB & (1<<PB7)) ) |
21 | uart_puts("Licht an"); |
22 | else
|
23 | uart_puts("Licht aus"); |
24 | }
|
25 | |
26 | return 0; // never reached |
27 | }
|
Das ding ist die ganze Zeit am senden und blicke grad nicht durch woran es liegt. Mit meinem überlangen und falsche Programmierweise hat es aber funktioniert was ich wollte. Für später: Wie stelle ich an das der yC erst senden soll wenn 2 Tasten(ungleichmässig gedrückt) oder mehrer Tasten gedrückt werden, nen Text zum PC sendet?
Jürgen Dell wrote: > Danke für die Hilfe. Habe es versucht mit dem entprellen, funktioniert > auch wohl, bloss es gibt bis jetzt noch ein anderes problem. > >
1 | > while (1) |
2 | > { |
3 | > if( PIND & (1<<PD7) ) |
4 | > { |
5 | > // Schalter PD0 jetzt offen |
6 | > if( taste0_vorher == 1 ) |
7 | > { |
8 | > // Schalter PD0 vorher geschlossen => LED umschalten (toggeln) |
9 | > PORTB ^= (1<<PB7); |
10 | > // neuen jetzt Zustand merken |
11 | > taste0_vorher = 0; |
12 | > } |
13 | > } |
14 | >
|
15 | > else |
16 | > { |
17 | > taste0_vorher = 1; |
18 | > } |
19 | >
|
20 | > if( !(PORTB & (1<<PB7)) ) |
21 | > uart_puts("Licht an"); |
22 | > else |
23 | > uart_puts("Licht aus"); |
24 | > } |
25 | >
|
26 | > return 0; // never reached |
27 | > } |
28 | >
|
> > Das ding ist die ganze Zeit am senden und blicke grad nicht durch woran > es liegt. Ach du wolltest, dass der Text nur gesendet wird, wenn ein Tastendruck festgestellt wird? Sorry. Das hab ich nicht mitgekriegt. Na ja, dann musst du das auch so programieren. Nur dann, wenn eine Taste gedrückt wurde, wird der Text gesendet. Wo wird festgestellt, dass eine Taste gedrückt wurde? Na hier, denn genau dan dieser Stelle schaltest du ja auch die LED um: > if( PIND & (1<<PD7) ) > { > // Schalter PD0 jetzt offen > if( taste0_vorher == 1 ) > { Also wird wohl die Ausgabe da hineinwandern müssen. > Für später: Wie stelle ich an das der yC erst senden soll wenn 2 > Tasten(ungleichmässig gedrückt) oder mehrer Tasten gedrückt werden, nen > Text zum PC sendet? Du hältst in einer Variablen fest welche Tasten gedrückt sind. Und wenn dann diese Variable einen bestimmten Wert (der den gewünschten gedrückten Tasten entspricht) dann löst du deine Aktion aus. Aber: Das alles geht sehr viel einfacher mit den Entprellroutinen aus den weiter oben angegebenen Verlinkungen. Die führen auch darüber Buch, ob und wenn ja welche Taste gedrückt ist. Ob sie lang oder kurz gedrückt wurde. Und die Auswertung ist sehr viel simpler.
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.