Forum: Mikrocontroller und Digitale Elektronik MSP430 - serielle schnittstelle nutzen, aber wie ?!


von johannes (Gast)


Lesenswert?

Moin !

Hat jemand von euch schon mal probiert die serielle schnittstelle zu
nutzen?! ich habe folgendes vor:

ich habe den TI (MSP430F437IPZ) bereits auf ein geeignetes boartd
geloetet und den recieve und transmit pin mit einem geeigneten chip
versehen, der das ausgegebene signal fuer den PC erkennbar und lesbar
macht. hiernach habe ich mich an den code programmiert. danach habe ich
hyperterminal entsprechend initialisiert. es passiert aber rein gar
nichts. manchmal bekomme ich ein zufaelliges zeichen im hyperterminal
ausgegeben wenn ich den TI hochfahre, was heisst dass da irgendwas
kommuniziert. mein code sieht wie folgt aus:



#include <msp430x43x.h>
#include <stdio.h>




int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer

  P2DIR |= 0x0A;  //P2.3 & P2.1 = outputs

  P2SEL |= 0x30;  //UTXD0 and URXD0 = activated

  U0CTL = 0xF1;     //even parity; 2 stop bits; 8-bit data;
LISTEN=disabled;
                    //UART mode; Idle-line MP protocol; SWRST=enabled,
                    //while configuring other regs
  U0TCTL = 0x18;   // UCLKI=UCLK; ACLK; UART receive start-edge
feature; data
  U0RCTL = 0x00;

  ME1 = 0xC0;  //USART0 transmit and receive = enabled
  IE1 = 0x40;  //USART0 receive interrupt enabled

  UTCTL0 = SSEL0;                     // UCLK = ACLK
  UBR00 = 0x03;                         // 32k/9600
  UBR10 = 0x00;                         //
  UMCTL0 = 0x4a;                        //


  P2OUT = 0x02;
  U0TXBUF = 0x4A;


}// main



// USART 0 Receive interrupt service routine
#pragma vector=USART0RX_VECTOR
__interrupt void USART0RX (void)
{
   char temp;

   temp=U0RXBUF;
   P2OUT = 0x08;

}



vielleicht ist es ja n ganz dummer fehler.

vielen dank fuer eure hilfe !


gruss


johannes

von Mario (Gast)


Lesenswert?

Hallo,

der MSP430 verlangt, dass man die im Datenblatt angegebene Reihenfolge
der Registerkonfiguration genau einhält, ansonsten verhält sich die
USART irgendwie, nur nicht so, wie man sie braucht (hab ich selbst
schon mehrfach erlebt ...).

Ansonsten ist es wichtig, während der Konfiguration den Software-Reset
reinzuhauen. Das hast du zwar gemacht, aber ich seh grad nicht, wo du
den auch wieder aufhebst ?!?

Hier mal meine (funktionierende) Konfiguration für 38400 Baud (8N1) aus
einem 4MHz-Takt.

UCTL1 |= SWRST;            // Software-Reset aktivieren
UCTL1 |= CHAR;             // 8N1
UTCTL1 |= SSEL0;           // ACLK als Taktquelle
UBR01 = 0x68;              // 38400 Baud
UBR11 = 0x00;
UMCTL1 = 0x20;
ME2 |= UTXE1 + URXE1;      // Module einschalten (TX, RX)
UCTL1 &= ~SWRST;           // Software-Reset wieder raus
IE2 |= URXIE1;             // Interrupt Enable

Hoffe das hilft weiter,

Grüße, Mario

von thomas.o (Gast)


Lesenswert?

hallo!

ich sehe in deinem Code keine Initialisierung des Clock Systems. Das
angeschlossene 32kHz Quarz wird nämlich nicht automatisch als Clock
Source verwendet, sondern der interne Oszillator, welcher ca. 800kHz
hat.

mfg,
thomas

von johannes (Gast)


Lesenswert?

Danke danke fuer die schnelle hilfe !!!
ich hab hier grad n bisschen thermik - ich klemm mich da morgen frueh
mal hinter !

bis die tage


johannes

von R2D2 (Gast)


Lesenswert?

Du sendest auch nur genau ein Zeichen! U0TXBUF wird nur in Main
beschrieben, aber nicht mehr in irgendwelchen IRQs. Da kannst du nur 1
Zeichen beim Reset bekommen. Außerdem würd ich dir raten das Datenblatt
genau zu lesen und nicht irgendwelche 0x?? werte zuzuweisen, sondern die
bitnamen zu verwenden. Ich hab echt keine Lust die Bits zu überprüfen ob
du dich da nicht irgendwo vertan hast.

Hatte grade selber lang genug mit nem UART-Problem zu kämpfen.
Erkenntnis:
SMCLK ist nicht gleichwertig mit MCLK. Das gilt nur, solange man den
DCO benutzt. Einen Quarz muss man für SMCLK nochmal getrennt von MCLK
aktivieren.

von Mario (Gast)


Lesenswert?

Hallo R2D2,

bei den MSP430s (blöder Plural !) gibt es insgesamt drei Takte: ACLK
(Auxiliary CLocK), MCLK (Main CLocK) und SMCLK (Sub Main CLocK), die
jeweils eigenständig arbeiten.

Daneben gibt es drei (bei kleineren Derivaten manchmal auch nur zwei)
Taktquellen, das sind LFXT1 (1. Quarzoszillator, auch für Uhrenquarze),
XT2 (2. Quarzoszillator) und DCOCLK (der interne Oszillator, der nach
einem Reset standardmäßig aktiviert ist und mit etwa 800kHz schwingt).


Je nach gewünschter Konfiguration kann man jetzt diese Taktquellen (mit
oder ohne Vorteiler) an die jeweiligen Takte anlegen, und auch die
Peripheriemodule (USART, ADC etc.) bieten die Möglichkeit, den jeweils
gewünschten Takt auszuwählen.

Ist etwas undurchsichtig am Anfang, ich hab mich da auch erst
durchfummeln müssen. Wenn man's mal raus hat, ist es aber eigentlich
gar nicht so schlimm :-)

Grüße, Mario

von R2D2 (Gast)


Lesenswert?

Danke für deine Information. Mir war das schon klar mit den
verschiedenen Taktquelle. Ich hab nur bis jetzt eigentlich immer den
DCO oder einen 32kHz-Quarz(ACLK) verwendet. Allerdings hatte ich noch
fast nie den UART benutzt (waren alles Anwendungen die unabhängig vom
PC arbeiten sollen und für's Debuggen halt der JTAG). Da SMCLK bei
DCO-Benutzung standardmäßig == MCLK ist hab ich garnicht weiter drauf
geachtet. Das entsprechende Bit is mir aus welchen Gründen auch immer
beim ersten mal nicht aufgefallen. Hat halt ein paar Stunden bei der
Fehlersuche gekostet, weil ich die ganze Zeit den Fehler bei den
Optokopplern gesucht hab.

An den Code hab ich halt garnicht gedacht, weil er noch von meinen
Experimenten mit dem TUSB-Controller war und da hab ich den Takt an
UCLK eingespeist.

Aber wie's so schön heißt: Aus Fehlern wird man klug.

von johannes (Gast)


Lesenswert?

Also, habe jetzt meinen code wie folgt ueberarbeitet:


#include <msp430x43x.h>
#include <stdio.h>




int main(void)
{
  char ch;

  WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer

  P2DIR |= 0x1A;  //P2.4, P2.3 & P2.1 = outputs

  P2SEL |= 0x30;  //UTXD0 and URXD0 = activated

  U0CTL |= SWRST;   // Software-Reset activated
  U0CTL |= CHAR;     //no parity; 1 stop bits; 8-bit data;
LISTEN=disabled;
                    //UART mode; Idle-line MP protocol;
//  U0TCTL = 0x18;   // UCLKI=UCLK; ACLK; UART receive start-edge
feature; data
  UTCTL0 = SSEL0;    // UCLK = ACLK
  U0BR0 = 0x68;      // 38400 Baud
  U0BR1 = 0x00;
  UMCTL0 = 0x20;
  U0RCTL = 0x00;
  ME1 |= UTXE0 + URXE0;  //USART0 transmit and receive = enabled
  U0CTL &= ~SWRST;       // Software-Reset disabled

  IE1 = 0x40;  //USART0 receive interrupt enabled

/*  UTCTL0 = SSEL0;                     // UCLK = ACLK
  UBR00 = 0x03;                         // 32k/9600
  UBR10 = 0x00;                         //
  UMCTL0 = 0x4a;                        //  */


  P2OUT = 0x02;
  ch = 'J';
  U0TXBUF = ch;


}// main



// USART 0 Receive interrupt service routine
#pragma vector=USART0RX_VECTOR
__interrupt void USART0RX (void)
{
   char temp;

   temp=U0RXBUF;
   P2OUT = 0x08;

}



das sollte jetzt eigentlich laufen funzt aber auch immer noch nicht.
habe saemtliche loetstellen ueberprueft - die hardware scheint i. o. zu
sein.
ich weiss nicht mehr weiter.

@thomas:

du meintest weiter:

"Autor: thomas.o
Datum: 14.07.2005 17:25

hallo!

ich sehe in deinem Code keine Initialisierung des Clock Systems. Das
angeschlossene 32kHz Quarz wird nämlich nicht automatisch als Clock
Source verwendet, sondern der interne Oszillator, welcher ca. 800kHz
hat.

mfg,
thomas"


wie sehe das denn im konkreten source code aus ?!
waere nett wenne mir ma n beispiel posten koenntest - bin echt
verzweifelt!


Danke


gruss an allemann


johannes

von R2D2 (Gast)


Lesenswert?

Ich weiß ja nicht ob es dein Ziel ist einfach P2.3 auf 1 zu schalten
sobald irgendwas vom µC empfangen wird. Dein erstes Posting las sich so
als wolltest du was am PC sehen. Auf die Gefahr hin mich zu
wiederholen:
"Du sendest auch nur genau ein Zeichen! U0TXBUF wird nur in Main
beschrieben, aber nicht mehr in irgendwelchen IRQs. Da kannst du nur 1
Zeichen beim Reset bekommen. "

Wenn du nichts senden willst solltest du auch das U0TXBUF aus main()
rausnehmen.

von Mario (Gast)


Lesenswert?

Hallo,

hmm, also wenn ich das Programm richtig verstehe, müsste der MSP430
beim Reset ein 'J' schicken und dann verstummen. Kommt vom PC das
erste Zeichen rüber (egal welches), wird P2.3 gesetzt. Anschließend
passiert nichts mehr ...

Wie R2D2 schon sagte, ist evtl. ein bissl spartanisch an Funktionalität
;-) Was genau haste denn vor ?

@R2D2: Oh ja, der MSP430 hat da ein paar versteckte "Fallen", die man
erst mal wissen muss. Die ganzen Takte und Taktquellen, der genaue
Initlaiisierungsablauf bei der USART, der Watchdog ... Bin da auch
schon desöfteren wo reingetreten ;-)

Grüße, Euer

Mario

von R2D2 (Gast)


Lesenswert?

UART is doch im Datenblatt mit ner dicken fetten Warunung versehen. Wenn
man nur angefangen hat das Kapitel zu lesen kann doch nix mehr schief
gehen. Ok, der OP hats flsach gemacht. Aber keine Ahnung wie das geht.

Den Watchdog hab ich außer für gezielte Resets noch nicht benutzt. Der
GCC deaktiviert den ja automatisch beim Start, also stört der mich
nicht sonderlich.

Insgesamt is der MSP aber ne durchdachte, flexible Architektur. Jetzt
müssen nur noch 2xxx er mit mehr Pins/Flash rauskommen. Das wär ideal.

von johannes (Gast)


Lesenswert?

also, zur frage was ich eigentlich machen will:
erstmal sichergehen, dass meine hardware i. O. ist und das die serielle
schnittstelle funktioniert (deshalb die spartanische architekture; wird
ein zeichen empfangen, soll der interrupt handler ausgefuehrt werden
und ein LED faengt an zu leuchten - ansonsten wird ein J beim reset
gesendet).
sobald das laeuft habe ich vor ein keypad auf meinem TI zu
implementieren, das jeweils den wert der gedrueckten taste auf dem PC
ausgibt, aber bis dahin scheint mir das noch ein langer weg zu sein...
da ihr weiter nicht auf meinen code eingegangen seid vermute ich mal
das der ok ist. werde dann vielleicht mal den chip zur
datenuebertragung auswechseln - vielleicht hab ich den ja beim
aufloeten kaputt gemacht.


bis dann


johannes

von Mario (Gast)


Lesenswert?

Hi,

hm, wo wird eigentlich das Interrupt-Enable-Bit gesetzt ? Schreib mal
noch die EINT-Anweisung mit rein. Ansonsten müsste der Code eigentlich
schon funktionieren.

Ich würd nicht gleich den Schnittstellentreiber auslöten, schau doch
zuerst mal mit nem Oszi, ob da was passiert.

Grüße, Mario

von johannes (Gast)


Lesenswert?

Mario!

kurz bevor ich den software reset rausnehme aktiviere ich die
interrupts. danach enable ich den receive interrupt weil ich den
spaeter nutzen moechte (im prinzip brauch ich den transmit interrupt ja
ueberhaupt gar nicht!).


  ME1 |= UTXE0 + URXE0;  //USART0 transmit and receive = enabled
  U0CTL &= ~SWRST;       // Software-Reset disabled

  IE1 = 0x40;  //USART0 receive interrupt enabled


"hm, wo wird eigentlich das Interrupt-Enable-Bit gesetzt ? Schreib
mal
noch die EINT-Anweisung mit rein. Ansonsten müsste der Code eigentlich
schon funktionieren. "

was meinst du mit der EINT-Anweisung ???


gruesse

johannes

von Mario (Gast)


Lesenswert?

Hi,

ja schon, das ist ja auch richtig, dass du die Interrupts für die USART
freigibst.

Du musst aber die Interrupts auch GLOBAL erlauben ! Es gibt ja beim
MSP430 (und bei vielen anderen Controllern auch) immer ZWEI Stufen von
Interrupt Enable-Flags, die erste sind die SPEZIFISCHEN Flags für die
jeweiligen Module (also z.B. USART, ADC, Timer-Interrupts,
Port-Interrupts ...), die zweite ist das (einzelne) GLOBALE
Interrupt-Flag, das sich im Status-Register aufhält. Ist es nicht
gesetzt, wird KEIN Interrupt ausgeführt.

Je nach Compiler sieht die Anweisung für das Setzen und Löschen dieses
Flags anders aus, bei mir (IAR Kickstart) setze ich das Flag z.B. mit
der Anweisung:

    _EINT();

Hast du einen anderen Compiler, musst du evtl. mal in die Hilfe
schauen, wie das bei dir funktioniert.

Grüße, Mario

von johannes (Gast)


Lesenswert?

Du hast natuerlich vollkommen recht! ich mach das mit:
_BIS_SR(LPM4_bits + GIE);    //enable maskable interrupts
zu dumm dass ich das vergessen hab!

vielen dank fuer die hilfe soweit. ich probier das nachher ma mitm oszi
aus und hoffentlich kommt da was durch. ansonsten mal sehen was ich dann
mache..


bis dann


johannes

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.