Forum: Mikrocontroller und Digitale Elektronik MSP430 - UART sendet Zeichen doppelt


von Steffen (Gast)


Lesenswert?

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

von KoF (Gast)


Lesenswert?

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 :)

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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

von KoF (Gast)


Lesenswert?

magst du mir sagen, wo du appnotes von iar herbekommst?
ich habe gerade diese nicht bei iar gefunden!

von Michael (Gast)


Lesenswert?

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

von KoF (Gast)


Lesenswert?

@ Steffen

hast du eventuell den teiler falsch gesetzt
was für ein quarz hast du und wie hast du den uart initialisiert?

von Steffen (Gast)


Lesenswert?

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

von KoF (Gast)


Lesenswert?

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
}

von Steffen (Gast)


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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

von KoF (Gast)


Lesenswert?

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!

von Steffen (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.