Hallo! Ich verstehe nicht, wieso ich Müll rauskriege, wenn ich eine Funktion habe: int sendstring(char *s) { unsigned char c = 0; while(s[c] != 0) if( USR & 0x20 ) UDR = s[c++]; return(0); } int main(void) { sendString("Hallo, Du da!\n\r\0"); return(0); } ich auf dem Terminal nur Müll angezeigt bekomme (sendstring abgerollt in Main geht aber wunderbar!). Im AVR-GCC-Tutorial habe ich einen Hinweis auf die Harvard-Architektur gefunden, werde aber daraus nicht schlau. Die Zeichenkette ist ja statisch und wird vom Compiler WO hingepackt? Muß ich sendString einen Flag "Konstante/Programmspeicher" übergeben, daß er den Pointer auf den richtigen Speicher anwendet? Saluti! Ludwig
Du ratterst ganz ganz schnell durch den String durch, stellst fast, dass das UART data register not empty ist, und gehst zum nächsten Zeichen über. Du willst wohl stattdessen lieber für jedes Zeichen einzeln warten, bis das UDR empty ist, und dann weitermachen. Deine Interruptvariante ist natürlich besser. Übrigens braucht diesen den Test auf UDRE selbst gar nicht: wenn der Interrupt triggert, ist garantiert, dass dieses Bit gesetzt ist.
Hallo! Das Problem ist, daß wenn ich strcpy "per Hand" durchführe: int sendString(char *c) { unsigned int count = 0; while( c[count] ) { obuf[count] = c[count]; count++; } BufCount = 0; UDR = obuf[BufCount++]; return(0); ich nicht das ausgegeben bekomme, was ich durch sendString("Hallo, Du da!\n\r\0"); übergeben hatte. BTW, BufCount ist eine globale unsigned char für die Position im Puffer, und mit Änderung von UDR starte ich die Übertragung (der Rest wird per Interrupt gemacht). Das ist zwar nicht ganz elegant, um die Eleganz will ich mich in einem zweiten Augenblick kümmern. Saluti! Ludwig
Das kann viele Ursachen haben. Mach doch mal ein komplettes, vollständiges Programm fertig. Um die Hardvard-Architektur brauchst du dich nicht kümmern, solange du mit dem verfügbaren RAM auskommst und nichts optimieren musst.
Hallo! Karl Heinz, wie kann ich ein vollständiges Programm fertig machen, wenn die einzelne Funktion nicht funktioniert? Auch ohne Optimierung ("-Os" ist rauskommentiert) kriege ich nur Datensalat. Im Assemblerfile sehe ich, daß die Konstante "Hallo, Du da!\n\r\0" mit der Direktive ".string" definiert wird - leider habe ich keine Dokumentation über die einzelnen Direktiven gefunden. Was macht ".string"? SalutI! Ludwig
Karl Heinz meint, dass du den kompletten Quellcode (das C-Listing) posten sollst. Und das ist eine gute Idee. Dadurch kann man oft erst sehen, wo und wie welche Variablen angelegt werden, ob es Initialisierungsprobleme gibt, ob sinnvolle Includefiles eingebunden werden etc.. Gelegentlich findet sich bei komplettem Quellcode sogar ein Helfer, der das Programm auf seinem Rechnersystem prüft... Bei grösseren Projekten kann es notwendig sein, den Quellcode auf den reproduzierbaren Fehlerfall zu kürzen. Gelegentlich kann es sogar angebracht sein, das Makefile oder weitere Daten bekanntzugeben.
> Karl Heinz, wie kann ich ein vollständiges Programm fertig machen, > wenn die einzelne Funktion nicht funktioniert? Indem du exakt das Program postest, das du auch durch den Compiler schickst. Und zwar vollständig. Oftmals ist es so, dass wir nur beim Durchlesen von Code-Schnipseln auch Dinge übersehen, bzw. das der eigentliche Fehler genau in dem Code steckt, den du nicht postest. Indem du ein komplettes Program postest, ermöglichst du uns, dass wir deinen Fehlerfall (so gut es geht) bei uns nachstellen können. Wir können das selbst mal durch den Compiler jagen und nachsehen was da schief läuft. Du bringst ja auch nicht nur die Hutablage deines Autos zum Mechaniker wenn dort was klappert.
Zum Code wäre es gut, wenn Du den CPU-Typ sowie die F_CPU auch noch angibst! Gruss Peter
Das sieht soweit eigentlich ganz gut aus. Da werden wir wohl in den Simulator muessen. Welchen AVR benutzt du?
Okey, F_CPU ist 3.6864 MHz (steht im Code) und als CPU verwendest Du offenbar den AT90S3213... Im Prinzip funktioniert Dein Program, mal abgesehen davon, dass Du den Buffer-Inhalt [Das klappt!] mit [Hallo Du da!!] überschtreibst, nachdem nur die ersten zwei Zeichen vom ersten String raus sind...! Die Strings landen so wie's Du machst im RAM, wenn Du sie im Flash haben möchtest müsstest Du... #include <avr/pgmspace.h> //includen char MyString[] = PROGMEM "Hello World!\n\r" //String im Flash // oder direkt als Parameter mit dem PSTR() Macro sendString_P(PSTR("Ich komm aus dem Flash!\n\r")); // im FLASH //--------------------------------------------------------- // Für Strings im FLASH braucht es eigene Funktionen // für den Datenzugriff z.B. int sendString_P(PGM_P str) //--------------------------------------------------------- int sendString_P(PGM_P str) //--------------------------------------------------- // send a ProgMem string to UART0 Transmit-buffer //--------------------------------------------------- { char c=pgm_read_byte(str); // get first char from ProgMem while (c) // while not string-end { UART_putc(c); // copy char to TX-Buffer (wait if full) c=pgm_read_byte(++str); // get next char from ProgMem } } Mehr dazu steht in der avr_libc Dokumentation! Gruss Peter
Hallo! Also, ich benutze einen AT90S2313 in einem STK500 Testboard, der standardmässig 3.6864MHz liefert. Als Umgebung nutze ich den "vi" mit dem "avr-gcc", "make" und "uisp". Zu meiner Schande muß ich zugeben, mich nie mit dem GNU-Debugger beschäftigt zu haben. Saluti! Ludwig
@Ludwig:
Kleine Anmerkung:
>> sendString("Hallo, Du da!\n\r\0");
Das "\0" am Ende kannst Du weglassen - stört zwar nicht, erzeugt der
Compiler aber automatisch beim Ablegen eines Strings; also:
sendString("Hallo, Du da!\n\r");
Gruß, Günter
Also so wie ich das sehe ist dein eigentliches Problem eigentlich nur dasjenige, dass du nicht wartest, bis das vorherige Zeichen erfolgreich gesendet wurde. Es ist eigentlich ja ziemlich logisch, dass der UART beim Tempo der CPU nicht mithalten kann. Am einfachsten wartest du nach der Ausgabe jedes einzelnen Zeichens, bis das Senderegister wieder leer ist. Ansonsten müsstest du echt interruptgesteuert senden mit einem entsprechenden Sendepuffer dazwischen. Wenn du keine absolute High Performance Application haben willst scheint mir dieser Weg allerdings zu umständlich.
Moment mal. Das ganze senden läuft interruptgesteuert ab. Das heist: Wenn SendString zurückkommt, dann ist der String noch lange nicht gesendet. Er ist grade mal im Buffer und der Interrupt gibt das ganze aus. Das heist aber auch: Lass den BuffCount danach in Ruhe. Auch weiss ich nicht was alles passiert, wenn du in der while Schleife ständig auf das USR Register zugreifst. Das andere: Die ISR muss sich selbst nach dem letzten Zeichen den Interrupt abdrehen. Den wenn das letzte Zeichen gesendet wurde und du nichts mehr ins UDR stellst, tritt der Interrupt sofort wieder auf, das USART-Ausgangsregister ist ja zur Benutzung frei. Aber all das passt nicht zu deiner Fehlerbeschreibung: Anstatt dem Text kommt eine Menge Unsinn über die USART. Es sei denn du hast den eigentlichen Text übersehen und richtest dein Augenmerk auf den Unsinn der irgendwo im Speicher steht und auch ausgegeben wird, weil die ISR auf Biegen und Brechen immer weiter ausgibt weil der Interrupt immer wieder kommt.
Denkfehler meinerseits. Die ISR wird zwar noch aufgerufen, macht aber nichts mehr, da die Funktion am Ende des Strings angelangt ist. Damit kann ich dir auch nicht erklären warum das nicht funktioniert. Sollte meiner Ansicht nach eigentlich klappen. Das 'volatile' sollte in diesem Fall auch kein Problem sein.
Ich habe weiter oben beschrieben warum es nicht klappt: >Im Prinzip funktioniert Dein Program, mal abgesehen davon, >dass Du den Buffer-Inhalt [Das klappt!] mit [Hallo Du da!!] >überschtreibst, nachdem nur die ersten zwei Zeichen vom ersten >String raus sind...! Könnt ihr nicht lesen...???
Hallo! Peter, das sollte wohl NICHT das Problem sein, denn wenn der Bufferinhalt überschrieben wird, sollte ja doch was drin stehen und übertragen werden! Ich kriege im Minicom lauter komische Zeichen, abgezählt soviele wie eigentlich im Puffer sich befinden. Ich werde das mit dem "volatile" versuchen und bescheidgeben. Könnte einige Tage dauern. Saluti! Ludwig
> Das 'volatile' sollte in diesem Fall auch kein Problem sein.
Warum nicht?
Dieser Code (vom Poster):
1 | char obuf[BUFLEN + 1]; |
2 | char ibuf[BUFLEN + 1]; |
3 | unsigned int BufCount = 0; |
4 | |
5 | |
6 | ISR(UART_UDRE_vect) |
7 | {
|
8 | PORTB = 0xaa; |
9 | if( obuf[BufCount] != 0 ) |
10 | UDR = obuf[BufCount++]; |
11 | }
|
12 | |
13 | int sendString(char *c) |
14 | {
|
15 | unsigned int count = 0; |
16 | while( c[count] ) |
17 | {
|
18 | obuf[count] = c[count]; |
19 | count++; |
20 | }
|
21 | |
22 | BufCount = 0; |
23 | UDR = obuf[BufCount++]; |
24 | return(0); |
25 | }
|
Weder obuf noch BufCount läuft Gefahr 'gleichzeitig' in der ISR und woanders gelesen oder geschrieben zu werden. BufCount hätte Potential dazu, da hier ja in SendString noch was fehlt: Die Abfrage ob ein vorher gesendeter String noch im Buffer steckt oder schon raus ist. Dazu würde man wahrscheinlich den BufCount nehmen und solange warten bis der wieder 0 ist (und dann ist volatile eine extrem gute Idee). Aber im Moment sollte das noch kein Problem sein.
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.