mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 Usart - Baudratenproblem


Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe ein Problem mit dem Senden von Daten.

Ich möchte Daten durchgehend über uart an ein Funkmodul senden, welches 
die Daten dann verschicken soll. Die Baudrate habe ich auf 115200 
eingestellt; am Controller und Funkmodul natürlich. Ich werte ein CTS 
Signal vom Funkmodul aus. Wenn dessen Buffer weniger als 17 Byte frei 
hat, geht das Signal auf HIGH , wenn mehr als 34Byte frei sind, geht es 
auf LOW. Ich sende dann nur, wenn das Signal LOW ist. Allerdings hängt 
sich das Funkmodul scheinbar immer auf, weil der Buffer überläuft, wobei 
ich das doch mit der CTS-Abfrage eigentlich verhindern will.

Mich würd nun interessieren, ob jemand eine Idee hätte, woran das liegen 
könnte.

Wenn ich die Daten in nicht so schneller Folge sende, funktioniert es 
komischerweise wunderbar.

Der CTS-Port des Funkmoduls toggelt auch immer, schön zu sehen am Oszi.

Ich habe hier einmal Stücke aus meinem Code. Ich hoffe, das da das 
wichtigste dabei ist.

Mit der folgenden Funktion sende ich die Daten:
void SendUSART0(char* str)       // Einen String über die serielle Schnittstelle 
{                                // (USART0) senden
  while (*str != 0)
  {
    // Warten, bis USART0 TX-buffer sendebereit
    while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 0));   
    TXBUF0 = *str++;
  }
}/* void SendUSART0(char* str) */
Die Funktion wird in der main() in einer endlosschleife einfach immer 
wieder aufgerufen. Ich sende da immer einfach 0xFF.

Das Folgende ist die Initialisierung der Schnittstelle
InitUSART(1, 0, 1, 0, 115200, 9600, 0, 0); 

void InitUSART(char USART0, char USART1, char clock0, char clock1,  
               unsigned int baudrate0, unsigned int baudrate1, char IR0,
               char IR1)
{
  if (USART0) ME1 |= UTXE0 + URXE0;  // falls gesetzt, USART0 einschalten 
                                     // (TX- und RX-teil)
  if (USART1) ME2 |= UTXE1 + URXE1;  // falls gesetzt, USART1 einschalten 
                                     // (TX- und RX-teil)
  UCTL0 |= CHAR;                     // 8 data bits, 1 stop bit, no parity (8N1)
  UCTL1 |= CHAR;                     // 8 data bits, 1 stop bit, no parity (8N1)
  if (clock0 == 0) UTCTL0 |= SSEL0;         // ACLK als UCLK festlegen
  else if (clock0 == 1) UTCTL0 |= SSEL1;    // SMCLK als UCLK festlegen
  if (clock1 == 0) UTCTL1 |= SSEL0;         // ACLK als UCLK festlegen
  else if (clock1 == 1) UTCTL1 |= SSEL1;    // SMCLK als UCLK festlegen
  
  if (clock0 == 1)
  {
      BCSCTL1 &= ~XT2OFF;                       // XT2on
      do
      {
          IFG1 &= ~OFIFG;                           // Clear OSCFault flag
          wait(255);                                 // Time for flag to set
      }
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?
      BCSCTL2 |= SELM_2 + SELS;                 // MCLK = SMCLK = XT2 (safe)  
      
      switch (baudrate0)
      {
        case 19200:
          UBR00 = 0xA0;
          UBR10 = 0x01;
          UMCTL0 = 0x00;                            // 8MHz 115200 modulation 
          break;
        case 115200:
          UBR00 = 0x45;                             // 8MHz 115200
          UBR10 = 0x00;                             // 8MHz 115200
          UMCTL0 = 0x00;                            // 8MHz 115200 modulation  
          break;
      }/* switch (baudrate0) */
  }/* if (clock0 == 1)*/
  
  if (clock0 == 0)    // ACLK als UCLK 
  {  
    switch (baudrate0)
    {
      case 1200:
        UBR00 = 0x1B;
        UBR10 = 0x00;
        UMCTL0 = 0x24;             // Siehe Application Note Tabelle 2, Seite 10 
        break;     

      case 2400:
        UBR00 = 0x0D;
        UBR10 = 0x00;
        UMCTL0 = 0x6D;             // Siehe Application Note Tabelle 2, Seite 10
        break;
    
      case 4800:
        UBR00 = 0x06;
        UBR10 = 0x00;
        UMCTL0 = 0xEF;             // Siehe Application Note Tabelle 2, Seite 10
        break;

      case 9600:
        UBR00 = 0x03; 
        UBR10 = 0x00;
        UMCTL0 = 0x4A;             // Siehe Application Note Tabelle 2, Seite 10
        break;
    }/* switch (baudrate0) */  
  }/* if (clock0 == 0) */

  if (clock1 == 0)    // ACLK als UCLK 
  {  
    switch (baudrate1)
    {
      case 1200:
        UBR01 = 0x1B;
        UBR11 = 0x00;
        UMCTL1 = 0x24;             // Siehe Application Note Tabelle 2, Seite 10 
        break;     

      case 2400:
        UBR01 = 0x0D;
        UBR11 = 0x00;
        UMCTL1 = 0x6D;             // Siehe Application Note Tabelle 2, Seite 10
        break;
    
      case 4800:
        UBR01 = 0x06;
        UBR11 = 0x00;
        UMCTL1 = 0xEF;             // Siehe Application Note Tabelle 2, Seite 10
        break;

      case 9600:
        UBR01 = 0x03; 
        UBR11 = 0x00;
        UMCTL1 = 0x4A;             // Siehe Application Note Tabelle 2, Seite 10
        break;
    }/* switch (baudrate0) */  
  }/* if (clock0 == 0) */


  if (USART0) UCTL0 &= ~SWRST;         // USART freigeben
  if (USART1) UCTL1 &= ~SWRST;
  if (IR0==0) IE1 |= URXIE0;           // IR0: 0 -> nur RX-Interrupt anschalten
  if (IR0==1) IE1 |= UTXIE0;           //      1 -> nur TX-Interrupt anschalten
  if (IR0==2) IE1 |= URXIE0 + UTXIE0;  //      2 -> TX- und RX-Interrupt ansch.
  if (IR1==1||IR1==2) IFG1 &= ~UTXIFG0;// Initales Interrupt-Flag löschen
  if (IR1==0) IE2 |= URXIE1;           // IR1: 0 -> nur RX-Interrupt anschalten
  if (IR1==1) IE2 |= UTXIE1;           //      1 -> nur TX-Interrupt anschalten
  if (IR1==2) IE2 |= URXIE1 + UTXIE1;  //      2 -> TX- und RX-Interrupt ansch.
  if (IR1==1||IR1==2) IFG1 &= ~UTXIFG1;// Initales Interrupt-Flag löschen
}/* void InitUSART(char USART0, char...... */

Ich hoffe, dass es nicht zu sehr durcheinander ist. Wäre klasse, wenn 
jemand ne Idee hätte wo der Haken liegen könnte.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 0));

Das bedeutet doch, er soll warten, solange BEIDE Bedingungen erfüllt 
sind. Wenn nur eine davon nicht erfüllt ist, gehts weiter. Also wenn der 
TXBUF leer ist, sendet der schon wieder. Würd ich denken zumindest beim 
schnellen hingucken jetzt.

while (!(IFG1 & UTXIFG0));
while((P3IN & 0x02) == 0);

wäre besser....denke ich :-)

Autor: szimmi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm,
aus meiner Sicht ist die CTS-Logik in der Abfrage
while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 0));
verkehrt herum.
Du schreibst, dass Du die Übertragung anhalten willst, wenn das CTS 1 
ist. Du hälst aber an, wenn es 0 ist. Meiner Meinung nach müsste der 
Code
while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 1));
lauten.

Autor: szimmi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oerks,
schmarrn.
while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 0x02));
oder so in der Art :-)

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann steigt die while Schleife aber trotzdem aus, sobald das UTXIFG0 
gesetzt wird, denn dann ist die Bedingung nicht mehr erfüllt. Statt && 
müsste dann || rein.

Gesprochen dann: Solange der TXBUffer nicht geleert ist ODER solange CTS 
auf 1 ist, warte.

Autor: szimmi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo,
das ist natuerlich sehr fein beobachtet :-)

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

erst einmal vielen Dank. Natürlich war die while-Schleife falsch. 
Logischerweise muss sie ja so aus sehen:
while ((!(IFG1 & UTXIFG0))  || ((P3IN & 0x02) == 1));

Es soll ja in der Schleife verweilt werden, wenn die eine oder die 
andere oder eben beide zusammen erfüllt sind.

Leider funktioniert es immer noch nicht, die übertragung geht ein paar 
wenige Sekunden, dann bricht sie ab und ist erst nach Resetten des 
Funkmoduls wieder
möglich.

Selbst wenn ich super langsam sende, also vielleicht nur ein, zwei oder 
drei Datenpakete in der Sejunde hängt sich das Modul nach einiger Zeit 
schon auf.

Jemand noch eine Idee, woran es noch liegen kann?

Grüße
Sven

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Nachtrag, bei einer Baudrate von z.b. 19200 geht das ganze ohne 
Probleme, da kann ich die Daten so schnell senden, wie der 
Mikrocontroller nur kann und das Modull rennt einfach durch.

Autor: szimmi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Schleife is immer noch falsch:
((P3IN & 0x02) == 1));
ist immer false :-)
bitte in
while ((!(IFG1 & UTXIFG0))  || ((P3IN & 0x02) == 0x02));
ändern.
Vielleicht gehts dann besser

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.