Hallo, ich glaube ich habe ein kleines c-Problem. Ich versuche einen String über USART1 vom Mega128 auszugeben. Ich habe zwei Prozeduren. Eine, um Zeichen zu senden, eine Andere um Strings zu senden. Kurz gesagt: Die Prozedur usart1_sendByte() funktioniert, usart1_sendString() funktioniert nicht. Ich erhalte im Hyperterminal nur Leerzeichen. Kann mir jemand einen Tip geben woran das liegen könnte? Ich rufe die Prozeduren im hauptprogramm so auf: usart1_sendByte('X'); <--- funktioniert usart1_sendString("Willkommen"); <--- funktioniert nicht Hier die beiden Prozeduren: void usart1_sendByte(unsigned char data){ //Warte bis Transmit Buffer leer ist while ( !( UCSR1A & (1<<UDRE1) ) ); //Data in den Buffer schreiben (startet die Übertragung) UDR1 = data; } void usart1_sendString(unsigned char* data){ //Alle zeichen nacheinander ausgeben while (*data++){ //Warte bis Transmit Buffer leer ist while ( !( UCSR1A & (1<<UDRE1) ) ); //Data in den Buffer schreiben (startet die Übertragung) UDR1 = *data; } }
Hallo Klaus, ich hasse Konstruktionen wie while (*data++){ weil ich mir die Reihenfolge der Abarbeitung einfach nicht merken kann. teste doch mal while (*data) { //Warte bis Transmit Buffer leer ist while ( !( UCSR1A & (1<<UDRE1) ) ); //Data in den Buffer schreiben (startet die Übertragung) UDR1 = *data; data++; } Wenn das läuft, kanst Du immer noch den vermeindlich kürzeren Code testen. Oryx
Hallo Oryx, ich habe das schon längst getestet, auch die Variante mit Zähler und data[i]... Aber ich habe es eben nochmal getestet. Ich habe deinen Vorschlag genommen und im Hauptprogramm folgendes geschrieben: usart1_sendByte('K'); usart1_sendString("Willkommen"); usart1_sendByte('D'); Ich benutze UARTMonitor, um zu sehen was am PC ankommt: 4b ff ff ff ff ff ff ff ff ff ff ff ff 44 (K und D kommen fehlerfrei an!) mich wundert es warum ich 12 Mal "ff" erhalte.... Wenn ich anstatt UDR1 = *data einfach mal UDR1='X' schreibe, dann erhalte ich 12 Mal "X". Das heisst prinziepiell funktioniert es, aber eventuell ist was mit "data" nicht in Ordnung. Vielleicht steht das "Willkommen" nicht im Speicher? Für weitere Hinweise und Tips wäre ich dankbar. Gruß, Klaus
Jetzt wirds peinlich :-) Ich habe den Fehler gefunden. nachdem ich im vorherigen Posting geschrieben habe, daß "Willkommen" evtl. nicht im Speicher steht, habe ich mal mein Makefile untersucht: $(OBJCOPY) -j .text -j .datam -O ihex $(PRG) $(PRG)_flash.hex Da stand ".datam" anstatt ".data". Daran hat es gelegen und jetzt geht es auch wie es soll. Man, man. Wenn das so weiter geht, darf ich mich hier gar nicht mehr hertrauen ;-) Danke nochmal für die Hilfe. Gruß, Klaus
Nun, Dein erster Code hat einen kleinen Schönheitsfehler: while (*data++) { ... = *data; } Du inkrementierst den Pointer zu früh. Du willst eher while (*data) { ... = *data++; } schreiben oder auch while ((c = *data++)) { ... = c; } Für Dein 0xff-Problem: ich tippe darauf, daß Du Deinen m128 irgendwie über das COFF-File und AVR-Studio programmierst, ja? Don't do this. Nimm lieber avrdude dafür. Details zum Problem findest Du im README zum Betatest meines avr-coff-patches, unter ``known issues'', ziemlich am Ende: http://www.sax.de/~joerg/README.coff-avr-patch
Haben sich unsere Postings gekreuzt. Klar, Du hast damit ungewollt das Verhalten von AVR Studio simuliert. ;-) Genau dasselbe passiert nämlich dort auch (die Initialisierungswerte von .data werden nicht in den ROM geladen).
Hallo Joerg, auch dir danke für deine Antwort. Du hattest Recht. Das while(*data++) war falsch. Dadurch wurde das erste Zeichen weggelassen, aber dieser Fehler war schnell behoben :-) Zum programmieren benutze ich übrigens schon avrdude. Nur, um die fuses zu setzen habe ich stk500.exe benutzt (bei avrdude kann man die nicht in der Kommandozeile übergeben, wenn ich das richtig verstanden habe)... So, jetzt muß ich nur noch herausfinden warum Umlaute nicht richtig übertragen werden, dann habe ich es geschafft. Any ideas? (8 Bit-Modus ist an: UCSR1C = (3<<UCSZ10); ) Gruß, Klaus
Hallo an alle Ebenfalls eine elegante Lösung wäre: for ( ;*data; data++) { while ( !( UCSR1A & (1<<UDRE1) ) ); UDR1 = *data; } wobei ich persönlich direkte Zuweisungen an die Register scheusslich finde und selber auch vermeide. Gruss Christian
Bei avrdude kann man die Fusebits derzeit nur als Hex in der Kommandozeile übergeben. Symbolische Fusebits habe ich mir gedanklich mal vorgenommen, wenn ich mal vieeel Zeit habe. ;-) (Vielleicht macht's ja jemand anders vor mir.) Wie kommen Deine Umlaute denn an? Gleicher Zeichensatz auf beiden Seiten? Was ist, wenn Du sie im C-Programm mal in hex codierst, '\xdf' wäre beispielsweise ein ß.
Hi Joerg, danke für deine Antwort. kannst du mal an einem Beispiel zeigen, wie man die Fuses und Lockbits per Kommandozeile übergibt? Die Anleitung von Avrdude ist was das betrifft ziemlich lückenhaft. ich habe da nur ein Beispiel gefunden, wie man das im Terminalmodus macht. Ich habe mal einen Test wegen den Umlauten gemacht: 1. usart1_sendByte(129); -> kommt korrekt als ü an 2. usart1_sendByte('ü'); -> kommt als 0xfc an 3. usart1_sendByte('\129'); -> kommt als 0x39 an Wieso kommen 2+3 falsch an? Als Empfänger benutze ich Hyperterminal. habe schon Ansi, VT100 etc. eingestellt...kein Erfolg. Gruß, Klaus
Aus der man page von avrdude: -f format This option specifies the file format for the input or out- put files to be processed. Format can be one of: ... m immediate; actual byte values specified on the command line, seperated by commas or spaces. This is good for programming fuse bytes without having to create a sin- gle-byte file or enter terminal mode. D. h. sowas wie avrdude ... -f m -m lf -i 0x23 Eine Alternative ist avrdude ... -m lf -I 0x23 (-I ist die Vereinigung von -i ... mit -f m) Deine Umlautprobleme sind nur Verständnisprobleme und Mismatch zwischen Zeichensätzen. ;-) Zeichen 129 mag ein ü in der steinalten IBM Codepage 437 sein, aber die nimmt praktisch keiner mehr. Auch Windows ist seit langem zu ISO 8859-1 (dort ,,ANSI'' genannt) gewechselt und danach zu Unicode (für 16-bit Zeichensätze). Dort ist ein ü halt ein \xfc. \129 ist oktal 129, also völlig korrekt \x39. Wahrscheinlich mußt Du Dir was anderes als das blöde Hyperterminal leisten. Keine Ahnung, hab' kein Windows. Unter Unix nehme ich cu als ,,Terminal-Emulator'', das muß aber nicht wirklich ein Terminal emulieren, sondern es bedient lediglich die seriöse Schnittstelle -- es läuft ja schon selbst in einem Terminal. In diesem sind dann folglich die Zeichensätze, die ich beim Editieren nehme und die zum Anzeigen der Daten die gleichen.
Hallo Joerg, danke für deine Antwort. Das mit den Umlauten ist mir aber noch nicht ganz klar. Wenn ich vom Mega128 aus folgendes an meinen Pc sende usart1_sendByte(129); dann kommt das korrekt als ü an. Wieso kommt das korrekt an? Wieso sehe ich im Hyperterminal unter Windows und auch unter anderen Programmen, wie zb UARTMonitor etc. das es ein "ü" ist (obwohl es ne Steinalte IBM Codepage 437 ist)? Wenn ich aber vom Mega128 aus das versende: usart1_sendByte('ü'); Dann empfange ich auf dem Windows Rechner 0xfc. Hyperterminal zeigt mir das aber nicht als "ü" an, sondern als ^3 (hochgestellte drei), obwohl das jetzt "Windows-kompatibel" sein soll? Für mich ist hier eindeutig der avr-gcc "schuld", weil er aus 'ü' nicht eine 129 (dezimal) macht, sondern 0xfc. Langer rede kurzer Sinn. Wie kann ich dem avr-gcc beibringen, daß er Strings wie "Menü" auch korrekt verschickt? Kann ich die verwendete Codepage irgendwo ändern? Habe nur ich dieses Umlaut-Problem? ;-) Andere arbeiten doch auch unter Windows und dem Hyperterminal. Gruß, Klaus
Offenbar benutzt Hyperterminal die CP437, der Rest von Windows aber (insbesondere der Editor, mit dem Du das Zeichen in das C-Programm eingibst) ISO 8859-1. Dein Hyperterminal findet das dann abartig, wenn das Zeichen gesendet wird. Der avr-gcc baut exakt das in den Code ein, was Du ihm eingibst, und der AVR gibt genau das über die UART aus. Wenn Du in der Eingabe (Editor) und Ausgabe (Hyperterminal) beides unterschiedlich interpretierst, ist das ganz offenbar Deine Schuld. ;-)
Ich dachte mir schon, daß ich irgendwie Schuld daran habe ;-) Najut, dann muß ich mal kucken, wie ich dieses Problem löse (evtl. mit ein paar #defines für die Umlaute...) Nette Seite: http://www.gymel.com/charsets/ Vielleicht finde ich ja im Netz einen "Codepage converter" :-) Danke für deine Hilfe! Gruß, Klaus
Der Codepage-Konverter heißt `recode' (GNU recode). Ah ja, Eingabe von "gnu recode" bei Gugel bringt ihn sofort als ersten Treffer... % echo 'äöüÄÖÜß' | recode latin1..ibm437 | hd 00000000 84 94 81 8e 99 9a e1 0d 0a |......á..| 00000009
Achso, damit weißt Du natürlich nicht die ISO 8859-1 Werte: % echo 'äöüÄÖÜß' | hd 00000000 e4 f6 fc c4 d6 dc df 0a |äöüÄÖÜß.| 00000008 Jetzt hast Du beides. Wie Du siehst, impliziert recode bei Angabe von ibm437 auch, daß dort \r\n als Zeilentrenner benutzt wird.
Nochmal vielen Dank für deine Antowrt. Hab "recode" und "hd" sogar für meinen Windows-Rechner gefunden! Gruß, Klaus
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.