Hallo Leute, ich hoffe, dass mir einer bei meinem Problem behilflich sein kann. Und zwar versende ich bei einem Ereignis mehrere SMS über einen Atmega32. Hierbei treten jedoch regelmäßig Fehler auf, so dass mehrer SMS nicht gesendet werden. Um diese Fehler zu behandeln, möchte ich den Ergebniscode den mir das Modem schickt gerne auslesen und darauf dementsprechend reagieren. (So dass die SMS evt. nochmal gesendet wird) Dies wollte ich mit folgenden Methoden realisieren: /* Zeichen empfangen */ uint8_t uart_getc(void) { while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar ; return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben } void uart_gets( char* Buffer, uint8_t MaxLen ) { uint8_t NextChar; uint8_t StringLen = 0; NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen // Sammle solange Zeichen, bis: // * entweder das String Ende Zeichen kam // * oder das aufnehmende Array voll ist while( NextChar != '\n' && StringLen < MaxLen - 1 ) { *Buffer++ = NextChar; StringLen++; NextChar = uart_getc(); } // Noch ein '\0' anhängen um einen Standard // C-String daraus zu machen *Buffer = '\0'; } Wenn ich zum testen Daten über das Hyperterminal sende, werden diese durch die obenstehenden Methoden richtig erfasst. Die eigentliche Aufgabe, den Ergebniscode des Modems abzufangen, wird jedoch nicht erfüllt...dies funktioniert nicht. Er hängt sich bei: NextChar = uart_getc(); Obwohl ja Daten vom Modem gesendet werden...!? Wie gesagt über's Hyperterminal funktionierts. Würde mich über jede Hilfe freuen! Vielen Dank im Vorraus Gruß Thomas
Hängt es bereits im ersten uart_getc()? Dann könnte z.B. die Hardware nicht stimmen (TXD vom Modem über Pegelwandler an RXD vom AVR?) oder die im Codefetzen nicht sichtbare UART-Initialsierung ist falsch. Beides schliesse ich aus, weil du schreibst, dass die Übertragung AVR-Hyperterminal funktioniert. Hängt es in einem der uart_getc() in der while-Schleife? Bist du sicher, dass ein Zeilenende kommt und wenn dass dann ein '\n' (LF, Unix-Style) am Zeilenende steht und nicht ein '\r' (CR, Mac-Style) oder ein '\r' und ein '\n' (CRLF, PC-Style)? Wie verhält sich das Modem an Hyperterminal (besser wäre z.B. Br@y-Terminal o.ä. bei denen man die Einzelzeichen hexadezimal anzeigen kann).
ja...das die Hardware nicht stimmt kann man ausschließen. mit Hyperterminal geht ja alles. Das ist ja gerade das Merkwürdige. ich habe mich ja auch im Hyerterminal und mit einem RS232 Sniffer davon überzeugt, dass eine Antwort zurückkommt...und welche Datenpakete gesendet werden. Ja es hängt so wie es aussieht schon bei der ersten Abfrage. Ich habe es auch schon mit "while( StringLen < MaxLen - 1 )" statt "while( NextChar != '\n' && StringLen < MaxLen - 1 )" probiert... dass hat aber auch nicht funktioniert.?
Thomas wrote: > Ja es hängt so wie es aussieht schon bei der ersten Abfrage. Wenn du Position ### 1 meinst (s.u.), dann verstehe ich nicht was das folgende bringen soll: > Ich habe es auch schon mit > while( StringLen < MaxLen - 1 ) > statt > while( NextChar != '\n' && StringLen < MaxLen - 1 ) > probiert... dass hat aber auch nicht funktioniert.?
1 | void uart_gets( char* Buffer, uint8_t MaxLen ) |
2 | {
|
3 | uint8_t NextChar; |
4 | uint8_t StringLen = 0; |
5 | |
6 | // Warte auf und empfange das ERSTE Zeichen
|
7 | NextChar = uart_getc(); // ### 1 |
8 | |
9 | // Sammle solange Zeichen, bis:
|
10 | // * entweder das String Ende Zeichen kam
|
11 | // * oder das aufnehmende Array voll ist
|
12 | |
13 | while( NextChar != '\n' && StringLen < MaxLen - 1 ) |
14 | {
|
15 | *Buffer++ = NextChar; |
16 | StringLen++; |
17 | NextChar = uart_getc(); // ### 2 |
18 | }
|
19 | |
20 | // Noch ein '\0' anhängen um einen Standard
|
21 | // C-String daraus zu machen
|
22 | *Buffer = '\0'; |
23 | }
|
Bei dem Code läuft du in einen Hänger, wenn nie ein '\n' kommt und wenn nie mehr oder gleichviel Zeichen wie MaxLen-1 gesendet werden. Durch Weglassen der Prüfung auf '\n' verschlimmerst du die Situation. Den CR-Fall könntest du so abfangen: while( NextChar != '\r' && NextChar != '\n' && StringLen < MaxLen - 1 ) Es ist auch wichtig, wie der Rest des Programmes konstruiert ist. Wenn das Modem im Normalfall keine Statusmeldungen schickt, würde eine ständige Prüfung auf Statusmeldungen mit uart_gets() immer zur Blockade führen. Dieses uart_gets ist ja wegen uart_getc an Pos. ### 1 und wegen dem while inkl. ### 2 grundsätzlich blockierend. Man könnte das ändern, indem man z.B. die Daten nebenläufig zum Userprogramm in einem RX-Interrupt empfängt, einen Puffer füllt und im Programm je nach Füllgrad des Puffers darauf reagiert. Wenn es ohne Interrupt gehen soll, könnte vor dem Aufruf der uart_getc prüfen, ob in der UART Daten vorliegen und dann - und nur dann - dorthin verzweigen.
1 | void uart_gets( char* Buffer, uint8_t MaxLen ) |
2 | {
|
3 | uint8_t NextChar; |
4 | uint8_t StringLen = 0; |
5 | |
6 | // Wenn ein Zeichen in der UART vorhanden ist,
|
7 | // dann empfange das als ERSTES Zeichen einer
|
8 | // Statusmeldung
|
9 | |
10 | if ((UCSRA & (1<<RXC))) |
11 | {
|
12 | NextChar = uart_getc(); // ### 1 |
13 | |
14 | // Sammle solange Zeichen, bis:
|
15 | // * entweder das String Ende Zeichen kam
|
16 | // * oder das aufnehmende Array voll ist
|
17 | while( NextChar != '\n' && StringLen < MaxLen - 1 ) |
18 | {
|
19 | *Buffer++ = NextChar; |
20 | StringLen++; |
21 | |
22 | // Mit der Annahme, dass dann noch
|
23 | // mehr Zeichen kommen, darauf warten...
|
24 | NextChar = uart_getc(); // ### 2 |
25 | }
|
26 | }
|
27 | |
28 | // Noch ein '\0' anhängen um einen Standard
|
29 | // C-String daraus zu machen
|
30 | *Buffer = '\0'; |
31 | }
|
ADD: In dem letzten Vorschlag würde ich aber den Namen der Funktion ändern, weil der normale µC-Programmierer davon ausgeht, dass uart_gets auf Gedeih und Verderb auf einen String wartet. Damit dass eine so benannte Funktion ohne String (bzw. einem Leerstring) zurückkommt, rechnet er eigentlich nie oder selten ;-)
OK vielen Dank für die Vorschläge. Bin noch relativ neu in diesem Gebiet. Ich werde es nun mal mit einem Empfangs-Interuppt versuchen und einen Puffer vollschreiben...den ich in der Hauptroutine auslesen falls das entspechende Flag gesetzt ist. Wobei es mir immer noch unverständlich ist, wieso er mit dem bisherigen Code nichts auslesen konnte (also jedenfalls nicht die Daten vom Modem).
Ich habe das Problem nun wie oben beschrieben gelöst. Jetzt habe ich ein anderes Problem.... muss nun zum Abschluss noch die ca. 30 Nummern in ein Array etc. hinterlegen. Weiß aber nicht genau in welcher Datenstrucktur. kann mir einer einen Vorschlag machen? mit: char Number[30]; Nummer[0] = "+49...."; geht es ja nicht !???
char Nummer[30]; // <--- meine ich natürlich Nummer[0] = "+49...."; geht es ja nicht !???
Thomas wrote: > char Nummer[30]; // <--- meine ich natürlich > Nummer[0] = "+49...."; geht es ja nicht !??? Beginner
1 | char *Nummer[30] = { |
2 | "+49...", |
3 | "+49...", |
4 | "+49...", |
5 | "+49...", |
6 | // usw.
|
7 | "+49..."
|
8 | };
|
Vergleiche im Programm mit strcmp() Intermediate http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash Expert http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Array_aus_Zeichenketten_im_Flash-Speicher
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.