Hallo zusammen, ich versuche gerade eine ATMega32 mit C zu programmieren. Mein Problem ist nun, dass ich vom Hyperterminal einen string an den Controller senden will. Die Eingabe sollte mit der Entertaste beendet werden. Ich habe mir nun folgendes überlegt: unsigned char empfangen() { unsigned char receive; int i=0; while (uart_getc_wait()!=10) { receive[i]=UDR; i++; } receive[i]='\0'; return receive; Diesen String möchte ich dann später wieder auf dem Hyperterminal ausgeben. Dafür habe ich schon eine Funktion geschrieben die mir beim Aufruf senden_string("test"); test auf dem Bildschirm ausgibt. Leider funktioniert die Sache mit dem empfangen nicht richtig. Sieht jemand meinen Fehler, oder kann mir jemand einen Code-Vorschlag schicken´, mit dem ich nicht nur einzelne Zeichen empfangen kann?? Danke schonmal für die Hilfe!
hab so was auch schon mal gemacht:
1 | #ifndef F_CPU
|
2 | #define F_CPU 16000000
|
3 | #endif
|
4 | |
5 | #define BAUD 19200UL //Baudrate
|
6 | #define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
|
7 | |
8 | |
9 | #define length 10 //Textlänge ab welcher Empfangen beendet wird
|
10 | |
11 | |
12 | void uart_init(void) |
13 | {
|
14 | UCSRB = (1<<RXEN)|(1<<TXEN); // UART TX und RX einschalten |
15 | UCSRC |= ( 1 << URSEL )|( 3<<UCSZ0 ); // Asynchron 8N1 |
16 | //nur für 19200 Baud bei 16MHz für Mega32
|
17 | UBRRH = 0; // Highbyte ist 0 |
18 | UBRRL = 51; // Lowbyte ist 51 |
19 | |
20 | //falls anderer Mega bzw andere Frequenz
|
21 | //UBRRH = (uint8_t) (UBRR_BAUD>>8);
|
22 | //UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
|
23 | }
|
24 | |
25 | void uart_putc(unsigned char c) |
26 | {
|
27 | while (!(UCSRA & (1<<UDRE))) {} // warten bis Senden möglich |
28 | UDR = c; // Zeichen senden |
29 | }
|
30 | |
31 | uint8_t uart_getc(void) |
32 | {
|
33 | while (!(UCSRA & (1<<RXC))) {} // warten bis Zeichen verfügbar |
34 | return UDR; // Zeichen aus UDR zurueckgeben |
35 | }
|
36 | |
37 | |
38 | int main (void) |
39 | {
|
40 | uint8_t i; |
41 | char c; |
42 | char* s; |
43 | char string[length+1]; |
44 | |
45 | uart_init(); |
46 | |
47 | while(1) |
48 | {
|
49 | |
50 | s=string; |
51 | i=0; |
52 | |
53 | do
|
54 | {
|
55 | c=uart_getc(); |
56 | if (c!='\r') |
57 | {
|
58 | *s=c; |
59 | uart_putc( c ); |
60 | s++; |
61 | i++; |
62 | }
|
63 | }
|
64 | while( i!=length && c!='\r'); |
65 | *s=0; |
66 | |
67 | uart_puts( "\r\n" ); |
68 | uart_puts( "eingegebender Text: " ); |
69 | uart_puts( string ); |
70 | while (!(UCSRA & (1<<UDRE))) {} |
71 | uart_puts( "\r\n" ); |
72 | |
73 | }
|
74 | return (0); |
75 | }
|
im prinzip empfange ich solange einen char vom PC, bis die maximallänge erreicht ist bzw. bis ein ENTER kommt die einzelnen char werden dann noch in ein string zusammengepack
Das trifft es schon fast! Danke! Nur würde ich gern den Teil vom Empfangen in einer Funktion schreiben. Habs gerade mal probiert, jetzt ergibt sich für mich allerdings das Problem mit der Rückgabe.... Was muss ich nun zurückgeben und wie lautet der Funktionsaufruf dafür dann?
kannst ja mal deine Lösung noch mal posten, damit auch andere davon profitieren können
Kein Problem! Hab noch eine Funktion zum empfangen von Integer Zahlen hinzugefügt. //Empfangen int input_int() { int zahl; char zahl_c[100]; zahl=atoi(input_string()); return zahl; } char input_string() { char string[100]; int i=0; char c; do { c=uart_getc_wait(); if (c!='\r') { string[i]=c; i++; } } while(i!=99 && c!='\r'); string[i]='\0'; return string; } unsigned char uart_getc_wait() { // Warten, bis etwas empfangen wird while (!(UCSRA & (1 << RXC))); // Das empfangene Zeichen zurückliefern return UDR; }
> char input_string() > { > char string[100]; > int i=0; > char c; > do > { > c=uart_getc_wait(); > if (c!='\r') > { > string[i]=c; > i++; > } > } > while(i!=99 && c!='\r'); > string[i]='\0'; > > return string; > } Da fehler erst einmal ein * in der Funktionsdefinition char* input_string() { ... } In input_int braucht wohl niemand das Array zahl_c. Das verbraucht nur Speicherplatz bzw., wenn der Optimizer es rausschmeist, verwirrt nur. Aber, das ist alles Kleinkram. Das folgende aber nicht: Deine input_string() Funktion ist fehlerhaft: Du gibst einen Pointer auf eine lokale Variable zurück. Das darfst du aber nicht. Lokale Variablen werden beim verlassen einer Funktion zerstört. Damit gibst du aber dem Aufrufer der Funktion einen Pointer zurück, der auf Speicher zeigt, der schon längst freigegeben wurde -> auf einem System, dass den Speicher etwas riguroser überwacht, kann es durchaus passieren, dass sich dann das Betriebssystem einschaltet und deinem Programm auf die Finger klopft. Aber auch auf einem AVR ohne Betriebssystem ist das nach wie vor fehlerhaft. In deiner Verwendung in input_int() wird das zwar funktionieren, allerdings nur zufällig. * Wenn atoi ein bischen mehr auf dem Stack allokiert, hast du ein Problem. * Wenn zwischen dem Empfang des Pointers beim Aufrufer und der Verwendung der Daten auf die der Pointer zeigt noch weitere Funktionsaufrufe liegen, die lokale Variablen anlegen, hast du ein Problem. Gib niemals die Adresse einer lokalen Variablen aus einer Funktion zurück! Das ist in C-speak: undefined behaviour. Alles Mögliche kann und wird passieren. Du hast mehrere Möglichkeiten um das Problem zu umgehen: * allokiere den 100-Zeichen Buffer als globale Variable * allokiere den 100 Zeichen Buffer zwar innerhalb der Funktion, dort aber als static Variable * Die Funktion input_string() kümmert sich überhaupt nicht mehr um den Buffer, sondern verlangt vom Aufrufer, dass er einen Buffer (ausreichender Größe) übergibt. * Du allokierst den Buffer dynamisch innerhalb der Funktion (diese Variante ist nur der Vollständigkeit halber aufgeführt, sie ist in C selbst auf einem nicht µC System nur eingeschränkt zu empfehlen. Das Problem ist: Wer gibt den Speicher wieder frei?)
Danke für die Verbesserung! Das Programm lief bis jetzt auch so, aber vielleicht wäre es irgendwann zu Problemen gekommen und ich hätte wieder ewig nach dem Fehler suchen müssen. >In input_int braucht wohl niemand das Array zahl_c. >Das verbraucht nur Speicherplatz bzw., wenn der Optimizer >es rausschmeist, verwirrt nur. Der Array war nur ausversehen noch drin, hatte vorher eine andere Lösung und dafür habe ich ihn gebraucht....
Steffen wrote: > Danke für die Verbesserung! > Das Programm lief bis jetzt auch so, Wie gesagt: Das war ein glücklicher Zufall(*) und funktioniert nur deswegen, weil input_int so aussieht wie es aussieht. Wenn ich zb mache: int foo( char c ) { char tmp[20]; int i; for( i = 0; i < 20; ++i ) tmp[i] = c; return tmp[0] + tmp[9]; } void bar() { char* Input = input_string(); foo( 'a' ); // an dieser Stelle sollte eigentlich bereits der // Inhalt von *Input zerstört sein } dann wird das zu Problemen führen. Die tatsächliche Funktionalität von foo() spielt keine Rolle, die Hauptsache sie legt ein paar lokale Variablen an. Auch wenn das vom C-Standard nirgends gefordert wird, so ist die Wahscheinlich- keit sehr hoch, dass diese Variablen genau in dem Speicher erzeugt werden, der einen Moment vorher noch die bewusste lokale Variable 'string' in input_string() gehalten hat. Und damit zerstört dir jeder Schreibzugriff die Daten, auf die du einen Pointer von input_string() bekommen hast. (*) glücklicher Zufall eigentlich ist das kein glücklicher Zufall, sondern ein sehr schlechter Zufall. Wenn du Glück gehabt hättest, dann wäre das Programm sofort abgestürzt und du hättest mitbekommen, dass es da ein Problem gibt. So hast du Pech und alles schaut so aus, als ob es in Ordnung wäre.
Auch wenn der Post schon was älter ist, ich bin grade an etwas ählichem: Ich wollte dazu einfach die Funktion aus dem Manual benutzen: while(!(UCSRA&(1<<RXC))); return UDR; Was mir dabei nicht so ganz klar ist: Was genau macht "return UDR"? Wenn ich das, was ich empfange jetzt zb auf den LEDs (meintewegen Port B) anzeigen lassen will, wie komme ich dann an die Daten ran? "PORTB=UDR"?
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.