Hallo ... ich habe ein Problem mit einem MSP430F449. Ich habe den UART in Betrieb genommen und alles funktioniert soweit auch super. Nun habe ich die Baudrate auf 115200 erhöht. Nun werden die Zeichen doppelt gesendet. Ein UART0sendString("OKAY"); liefert nun OOKKAAYY ... Die sendChar-Routine habe sieht folgendermassen aus: void UART0sendChar( UINT8 character ) { while (!(IFG1 & UTXIFG0)); // wait till TX0-buffer is ready TXBUF0 = character; } Funktioniert diese Routine bei Euch richtig ? ICh weiss nicht, wo ich noch suchen soll. Vielleicht hat jemand von Euch eine Idee dazu. Danke Steffen
probiere doch mal die codes aus dem wiki! dort habe ich angefangen universal verwendbare codes zu posten MSP430 Codebeispiele ps wenn du schönen code hast, füge ihn doch ein :)
Hmm...zu dem Problem kann ich dir wenig helfen, allerdings gibt es eine wie ich finde sehr interessante application Note von IAR zu diesem Thema, so baue ich meine UART Routinen immer auf. Gruß Michael
Hallo ... erstmal danke für die Antworten. @KoF Diese Senderoutine ist aus den Beispielen hier. Die Routine läuft ja bis 57600 Baud richtig und stabil. Leider tritt bei 115200 dieses Problem auf. @Michael Danke für den Link. Den Ringspeicher im Eingang hatte ich auch ähnlich gemacht. Ich werde das mit dem Transmit-Interrupt versuchen, das hat allerdings gestern Abend nicht mehr richtig geklappt. Grüße Steffen
magst du mir sagen, wo du appnotes von iar herbekommst? ich habe gerade diese nicht bei iar gefunden!
Wenn du die IAR Embedded Workbench installierst (auch Demoversion), in dem Ordner und dann IAR Systems\Embedded Workbench 4.0\430\doc\appnotes Gruß Michael
@ Steffen hast du eventuell den teiler falsch gesetzt was für ein quarz hast du und wie hast du den uart initialisiert?
Also ich habe ein Olimex-HeaderBoard für den MSP430F449. Darauf ist an XT1 ein 32kHz und an XT2 ein 8MHz Quarz. Ich habe die Clocks jetzt so gesetzt, das MCLK aus XT1 und SMCLK aus XT2 läuft. Der UART wird von der SMCLK versorgt. Wie gesagt bis 57600 läuft es auch sehr gut. Ich denke, das es etwas damit zu tun hat, das nicht gewartet wird, bis das zeichen wirklich gesendet ist. Ich habe daher versucht gestern Abend den Transmit Interrupt zu verwenden und dmait ein Flag zu setzen, ob der Transmit abgeschlossen ist. Das hat aber leider nicht so auf Anhieb funktioniert. Im Datenblatt steht, das der Transmit-Buffer neu beschrieben werden muss, damit der anstehende Interrupt gelöscht wird. Das macht in meinen Augen aber keinen Sinn - was soll ich machen, wenn keine Zeichen mehr zu senden sind ? Die UART-Initialisierung habe ich gerade nicht hier, aber die Werte habe ich mit dem MSPGCC-Baudraten-Calculator berechnet. Er kommt da auf einen Wert von 115107 Baud (oder so ähnlich) - bin nicht zu Hause. Ich glaube am schönsten wäre es mit einem Transmit-FIFO, wie ich den auch für den Receive habe. Allerdings muss dafür der Transmit-Interrupt funktionieren - und ich muss nochmal im Datenblatt schauen, wie der Interrupt zurückgesetzt wird. Für Hilfe und Anregungen bin ich aber offen :-) Grüße Steffen
dann solltest du es wirklich mal so versuchen, wie in der appnote von iar die Michael gepostet hat. dort werden auch buffer verwendet! >Im Datenblatt steht, das der Transmit-Buffer neu beschrieben werden >muss, damit der anstehende Interrupt gelöscht wird. Das macht in meinen >Augen aber keinen Sinn - was soll ich machen, wenn keine Zeichen mehr zu >senden sind ? machst du das etwa? die register neu beschreiben? while (!(IFG1 & UTXIFG0)) >> diese anweisung macht doch genau das, was du willst! "warte, bis uart sendebereit!" erst dann sollte man den txbuffer füllen.
1 | void SendUSART0c(char c) |
2 | {
|
3 | while (!(IFG1 & UTXIFG0)); |
4 | TXBUF0 = c; |
5 | }
|
Hallo ... nein ... ich beschreibe die Register natürlich nicht neu. Aber das while (!(IFG1 & UTXIFG0)) wartet ja offensichtlich nicht, bis wieder sendebereit, da sonst die Zeichen ja nicht doppelt ankämen - oder sehe ich das falsch. Vielleicht sollte ich mal in den Errata-Sheets gucken, ob da was vermerkt ist. Grüße Steffen
Hallo ... ich habe mal in dem Errata-Sheet von diesem Prozessor nachgesehen. Da steht auch etwa zum UART: US13 US13 - Bug description: Module: USART0, USART1, Function: Unpredictable program execution USART interrupts requested by URXS can result in unpredictable program execution if this request is not served within two bit times of the received data. Workaround: Ensure that the interrupt service routine is entered within two bit times of the received data. Hat jemand eine Ahnung wie man das sicherstellen soll ? Grüße Steffen
hmm... also es macht genau das, was es soll! bevor das zeichen in tx übertragen wird überprüft es, ob nicht eventuell noch eine übertragung läuft. poste mal deinen code!
Hallo KoF hier die notwendigen Schnipsel aus meinem Code ... also die Initialisierung der Clock-Sources: FLL_CTL1 &= ~XT2OFF; // XT2 einschalten (8MHz) do { FLL_CTL0 &= ~XT2OF; // clear XT2 osc fault flag for (i = 0; i < 1000; i++); // warten } while(FLL_CTL0 & XT2OF); FLL_CTL1 |= SELM_A; // MCLK = XT1 FLL_CTL1 |= SELS; // SMCLK = XT2 FLL_CTL1 &= ~SMCLKOFF; // SMCLK einschalten - die Initialisierung des Quarzes: UTCTL0 = SSEL1; // UCLK = SMCLK UBR00 = UBR0_DEF; // aus XT2 UBR10 = UBR1_DEF; // eingestellte Baudrate UMCTL0 = UMCTL_DEF; // erzeugen UCTL0 = CHAR; // 8-bit character SWRST ME1 |= UTXE0 + URXE0; // UART0 TX/RX einschalten IE1 |= URXIE0; // UART0 Receive-Interrupt einschalten //IE1 |= UTXIE0; // UART0 Transmit-Interrupt einschalten P2SEL |= 0x30; // P2.4,5 = USART0 TXD/RXD P2DIR |= 0x10; // P2.4 output direction - der Sendeaufruf: UART0sendString ( "ANGEKOMMEN !" ); - die SendString-Funktion: void UART0sendString ( UINT8* string ) { UINT8 zaehler = 0; while ( string[zaehler] != 0 ) { UART0sendChar( string[zaehler] ); zaehler++; } } und zu guter letzt die SendChar-Funktion: void UART0sendChar( UINT8 character ) { while (!(IFG1 & UTXIFG0)); // wait till TX0-buffer is ready TXBUF0 = character; UART0transmitInProgress = true; } Die Ausgabe am Hyperterminal ist dann: AANNGGEEKKOOMMMMEENN !! Any ideas ? Grüße Steffen
Ich glaube nicht, das es mit deinem Problem etwas zu tun hat, aber: void UART0sendString ( UINT8* string ) { UINT8 zaehler = 0; while ( string[zaehler] != 0 ) { UART0sendChar( string[zaehler] ); zaehler++; } } Du deklarierst String hioer als Pointer, verwendest es aber als Array. Müsste es nicht *(string + zaehler) heißen?!? Gruß Michael
Hallo ... also ich habe gerade versucht ob die Änderungen von Michael etwas bringt. Siehe da ... es ging. Allerdings habe ich dann zum Vergleich die alte Schreibweise eingefügt und es ging auch. Ich weiss nciht woher der Fehler kam. Vielleicht lag es an der PC-Schnittstelle. Ich hatte den PC während des Testens nicht neu gestartet. Ich glaube das Hyperterminal ist auch nicht das ideale Testprogramm. Hat jemand ein andere gute Alternative ? Allerdings bin ich mir nicht sicher, warum das vorher dann nicht funktioniert hat. Aber es sollte doch ein Zugriff auf Adresse_von_String[zaehler] das gleiche sein wie *(Adresse_von_String+zaehler) ... oder sehe ich da was falsch ? Grüße und danke für Eure Hilfe Steffen
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.