Forum: Mikrocontroller und Digitale Elektronik MSP430 - UART empfängt keine Zeichen


von Hans W. (hans_wurst)


Lesenswert?

Hallo,

ich verwende das Beispiel "msp430x24x_uscia0_uart_01_115k.c" von TI um 
die UART-Schnittstelle von meinem MSP430F247 zu erstellen.

Wenn ich zusätzlich noch eine Funktion erstelle um ein Zeichen zu 
versenden ,funktioniert das wunderbar. Das Empfangen von Zeichen 
funktioniert jedoch selbst bei unverändertem Beispielcode nicht. Der 
RX-Buffer scheint immer leer zu sein und ein Interrupt wird 
dementsprechend auch nie ausgelöst.
Hat jemand schon ein ähnliches Problem gehabt?

Hier mal der unveränderte Beispielcode vom 
"msp430x24x_uscia0_uart_01_115k.c":
1
//******************************************************************************
2
//   MSP430x24x Demo - USCI_A0, 115200 UART Echo ISR, DCO SMCLK
3
//
4
//   Description: Echo a received character, RX ISR used. Normal mode is LPM0.
5
//   USCI_A0 RX interrupt triggers TX Echo.
6
//   Baud rate divider with 1MHz = 1MHz/115200 = ~8.7
7
//   UCBRx = 08; In UCA0MCTL: UCBRSx = round(0.7*8) = 05
8
//   ACLK = n/a, MCLK = SMCLK = CALxxx_1MHZ = 1MHz
9
//
10
//                MSP430F249
11
//             -----------------
12
//         /|\|              XIN|-
13
//          | |                 |
14
//          --|RST          XOUT|-
15
//            |                 |
16
//            |     P3.4/UCA0TXD|------------>
17
//            |                 | 115200 - 8N1
18
//            |     P3.5/UCA0RXD|<------------
19
//
20
//  B. Nisarga
21
//  Texas Instruments Inc.
22
//  September 2007
23
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
24
//******************************************************************************
25
#include "msp430x24x.h"
26
27
void main(void)
28
{
29
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
30
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
31
  {  
32
    while(1);                               // If calibration constants erased
33
                                            // do not load, trap CPU!!
34
  }   
35
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
36
  DCOCTL = CALDCO_1MHZ;
37
  P3SEL = 0x30;                             // P3.4,5 = USCI_A0 TXD/RXD
38
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
39
  UCA0BR0 = 8;                              // 1MHz 115200
40
  UCA0BR1 = 0;                              // 1MHz 115200
41
  UCA0MCTL = UCBRS2 + UCBRS0;               // Modulation UCBRSx = 5
42
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
43
  IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
44
45
  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, interrupts enabled
46
}
47
48
// Echo back RXed character, confirm TX buffer is ready first
49
#pragma vector=USCIAB0RX_VECTOR
50
__interrupt void USCI0RX_ISR(void)
51
{
52
  while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
53
  UCA0TXBUF = UCA0RXBUF;                    // TX -> RXed character
54
}

von Benjamin S. (recycler)


Lesenswert?

Du empfängst ein Zeichen, schiebst es in das Sende register. Beim 2. 
Aufruf bzw. Empfang wartest du so lange, bis das Senden Abgeschlossen 
ist.
1
while (!(IFG2&UCA0TXIFG));

Und ab da hängt dein Kollege im Interrupt.
1
#include "msp430x24x.h"
2
char tmp;
3
4
void main(void)
5
{
6
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
7
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
8
  {  
9
    while(1);                               // If calibration constants erased
10
                                            // do not load, trap CPU!!
11
  }   
12
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
13
  DCOCTL = CALDCO_1MHZ;
14
  P3SEL = 0x30;                             // P3.4,5 = USCI_A0 TXD/RXD
15
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
16
  UCA0BR0 = 8;                              // 1MHz 115200
17
  UCA0BR1 = 0;                              // 1MHz 115200
18
  UCA0MCTL = UCBRS2 + UCBRS0;               // Modulation UCBRSx = 5
19
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
20
  IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
21
22
  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, interrupts enabled
23
}
24
25
26
27
#pragma vector=USCIAB0RX_VECTOR
28
__interrupt void USCI0RX_ISR(void)
29
{
30
  tmp = UCA0RXBUF;                    // save RXed character
31
}

von Hans W. (hans_wurst)


Lesenswert?

Danke für die Antwort.
Mein Problem ist jedoch, dass er erst gar nicht in die ISR rein springt. 
Wenn ich dort einen Breakpoint setzte, wird er trotzdem nie erreicht.

von Benjamin S. (recycler)


Lesenswert?

Ich kenne den 247 nicht, aber hast du einen Uhrenquarz (32,768khz) dran. 
Sonst geht garnix. Jedenfalls bei den alten war das so, weil die die Clk 
für den DCO verwenden.

2. Fehlt nicht ein #include signal.h ???
Irgendwas musst für den Interrupt noch eingebunden werden, soweit ich 
dass noch weiß.

von Jörg S. (joerg-s)


Lesenswert?

Er sagt ja das er problemlos senden kann. Die Clocks sollten also 
passen.

Am Portpin kommt auch ganz sicher was an?

von Stefan (Gast)


Lesenswert?

>Ich kenne den 247 nicht, aber hast du einen Uhrenquarz (32,768khz) dran.
>Sonst geht garnix. Jedenfalls bei den alten war das so, weil die die Clk
>für den DCO verwenden.
Das ist ja grad das Tolle, dass man dann eben keinen Quarz braucht!

>2. Fehlt nicht ein #include signal.h ???
>Irgendwas musst für den Interrupt noch eingebunden werden, soweit ich
>dass noch weiß.
Nein, "msp430x24x.h" reicht!

Ist überhaupt der richtige RX-Pin beschaltet?

von Stefan (Gast)


Lesenswert?

OT:
@Jörg: kommst Du Dir verfolgt vor ? ;-))

von Jörg S. (joerg-s)


Lesenswert?

>@Jörg: kommst Du Dir verfolgt vor ? ;-))
Nö, geht noch ;)

von Benjamin S. (recycler)


Lesenswert?

@Stefan und Jorg. Bei den alten Brauchte man einen zum abgleich, damit 
das stibil lief. Mit den neuen MSPs hab ich leider keine Erfahrung.
Ob das mit dem DCO so richtig hinhaut kann ich auch nicht sagen und ob 
es da nicht zu Jitter kommt.

Hast du sicher RX Pin 0 verwendet und nicht RX1?

von Stefan (Gast)


Lesenswert?

Die neuen werden ab Werk bei versch. Frequenzen kalibriert und die 
entspr. Kalibrierwerte im INFO_A abgelegt. Deshalb ja auch:
1
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
2
  {  
3
    while(1);                               // If calibration constants erased
4
                                            // do not load, trap CPU!!
5
  }   
6
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
7
  DCOCTL = CALDCO_1MHZ;

>Ob das mit dem DCO so richtig hinhaut kann ich auch nicht sagen und ob
>es da nicht zu Jitter kommt.
Das haut hin und der DCO ist erstaunlich genau.
Hab mal 'nen 2012 mit Fön und Kältespray malträtiert und keine mir 
messbare Abweichung feststellen können.

von Benjamin S. (recycler)


Lesenswert?

Danke, das ist sehr interessant. Habe mit dem 169er und einem noch 
älteren Modell gespielt, da wurde im Datenblatt hingewiesen, dass der 
DCO nicht zu ganau ist. Aber wie gesagt, das war damals.

von Hans W. (hans_wurst)


Lesenswert?

Benjamin S. schrieb:
> ...hast du einen Uhrenquarz (32,768khz) dran. Sonst geht garnix. Jedenfalls
> bei den alten war das so, weil die die Clk für den DCO verwenden.

Einen Uhrenquarz habe ich leider nicht. Wenn das wirklich so ist, dann 
kan ich wohl leider nicht empfangen.


> ...Fehlt nicht ein #include signal.h ??? Irgendwas musst für den
> Interrupt noch eingebunden werden, soweit ich dass noch weiß.

Das dieses Beispiel direkt von TI stammt und zum MSP dazugehört, gehe 
ich davon aus, dass der Code vollständig sein sollte.

von Jörg S. (joerg-s)


Lesenswert?

>Einen Uhrenquarz habe ich leider nicht. Wenn das wirklich so ist, dann
>kan ich wohl leider nicht empfangen.
Wie schon gesagt: Wenn senden geht, ist der CLK OK!

von Benjamin S. (recycler)


Lesenswert?

Das denk ich.
Verwende mal folgende ISR:
1
#pragma vector=USCIAB0RX_VECTOR
2
__interrupt void USCI0RX_ISR(void)
3
{
4
  char tmp;
5
  tmp = UCA0RXBUF;                    // save RXed character
6
}

und setzte den breakpoint auf tmp. Schau dann ob er reinspringt.

von Stefan (Gast)


Lesenswert?

Wir wissen immer noch nicht, ob der richtige RX-Pin verwendet wird und 
ob an dem Pin überhaupt was ankommt.
Weitere Fehlerquellen:
Baudrate, Stopbits, Parity
Falls da irgendwas nicht stimmt, wird auch kein RX-IRQ ausgelöst, siehe 
User-Guide UCAxCTL1-Register, UCRXEIE-Bit (hier =0)

von Stefan (Gast)


Lesenswert?

Nachtrag:
Dein Sender hat nicht zufällig Hardware-Handshake aktiviert und wartet 
vergebens auf Sendefreigabe?

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.