#include <avr/io.h> void main (void) { UCSRB |= (1<<RXEN); //Empfangen aktivieren UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); UBRRH = 00; //Baudrate einstellen 9600 bei 8 MHz UBRRL = 51; while (!(UCSRA & (1<<RXC))); //warten bis senden fertig PORTB = UDR; //schicke ein a über die schnittstelle } Warum leuchten die an PortB angeschlossenen Leuchtdioden nicht bis auf eine auf, wenn ich 0x7F über mein Terminal schicke? Danke!
Wie wär's wenn du die Port-Bits überhaupt erst einmal als Ausgang konfigurierst?
ok danke erstmal. Sorry, die PortBins habe ich bereits als Ausgänge definiert, habe allerdings vergessen diese neuere version hier zu posten ;) Also ich hatte wohl einen denkfehler, denn ich kann ja nicht in das Terminal 0x7F eingeben, da jedes einzeln eingegebene Zeichen: 0 und x und 7 und F jeweils das UDR (welches ja nur 8 Bit hat) belegt. Das heißt, ich kann nur einen wert eingeben. Aber: wie kann ich dann andere werte eingeben (also nicht nur 1 Ziffer)? danke
@ JKK Erzähl' mal etwas mehr... Woher weiss der ???, dass er mit 8 MHz laufen soll bzw. tut er das auch sicher? http://www.mikrocontroller.net/articles/AVR_Checkliste#.C3.9Cbertragungsprobleme_wegen_falschem_Takt.3F Wie ist die physikalische Verbindung zwischen µC und PC, d.h. liegt kommt das Signal TX vom PC irgendwann auf den Eingang RX vom µC? Ist auf dem PC auch 9600 8N1 kein Handshake eingestellt? http://www.mikrocontroller.net/articles/AVR_Checkliste#Sonstige_Fehlerquellen_bei_UART.2FUSART Und ein paar Feinheiten zu deinem Programm...
1 | #include <avr/io.h> |
2 | |
3 | int main (void) // <=== (1) |
4 | {
|
5 | DDRB = 0xFF; // PORTB Ausgang <=== (2) |
6 | |
7 | UCSRB |= (1<<RXEN); //Empfangen aktivieren |
8 | UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); // 8N1 |
9 | UBRRH = 0; //Baudrate einstellen 9600 bei 8 MHz |
10 | UBRRL = 51; |
11 | |
12 | while (1) // <=== (3) |
13 | {
|
14 | while (!(UCSRA & (1<<RXC))); //warten bis senden fertig |
15 | PORTB = UDR; //Zeichen auf PORTB-LEDs anzeigen |
16 | }
|
17 | }
|
(1) siehe C Standard (2) siehe Antwort von Andreas Kaiser und http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Datenrichtung_bestimmen (3) siehe http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Einf.C3.BChrungsbeispiel Punkt (5)
außerdem wenn ich "9" ins terminal ausgebe, leuchten die leds nicht binär 9. Warum?
JKK wrote: > außerdem wenn ich "9" ins terminal ausgebe, leuchten die leds nicht > binär 9. Warum? Weil, wenn du auf deiner Tastatur "9" drückst, der ASCII Code für "9" übertragen wird. Vergiss dass auf deiner Taste eine 9 steht, die eine Zahl darstellt. Das sind einfach nur Buchstaben die übertragen werden. Und für jeden 'Buchstaben' wird sein ASCII Code übertragen. Für den Buchstaben "9" eben der Code 0x39 oder eben binär 00111001 Such dir im Web eine ASCII Tabelle und kontrollier mal mit deinen LED, ob das was du drückst auch angezeigt wird.
Ok, das habe ich mir vorhin auch schon gedacht, dass es mit dem ASCII-Code zutun hat. Aber wie kann ich dann einen String empfangen? Sprich Zeicheneingabe und sobald ENTER gedrückt wird (am Terminal) soll er es auf den Port ausgeben. Danke!
JKK wrote: > Aber wie kann ich dann einen String empfangen? Indem du (zb. in einer Schleife) Zeichen für Zeichen empfängst und jedes empfangene Zeichen zb in einem Array ablegst. > Sprich Zeicheneingabe und > sobald ENTER gedrückt wird (am Terminal) Das ENTER wird genauso übertragen. Ist ein Zeichen wie jedes andere. Aber dein µC Programm erkennt daran, dass der String jetzt komplett übertragen wurde, dass also das Array alle Zeichen enthält. In guter alter C-Manier sollte jetzt im Array noch ein '\0' Character angehängt werden, damit das Ganze auch formal zu einem C-String wird. > soll er es auf den Port > ausgeben. Was soll er auf den Port ausgeben? Einen String kannst du nicht auf einem Port ausgeben. Ein String besteht aus mehreren Zeichen. (OK. Man könnte das Ganze Zeichen für Zeichen ausgeben. Technisch kein Problem, aber trotzdem relativ sinnlos). Was du wahrscheinlich willst: Du übertragst den String "123" und der µC soll das Bitmuster für die Zahl 123 am Port ausgeben. Du musst zwischen den Dingen trennen: Übertragen wird immer ein Text. Den fängst du in einem char-Array auf und hast daher einen String. Deine nächste Frage ist daher: Wie kann ich einen String, der eine Zahl beinhaltet, in die Zahl umwandeln. Und die Antwort: Schau dir mal die Funktion atoi() an. Übrigens würde ich dir empfehlen, anders weiter zu machen: Fang mal damit an, eine Sendefunktion zu schreiben, die dir einen C-String zum PC schicken kann. Diese Funktion benutzt du dann, um zu kontrollieren, ob dein empfangener String korrekt ist. Erst dann, wenn du weist, dass der empfangene String korrekt ist, beschäftigst du dich dann mit der Umsetzung in eine Zahl.
Vielen Dank für den Tipp, aber irgendwie verstehe ich noch nicht so ganz, wie ich nun atoi in mein Programm einbaue. Auch die Beispiele, die man im Netz dazu findet, bringen mich nicht wirklich weiter.
Dann schreib dein Programm doch mal soweit du kommst. Um das atoi() kann man sich kümmern, wenn es soweit ist.
#include <avr/io.h> #include <stdlib.h> int main (void) // <=== (1) { char Input ; int i=0; DDRB = 0xFF; // PORTB Ausgang <=== (2) UCSRB |= (1<<RXEN); //Empfangen aktivieren UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); // 8N1 UBRRH = 0; //Baudrate einstellen 9600 bei 8 MHz UBRRL = 51; while (1) // <=== (3) { while (!(UCSRA & (1<<RXC))); //warten bis senden fertig //Zeichen auf PORTB-LEDs anzeigen Input = UDR; PORTB = atoi(Input); } } die atoi heißt doch "Ascii-to-integer"....Aber ich verstehe den Zusammenhang noch nicht ganz. ich möchte wie ihr oben beschribene habt, bis zum Enter-Eingeben den Zahlenstring (z.b. dez.128) binär auf den PortC ausgeben. Danke!
Ich sagte doch, du benötigst ein char-ARRAY um dort den String zwischenzuspeichern. Wenn du mit String - Verarbeitung in C auf Kriegsfuss stehst, dann solltest du den Ankauf von Literatur in Erwägung ziehen. Das sind absolute C-Grundkenntnisse. Solange du auf dein Buch wartest, kannst du das allernotwendigste auch hier nachlesen: http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | |
4 | int main (void) // <=== (1) |
5 | {
|
6 | char c; |
7 | char Input[200]; |
8 | int i=0; |
9 | DDRB = 0xFF; // PORTB Ausgang <=== (2) |
10 | |
11 | UCSRB |= (1<<RXEN); //Empfangen aktivieren |
12 | UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); // 8N1 |
13 | UBRRH = 0; //Baudrate einstellen 9600 bei 8 MHz |
14 | UBRRL = 51; |
15 | |
16 | while (1) // <=== (3) |
17 | {
|
18 | |
19 | while (!(UCSRA & (1<<RXC))); //warten bis senden fertig |
20 | //Zeichen auf PORTB-LEDs anzeigen
|
21 | c = UDR; |
22 | |
23 | if( c != '\n' ) |
24 | {
|
25 | Input[i] = c; |
26 | i++; |
27 | }
|
28 | |
29 | else
|
30 | {
|
31 | Input[i] = '\0'; |
32 | PORTB = atoi(Input); |
33 | i = 0; |
34 | }
|
35 | }
|
36 | }
|
hmm anscheinend funktioniert das beispiel von k.h.buchegger auch nicht... Habe es nun reingeladen und wenn ich beispielsweise ins Terminal "193" + ENTER eingebe, ändert sich nix an meinen LEDs (die nachwievor alle leuchten) danke
Funktionieren ist, was du definierst. Was machen tut es hoffentlich, oder? Du hast immer noch nicht diese Fragen beantwortet: Woher weiss der ???, dass er mit 8 MHz laufen soll bzw. tut er das auch sicher? http://www.mikrocontroller.net/articles/AVR_Checkl... Wie ist die physikalische Verbindung zwischen µC und PC, d.h. liegt kommt das Signal TX vom PC irgendwann auf den Eingang RX vom µC? Ist auf dem PC auch 9600 8N1 kein Handshake eingestellt? http://www.mikrocontroller.net/articles/AVR_Checkl... Nur wenn beide Fragen positiv beantwortet sind, hat der µC überhaupt eine Chance, das Programm sinnvoll auszuführen. Und selbst dann gilt: "Die Hälfte seines Lebens debuggt der Programmierer vergebens!" Debuggen kann heissen, an strategischen Stellen zusätzliche, markante Aktionen ausführen lassen. Dadurch sieht man, bis wohin sich der µC im Programmcode vorgehangelt hat.
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | |
4 | // 0 Debugging AUS
|
5 | // 1 Debugging AN
|
6 | #define DEBUG 1
|
7 | |
8 | #if DEBUG
|
9 | #ifndef F_CPU
|
10 | /* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
|
11 | (z.B. durch Übergabe als Parameter zum Compiler innerhalb
|
12 | des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
|
13 | "nachträgliche" Definition hinweist */
|
14 | #warning "F_CPU war noch nicht definiert, wird nun mit 8000000 definiert"
|
15 | #define F_CPU 8000000UL /* Quarz mit 8 Mhz */ |
16 | #endif
|
17 | |
18 | // siehe AVR-GCC-Tutorial
|
19 | // Abschnitt Warteschleifen
|
20 | #include <util/delay.h> |
21 | |
22 | // 10*25ms = 250ms warten
|
23 | #define DELAY_250MS() \
|
24 | for (int j = 0; j < 10; j++)
|
25 | delay_ms(25); |
26 | |
27 | #define DELAY_1000MS() \
|
28 | for (int j = 0; j < 40; j++) \
|
29 | delay_ms(25);
|
30 | |
31 | |
32 | static void fehlersuchen(unsigned char x) |
33 | {
|
34 | static unsigned char lx = 0; |
35 | |
36 | switch(x) |
37 | {
|
38 | case 0: |
39 | // Effekt 1
|
40 | // LED Lauflicht, wenn ein '\n' erkannt wurde
|
41 | for(int i = 0; i < 8; i++) |
42 | {
|
43 | PORTB = ~(1 << i); |
44 | // 10*25ms = 250ms warten
|
45 | for (int j = 0; j < 10; j++) |
46 | delay_ms(25); |
47 | }
|
48 | for(int i = 7; i >= 0; i--) |
49 | {
|
50 | PORTB = ~(1 << i); |
51 | for (int j = 0; j < 10; j++) |
52 | delay_ms(25); |
53 | }
|
54 | // 40*25ms = 1000ms warten
|
55 | for (int j = 0; j < 40; j++) |
56 | delay_ms(25); |
57 | break; |
58 | case 255: |
59 | // Effekt 2
|
60 | // Eine LED blinkt, wenn auf ein Zeichen gewartet wird
|
61 | for (int j = 0; j < 10; j++) |
62 | delay_ms(25); |
63 | PORTB ^= 0x80; |
64 | for (int j = 0; j < 10; j++) |
65 | delay_ms(25); |
66 | break; |
67 | default:
|
68 | // Effekt 3
|
69 | // LED zeigt die Zahl der empfangenen Zeichen im Puffer Input an
|
70 | for (int j = 0; j < 10; j++) |
71 | delay_ms(25); |
72 | PORTB = ~x; |
73 | for (int j = 0; j < 10; j++) |
74 | delay_ms(25); |
75 | break; |
76 | }
|
77 | }
|
78 | #else
|
79 | #define fehlersuchen(x)
|
80 | #endif
|
81 | |
82 | int main (void) // <=== (1) |
83 | {
|
84 | char c; |
85 | char Input[200]; |
86 | int i=0; |
87 | DDRB = 0xFF; // PORTB Ausgang <=== (2) |
88 | PORTB = 0xFF; // alle LED aus #1 |
89 | |
90 | UCSRB |= (1<<RXEN); //Empfangen aktivieren |
91 | UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); // 8N1 |
92 | UBRRH = 0; //Baudrate einstellen 9600 bei 8 MHz |
93 | UBRRL = 51; |
94 | |
95 | while (1) // <=== (3) |
96 | {
|
97 | while (!(UCSRA & (1<<RXC))) |
98 | {
|
99 | // warten bis senden fertig
|
100 | fehlersuchen(255); |
101 | }
|
102 | c = UDR; |
103 | |
104 | if( c != '\n' ) |
105 | {
|
106 | Input[i] = c; |
107 | i++; |
108 | fehlersuchen(i); |
109 | }
|
110 | else
|
111 | {
|
112 | fehlersuchen(0); |
113 | Input[i] = '\0'; |
114 | PORTB = ~atoi(Input); // #1 |
115 | i = 0; |
116 | }
|
117 | }
|
118 | }
|
Da hier im Beispiel im Debugmodus einfache Warteschleifen benutzt werden, muss man jetzt zwischen den einzelnen Tastendrücken 1-2 Sekunden warten, damit keine Zeichen verloren gehen. Dafür sieht es lustig aus ;-) #1 > ...ändert sich nix an meinen LEDs (die nachwievor alle leuchten) Deine LEDs scheinen wie auf dem STK500 beschaltet zu sein, d.h. LED an, wenn PORT-Pin LOW ist.
also...ich verwende ein STK500. Einen ATMega8515 und ich habe die Taktfrequenz des Controllers über die Fuses (Internal RC Osc.) auf 8 MHz gesetzt. Kurze Zwischenfrage, zwecks verunsicherung: welchen Unterschied gibt es zwischen "Taktfrequenz durch Fuses setzen" und "Project -> Configuration Options -> frequenzy"? Die LEDs leuchten am STK500 anfangs alle. Dann stelle ich im HyperTerminal ein 9600 baud, usw. Flusssteuerung "keine", und lokales Echo "an". Dann tut sich nix! D.h. die LEDs leuchten genauso wie vorher, nämlich alle. danke
JKK wrote: > also...ich verwende ein STK500. Einen ATMega8515 und ich habe die > Taktfrequenz des Controllers über die Fuses (Internal RC Osc.) auf 8 MHz > gesetzt. Internal RC Osc. ist keine gute Ausgangsvoraussetzung für eine funktionierende UART-Kommunikation zumindest nicht bei 9600 Baud. Näheres kannst du im obigen Link nachlesen und in den Tutorialartikeln über UART und in der Baudratentabelle im Datenblatt (max. Fehler sollte < 2% sein). > Kurze Zwischenfrage, zwecks verunsicherung: welchen Unterschied gibt es > zwischen "Taktfrequenz durch Fuses setzen" und "Project -> Configuration > Options -> frequenzy"? Damit der µC mit einer bestimmten Taktquelle läuft, muss diese Taktquelle körperlich vorhanden sein. Das stellst du durch das Design des Boards (externer Quarz etc.) oder Jumpereinstellungen etc. sicher. Und die Taktquelle muss vom µC angesprochen werden z.B. muss sie definiert zum Schwingen angeregt werden. Das stellst du durch die Fuses sicher. Und letztendlich kann man den Wert mit dem die Taktquelle schwingt an verschiedenen Stellen im Programmcode benötigen. Z.B. um genaue Warteschleifen zu machen. Da man den Wert i.d.R. nicht umständlich messen will sondern ihn normalerweise vom Boarddesign und den Fuses her ganz genau kennt, setzt man den Wert direkt oder indirekt über "Project -> Configuration Options -> frequency" als vorher definiertes Makro F_CPU im Programmcode ein. > Die LEDs leuchten am STK500 anfangs alle. Dann stelle ich im > HyperTerminal ein 9600 baud, usw. Flusssteuerung "keine", und lokales > Echo "an". Mit dem neuen Programmcode sollten die LEDs ziemlich schnell ausgehen und dann wild blinken, während auf Zeichen gewartet wird. > Dann tut sich nix! D.h. die LEDs leuchten genauso wie vorher, nämlich > alle. Das richtige Programm ist übersetzt und in den ATMega8515 geladen und ein RESET hast du auch schon gemacht?
ähm von welchem Programmcode sprechen wir eigentlich? Ich rede von dem von Karl-Heinz Buchegger um 16:34 Uhr.
BlauZahn wrote: > hmm anscheinend funktioniert das beispiel von k.h.buchegger auch > nicht... Das kann gut sein. Ich habe den Code mehr oder weniger blind getippt, also ohne ausprobieren zu können. Genau aus diesem Grund hab ich dir auch weiter vorne einen Stufenplan gegeben, wie man sowas systematisch angeht: * zuerst eine Ausgabefunktion schreiben, die Texte ausgeben kann Vorausssetzungen, die funktionieren muessen: keine für sich alleine testbar: ja * dann die String Empfangsfunktion schreiben, die einen String empfängt und den empfangenen String wieder zurückschickt Voraussetzungen: Die Stringsendefunktion muss funktionieren, aber das wurde ja bereits im vorhergehenden Schritt sicher gestellt * und erst dann eine Zahl umwandeln und am Port ausgeben lassen Voraussetzungen: die Empfangsfunktion muss funktionieren aber das wurdee im vorhergehenden Schritt sicher gestellt Du musst anfangen solche Schritt-für-Schritt Entwicklungen ernst zu nehmen bzw. deine Arbeit selbst in solchen Schritten zu organisieren. Jeder Schritt baut immer auf vorhegehenden, getesteten Schritten auf. Dadurch hast du immer eine Möglichkeit mit kleinen Veränderungen bzw. Ergänzungen von einem funktionierenden Schritt zum nächsten zu kommen. Dadurch weist du aber auch immer, wo der Fehler in etwa zu suchen ist, falls einer auftaucht. Einfach ein Programm runterzuklopfen hat den Nachteil, dass du dann mit einem nicht funktionierenden Programm dastehst und nicht weist wo du zu suchen anfangen sollst. > > Habe es nun reingeladen und wenn ich beispielsweise ins Terminal "193" + > ENTER eingebe, ändert sich nix an meinen LEDs (die nachwievor alle > leuchten) Das kann zb. die Ursache haben, dass dein Terminal beim Druck auf ENTER einen CR/LF oder nur ein LF oder nur ein CR wegschickt. Hängt von der Konfiguration des Terminals ab. Teste doch mal mit deinem ersten Programm (Tastendruck direkt auf die LEDs) welches Zeichen gesendet wird, wenn du auf ENTER drückst.
JKK wrote: > also...ich verwende ein STK500. Einen ATMega8515 und ich habe die > Taktfrequenz des Controllers über die Fuses (Internal RC Osc.) auf 8 MHz > gesetzt. Keine gute Idee > > Die LEDs leuchten am STK500 anfangs alle. Dann stelle ich im > HyperTerminal ein 9600 baud, usw. Flusssteuerung "keine", und lokales > Echo "an". Das lokale Echo schaltest du gleich wieder mal aus. Dafür lässt du jetzt erst mal den µC das Echo machen. Dadurch siehst du nämlich, ob die Übertragung funktioniert. Der µC soll alles was er empfängt direkt wieder zurückschicken ...
1 | #include <avr/io.h> |
2 | |
3 | void main (void) |
4 | {
|
5 | char c; |
6 | |
7 | UCSRB |= (1<<RXEN) | (1<<TXEN); |
8 | UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); |
9 | |
10 | UBRRH = 00; //Baudrate einstellen 9600 bei 8 Mhz |
11 | UBRRL = 51; |
12 | |
13 | while( 1 ) { |
14 | while (!(UCSRA & (1<<RXC))) |
15 | ; //warten bis ein Zeichen ankommt |
16 | |
17 | c = UDR; |
18 | PORTB = c; //emfpangenes Zeichen ausgeben ... |
19 | |
20 | while (!(UCSRA & (1<<UDRE))) //ist die Sendestufe bereit? |
21 | ;
|
22 | UDR = c; //... und wieder zurückschicken |
23 | }
|
24 | }
|
(Kann jemand anderer den Code mal testen. Ich hab hier kein Entwicklungssystem damit ich den Test selbst machen kann).
ok danke! Also dein Code funktioniert bis auf die LEDs. Der Controller scickt also das eingegebene Zeichen sofort wieder zurück. (Habe es mit einem Oszi getestet)
EinSteigÄr wrote:
> ähm....liegt wohl am Fehlenden Data Direction Register ;)
Jep.
Hab nicht drauf geachtet und einfach das erste Pgm im
Thread genommen und umgeändert.
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.