MSP430 Usart - Baudratenproblem

Gast #608987
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.
#609046
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 :-)
Gast #609051
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.
Gast #609887
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren