Forum: Mikrocontroller und Digitale Elektronik MSP430 Usart - Baudratenproblem


von Sven (Gast)


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:
1
void SendUSART0(char* str)       // Einen String über die serielle Schnittstelle 
2
{                                // (USART0) senden
3
  while (*str != 0)
4
  {
5
    // Warten, bis USART0 TX-buffer sendebereit
6
    while ((!(IFG1 & UTXIFG0))  && ((P3IN & 0x02) == 0));   
7
    TXBUF0 = *str++;
8
  }
9
}/* 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
1
InitUSART(1, 0, 1, 0, 115200, 9600, 0, 0); 
2
3
void InitUSART(char USART0, char USART1, char clock0, char clock1,  
4
               unsigned int baudrate0, unsigned int baudrate1, char IR0,
5
               char IR1)
6
{
7
  if (USART0) ME1 |= UTXE0 + URXE0;  // falls gesetzt, USART0 einschalten 
8
                                     // (TX- und RX-teil)
9
  if (USART1) ME2 |= UTXE1 + URXE1;  // falls gesetzt, USART1 einschalten 
10
                                     // (TX- und RX-teil)
11
  UCTL0 |= CHAR;                     // 8 data bits, 1 stop bit, no parity (8N1)
12
  UCTL1 |= CHAR;                     // 8 data bits, 1 stop bit, no parity (8N1)
13
  if (clock0 == 0) UTCTL0 |= SSEL0;         // ACLK als UCLK festlegen
14
  else if (clock0 == 1) UTCTL0 |= SSEL1;    // SMCLK als UCLK festlegen
15
  if (clock1 == 0) UTCTL1 |= SSEL0;         // ACLK als UCLK festlegen
16
  else if (clock1 == 1) UTCTL1 |= SSEL1;    // SMCLK als UCLK festlegen
17
  
18
  if (clock0 == 1)
19
  {
20
      BCSCTL1 &= ~XT2OFF;                       // XT2on
21
      do
22
      {
23
          IFG1 &= ~OFIFG;                           // Clear OSCFault flag
24
          wait(255);                                 // Time for flag to set
25
      }
26
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?
27
      BCSCTL2 |= SELM_2 + SELS;                 // MCLK = SMCLK = XT2 (safe)  
28
      
29
      switch (baudrate0)
30
      {
31
        case 19200:
32
          UBR00 = 0xA0;
33
          UBR10 = 0x01;
34
          UMCTL0 = 0x00;                            // 8MHz 115200 modulation 
35
          break;
36
        case 115200:
37
          UBR00 = 0x45;                             // 8MHz 115200
38
          UBR10 = 0x00;                             // 8MHz 115200
39
          UMCTL0 = 0x00;                            // 8MHz 115200 modulation  
40
          break;
41
      }/* switch (baudrate0) */
42
  }/* if (clock0 == 1)*/
43
  
44
  if (clock0 == 0)    // ACLK als UCLK 
45
  {  
46
    switch (baudrate0)
47
    {
48
      case 1200:
49
        UBR00 = 0x1B;
50
        UBR10 = 0x00;
51
        UMCTL0 = 0x24;             // Siehe Application Note Tabelle 2, Seite 10 
52
        break;     
53
54
      case 2400:
55
        UBR00 = 0x0D;
56
        UBR10 = 0x00;
57
        UMCTL0 = 0x6D;             // Siehe Application Note Tabelle 2, Seite 10
58
        break;
59
    
60
      case 4800:
61
        UBR00 = 0x06;
62
        UBR10 = 0x00;
63
        UMCTL0 = 0xEF;             // Siehe Application Note Tabelle 2, Seite 10
64
        break;
65
66
      case 9600:
67
        UBR00 = 0x03; 
68
        UBR10 = 0x00;
69
        UMCTL0 = 0x4A;             // Siehe Application Note Tabelle 2, Seite 10
70
        break;
71
    }/* switch (baudrate0) */  
72
  }/* if (clock0 == 0) */
73
74
  if (clock1 == 0)    // ACLK als UCLK 
75
  {  
76
    switch (baudrate1)
77
    {
78
      case 1200:
79
        UBR01 = 0x1B;
80
        UBR11 = 0x00;
81
        UMCTL1 = 0x24;             // Siehe Application Note Tabelle 2, Seite 10 
82
        break;     
83
84
      case 2400:
85
        UBR01 = 0x0D;
86
        UBR11 = 0x00;
87
        UMCTL1 = 0x6D;             // Siehe Application Note Tabelle 2, Seite 10
88
        break;
89
    
90
      case 4800:
91
        UBR01 = 0x06;
92
        UBR11 = 0x00;
93
        UMCTL1 = 0xEF;             // Siehe Application Note Tabelle 2, Seite 10
94
        break;
95
96
      case 9600:
97
        UBR01 = 0x03; 
98
        UBR11 = 0x00;
99
        UMCTL1 = 0x4A;             // Siehe Application Note Tabelle 2, Seite 10
100
        break;
101
    }/* switch (baudrate0) */  
102
  }/* if (clock0 == 0) */
103
104
105
  if (USART0) UCTL0 &= ~SWRST;         // USART freigeben
106
  if (USART1) UCTL1 &= ~SWRST;
107
  if (IR0==0) IE1 |= URXIE0;           // IR0: 0 -> nur RX-Interrupt anschalten
108
  if (IR0==1) IE1 |= UTXIE0;           //      1 -> nur TX-Interrupt anschalten
109
  if (IR0==2) IE1 |= URXIE0 + UTXIE0;  //      2 -> TX- und RX-Interrupt ansch.
110
  if (IR1==1||IR1==2) IFG1 &= ~UTXIFG0;// Initales Interrupt-Flag löschen
111
  if (IR1==0) IE2 |= URXIE1;           // IR1: 0 -> nur RX-Interrupt anschalten
112
  if (IR1==1) IE2 |= UTXIE1;           //      1 -> nur TX-Interrupt anschalten
113
  if (IR1==2) IE2 |= URXIE1 + UTXIE1;  //      2 -> TX- und RX-Interrupt ansch.
114
  if (IR1==1||IR1==2) IFG1 &= ~UTXIFG1;// Initales Interrupt-Flag löschen
115
}/* 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.

von Christian R. (supachris)


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

von szimmi (Gast)


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.

von szimmi (Gast)


Lesenswert?

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

von Christian R. (supachris)


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.

von szimmi (Gast)


Lesenswert?

Jo,
das ist natuerlich sehr fein beobachtet :-)

von Sven (Gast)


Lesenswert?

Hallo zusammen,

erst einmal vielen Dank. Natürlich war die while-Schleife falsch. 
Logischerweise muss sie ja so aus sehen:
1
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

von Sven (Gast)


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.

von szimmi (Gast)


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

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.