Forum: Mikrocontroller und Digitale Elektronik MSP430 UART RX Interrupt- und Empfangsfehler


von Megabyte (Gast)


Lesenswert?

Hallo µC-Gemeinde,
ich habe beim MSP430F1611 das Problem, dass der Interrupt beim Empfangen 
mit UART nur ausgelöst wird, wenn ich mehr als ein Zeichen sende, also 
nur bei zwei oder mehr.
Auch werden die Zeichen nicht richtig empfangen (z. B. wenn ich ein 
(also zwei) 'a' sende kommt am µC im RXBUF0 0xa7 (§) raus)

Ich habe die Hardware für ein Schulprojekt gestellt bekommen. Es wurden 
ein 8MHz- und ein 32768Hz-Quarz verbaut und ich hoffe richtig verbunden 
(laut Schaltplan: ja)

hier die Initialisierung von der UART
1
void initSerial () {
2
  // UART Reset für Konfiguration
3
  U0CTL |= 0x01;
4
  // P3.5 als Input
5
  P3DIR &= ~(0x20);
6
  // P3.4 als Output
7
  P3DIR |= 0x10;
8
  // Alternativ-Funktion von P3.5 + 4 auswählen (UART)
9
  P3SEL |= 0x20 | 0x10;
10
  // 8-MHz-Quarz aktivieren (X2)
11
  BCSCTL1 &= ~(0x80);
12
  // 8-MHz-Quarz als Quelle für SMCLK auswählen
13
  BCSCTL2 |= 0x08;
14
  // SMCLK auf 1 MHz runterteilen
15
  BCSCTL2 |= 0x40 | 0x20;
16
  // keine Parität
17
  U0CTL &= ~(0x80);
18
  // ein Stoppbit
19
  U0CTL &= ~(0x20);
20
  // 8-Bit-Daten
21
  U0CTL |= 0x10;
22
  // kein Listen-Mode
23
  U0CTL &= ~(0x08);
24
  // UART-Mode auswählen
25
  U0CTL &= ~(0x04);
26
  // kein Mulitprozessor-Mode
27
  U0CTL &= ~(0x02);
28
  // SMCLK als UCLK auswählen
29
  U0TCTL |= 0x20;
30
  U0TCTL &= ~(0x10);
31
  
32
//  // Baudrate: 115200 mit SMCLK (8 MHz)
33
//  UBR10 = 0x00;
34
//  UBR00 = 0x45;
35
//  UMCTL0 = 0xaa;
36
37
//  // Baudrate: 28800 mit SMCLK (8 MHz)
38
//  UBR10 = 0x01;
39
//  UBR00 = 0x15;
40
//  UMCTL0 = 0xbb;
41
42
  // Baudrate: 28800 mit SMCLK (1 MHz)
43
  UBR10 = 0x00;
44
  UBR00 = 0x45;
45
  UMCTL0 = 0xaa;
46
47
  // Senden aktivieren
48
  ME1 |= 0x80;
49
  // Empfangen aktivieren
50
  ME1 |= 0x40;
51
  // UART Reset zurücksetzen
52
  U0CTL &= ~(0x01);
53
  // UART RX Interrupt aktivieren
54
  IE1 |= 0x40;
55
}

und die ISR
1
#pragma vector = USART0RX_VECTOR
2
__interrupt void ser0int () {
3
  while (!(IFG1 & UTXIFG0));                // USART0 TX buffer ready?
4
  TXBUF0 = RXBUF0;                          // RXBUF0 to TXBUF0
5
}

in der main-Funktion werden alle Interrupts zugelassen (und sobald zwei 
Zeichen gesendet bzw. empfangen werden springt der Controller ja auch in 
die ISR)

Ach noch nebenbei, das Senden funktioniert einwandfrei (also µC -> PC).

Bitte um schnelle Hilfe!!
Gruss Michael

von Stefan (Gast)


Lesenswert?

>>// Baudrate: 28800 mit SMCLK (1 MHz)
1
  UBR10 = 0x00;
2
  UBR00 = 0x45;
3
  UMCTL0 = 0xaa;
Wenn ich mal die Modulation ausser Acht lasse, komme ich hier auf 14,4k 
und nicht 28,8k

von Megabyte (Gast)


Lesenswert?

Sorry, sind 14400! Hab mir die Baudrate neu berechnen lassen, aber 
vergessen den Kommentar zu aktualisieren.

von Christian R. (supachris)


Lesenswert?

Du musst auf jeden Fall nach Aktivieren des XT2 ein Delay einfügen und 
prüfen, ob das Fault-Flag weg ist. Das dauert einige Zeit, bis der Quarz 
fertig angeschwungen hat. Eventuell kommt die UART Logik durcheinander, 
wenn der noch nicht ganz fertig ist....

von MartinH (Gast)


Lesenswert?

Nur so nebenbei. Hast du am Anfang den Watchdog deaktiviert?
->  WDTCTL = WDTPW + WDTHOLD;             // halte watchdog an

Ansonsten würde ich auch sagen, erstmal warten bis der Quarz 
eingeschwungen ist.

Dann nochmal die Register gegenchecken, ob du wirklich SMCLK = MCLK / 8
gesetzt hast.

von MartinH (Gast)


Lesenswert?

Zum Debuggen ist es auch immer recht hilfreich wenn man direkt die Namen 
der einzelnen Bits benutzt, und nicht die Hex-Zahlen selbst:
Probier mal folgendes:
1
ME1 |= UTXE0 + URXE0;    // USART0 einschalten (TX- und RX-teil)
2
UCTL0 |= CHAR;           // 8 data bits, 1 stop bit, no parity (8N1)
3
UTCTL0 |= SSEL1;         // SMCLK als UCLK festlegen
4
UBR00 = 0xA0;            // 19200 baud aus 8 MHz erzeugen
5
UBR10 = 0x01;            // siehe application note tabelle 1, seite 9
6
UMCTL0 = 0x00;           // keine korrektur der division noetig
7
UCTL0 &= ~SWRST;         // USART freigeben
8
IE1 |= URXIE0;           // RX-interrupt anschalten
9
IFG1 &= ~UTXIFG0;  // initales interrupt-flag loeschen

Vorher SMCLK ohne Vorteiler von MCLK ableiten, und die Pins wie gehabt 
einstellen.  Evtl liegt es auch nur darann, dass das initiale Int-Flag 
bei dir nicht gelöscht wird.

von Megabyte (Gast)


Lesenswert?

Wird gelöscht! Mach ich schon in der Init!
1
void init () {
2
  // 8-MHz-Quarz aktivieren (X2)
3
  BCSCTL1 &= ~(0x80);
4
5
  // OSC-Fault-Flag zurücksetzen
6
  do {
7
    IFG1 &= ~(0x02);
8
    for (unsigned char i = 0xff; i > 0; i --);
9
  } while (IFG1 & 0x02);
10
11
  // 8-MHz-Quarz als Quelle für MCLK auswählen
12
  BCSCTL2 |= 0x80; // X2 als Quelle für MCLK
13
}

von Megabyte (Gast)


Lesenswert?

Sorry, bitte einfach vergessen.
Die SCH... Hardware macht mein schönes RS232-Signal zunichte!
ohne HW +6V -6V
mit HW  +4V -1V

da kann nix gehen

Trotzdem vielen Dank für die schnellen und guten Antworten und für die 
verbratenen Gehirnzellen.

LG Michael

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.