mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART mit MSP430 geht nicht


Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin ein ziemlicher µC-Neuling und da ich mittlerweile schon fast am 
verzweifeln bin, richte ich mich an euch und hoffe, dass ihr mir 
weiterhelfen könnt!

Und zwar geht es um eine einfache UART-Kommunikation. Ich habe schon 
alle damit zusammenhängende Beiträge durchforstet, kam jedoch trotzdem 
nicht weiter.

Ich benutze einen MSP430FG4619 und möchte lediglich mit dem 
Hyperterminal die Eingaben echoen.

Der Code lautet folgendermaßen:

#include "io430xG46x.h"

__interrupt void uartReceiveHandler( void );

unsigned char RxChar;


void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;             // Watchdog aus

  U1CTL |= UCSWRST;                     // Disabel interrupt

  P2SEL    |= BIT4 + BIT5;              // Verwendung der Ports 2.4 und 
2.5
  P2DIR    |= BIT4 ;
  P2DIR    &= ~BIT5;

  U1CTL |= BIT4;                        // 8-bit character
  U1CTL &= ~BIT7 + BIT5;                // no parity, 1 Stopbit
  U1TCTL |= BIT4 + BIT5;                // UCLK = SMCLK
  U1BR0 = 0xB4;                         // 32k/2400 - 13.65
  U1BR1 = 0x01;                         //
  U1MCTL = 0xFF;                        // modulation

  ME2 |= BIT4 + BIT5;                   // Enable USART0 TXD/RXD
  IE2 |= BIT4 + BIT5;                   // Enable USART0 RX interrupt

  U1CTL &= ~UCSWRST;                    // Enable Interrupt
}


#pragma vector=USART1RX_VECTOR

__interrupt void uartReceiveHandler( void )
{

  U1TXBUF = U1RXBUF;                    // empfangenes Byte sofort 
wieder verschicken

}

Vielen Dank schon mal im Voraus!

Viele Grüße
Johannes

Autor: Jörg S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> geht nicht
Was geht nicht? Springt er denn in die Interrupt Schleife? Kannst du 
Zeichen senden und sie kommen am PC an? Warum schaltest du den TX 
Interrupt an? Sind die globalen Interrupts überhaupt eingeschaltet?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was meinst du wohl, was passiert, wenn du das erste Zeichen vom MSP an 
den PC geschickt hast, und der Sende-Interrupt ausgelöst wird, ohne dass 
du einen Interrupt-Handler dafür hast?

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, den Sende-Interrupt hatte ich schon drin, habe ihn (dummerweise) für 
den Thread rausgenommen. Das heißt, der folgende Code würde noch dazu 
kommen:

#pragma vector=USART1TX_VECTOR

__interrupt void uartSendHandler( void )
{

}

Muss ich dann im Interrupt den Buffer wieder löschen?

Aber trotz alledem wird kein Interrupt ausgelöst, weder wenn ich mit dem 
Hyperterminal etwas verschicke noch wenn ich bewusst etwas in den 
SendeBuffer schreibe.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den TX-Interrupt schalte ich an, weil ich ja wieder etwas senden möchte. 
Die globalen Interrupts schalte ich mit dem folgenden Code an,oder? :

 __bis_SR_register(GIE);

Das hatte ich auch schon mal , hatte aber auch nicht funktioniert...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>U1CTL &= ~BIT7 + BIT5;                // no parity, 1 Stopbit
aktiviert Parity, Listen-Mode und vorallem SPI !

Ich vermute mal, Du wolltest:
U1CTL &= ~BIT7;
U1CTL |=  BIT5;

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan,

also ich möchte USART im UART-Mode verwenden. In dem Datenblatt dazu 
steht doch, dass beim Reseten von BIT 5 und BIT 7 zum einen ein Stopbit 
eingestellt wird und zum anderen die Parity disabled wird, oder?

Gruß
Johannes

Autor: Jörg S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du dir sicher das du dir das Senden mit Interrupt antuen willst? 
Senden würde ich "normal" machen.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

wie würde es denn "normal" gehen?

Autor: Jörg S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TX Interrupt ausschalten und nur  U1TXBUF = Daten;  verwenden.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und am besten immer die Makros für die Register-Bits verwenden, mit Bit3 
+ Bit 5 usw sieht ja kein Schwein durch. Nimm doch zum Start erst mal 
ein Demo von TI und schmeiß den TX-Int raus. Das bringt nur was, wenn du 
während des Sendens mit der CPU noch andere Sachen machen musst.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>dass beim Reseten von BIT 5 und BIT 7
Ja schon, aber Dein Code macht was anderes!
Ich korrigiere mein voriges Posting, Parity und SPI werden nicht 
aktiviert, aber trotzdem glaube ich, dass Du nicht das programmiert 
hast, was Du eigentlich wolltest:

>U1CTL &= ~BIT7 + BIT5;

  ~BIT7 = b01111111
+  BIT5 = b00100000
-------------------
          b10011111

Kommt zwar "zufällig"(?) was richtiges raus, ist aber nicht "schön" ;-)

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab es mal ausprobiert. Habe bewusst die TX-Interrupts disabled und den 
TX-Handler herausgenommen und in U1TXBUF ein 'q' geschrieben. Am 
Hyperterminal kommt aber leider trotzdem nix an...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähmm...
>P2SEL    |= BIT4 + BIT5;              // Verwendung der Ports 2.4 und 2.5

P2.4 u. P2.5 gehören zur USCI-Schnittstelle, Du benutzt aber die USART!
Probier mal lieber P4.0/4.1

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, stimmt! Wollte zuerst nämlich USCI verwenden. Hat halt Anfangs auch 
nicht funktioniert und bin deshalb auf USART umgestiegen. Aber ich 
probiere es nochmal aus!

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe nun den Code auf USCI umgeschrieben, da ich sont die hardware 
umlöten hätte müssen....Somit müssten jetzt die Ports wieder stimmen, 
die Kommunikation funktioniert jedoch immer noch nicht.. :-(

Was mache ich falsch???

Der Code:

#include "io430xG46x.h"
#include <intrinsics.h>



__interrupt void uartReceiveHandler( void );

unsigned char RxChar;


void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;             // Watchdog aus

  UCA0CTL1 |= UCSWRST;                  // Disabel interrupt

  P2SEL    |= BIT4 + BIT5;              // Verwendung der Ports 2.4 und 
2.5
  P2DIR    |= BIT4 ;
  P2DIR    &= ~BIT5;


  UCA0CTL0 &= ~BIT3;                       // 1 Stopbit
  UCA0CTL0 &= ~BIT4;                       // 8-bit character
  UCA0CTL0 &= ~BIT5;                       // LSB first
  UCA0CTL0 &= ~BIT7;                       // no parity

  UCA0CTL1 |= BIT6 + BIT7;                 // UCLK = SMCLK

  UCA0BR0 = 69;                            // 32k/115200 - 13.65
  UCA0BR1 = 0;                             //
  UCA0MCTL = UCBRS_4;                      // modulation

  IE2 |= BIT0;

  UCA0CTL1 &= ~UCSWRST;                    // Enable Interrupt

  __bis_SR_register(GIE);


}


#pragma vector=USCIAB0RX_VECTOR

__interrupt void uartReceiveHandler( void )
{

   UCA0TXBUF = UCA0RXBUF;                    // empfangenes Byte sofort 
wieder verschicken

}


Ich hoffe, ihr könnt mir weiterhelfen...

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also, ich habe jetzt mal von ganz vorne angefangen und versucht, 
irgendetwas an das Hyperterminal ohne Interrupts zu schicken (siehe 
folgender Code):

#include "io430xG46x.h"
#include <intrinsics.h>


void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;             // Watchdog aus

  P2SEL    |= BIT4 + BIT5;              // Verwendung der Ports 2.4 und 
2.5
  P2DIR    |= BIT4 ;
  P2DIR    &= ~BIT5;

  UCA0CTL0 &= ~BIT3;                       // 1 Stopbit
  UCA0CTL0 &= ~BIT4;                       // 8-bit character
  UCA0CTL0 &= ~BIT5;                       // LSB first
  UCA0CTL0 &= ~BIT7;                       // no parity

  UCA0CTL1 |= BIT6 + BIT7;                 // UCLK = SMCLK

  UCA0BR0 = 0x03;                           // 32k/9600 - 3.41
  UCA0BR1 = 0x00;                           //
  UCA0MCTL = 0x06;


  while(1)
    {
      while (!(IFG2 & UCA0TXIFG));         // Warten bis TX Buffer leer
      UCA0TXBUF = '5';                      // Testzeichen senden
    }
}

Er kommt jedoch nie in die letzte Zeile, in der die 5 in den Buffer 
geschrieben wird. Aber wieso nicht??? Hat irgendjemand eine Idee?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UCA0CTL1 &= ~UCSWRST;
fehlt, damit ist USCI nicht aktiv!

Halte Dich doch mal an die Init-Anweisung im User-Guide!!!

"Note: Initializing or Re-Configuring the USCI Module
 The recommended USCI initialization/re-configuration process is:
 1) Set UCSWRST (BIS.B #UCSWRST,&UCAxCTL1)
 2) Initialize all USCI registers with UCSWRST = 1 (including UCAxCTL1)
 3) Configure ports.
 4) Clear UCSWRST via software (BIC.B #UCSWRST,&UCAxCTL1)
 5) Enable interrupts (optional) via UCAxRXIE and/or UCAxTXIE"

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, vielen Dank für den guten Tipp...Jetzt kommt er auch in die letzte 
Zeile! Mit dem Oszilloskop kann ich jetzt schon mal erkennen, dass er 
irgendwas sendet. Nur leider interresiert das dem Hyperterminal nicht im 
geringsten.... Baudrate, Stopbits und Parity habe ich alles so 
eingestellt wie im Quellcode.....

Woran kann das noch liegen?!

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ist denn da überhaupt ein MAX3232 oder ähnliches dazwischen?

Autor: MartinH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Evtl passt einfach deine Baudrateneinstellung noch nicht.
Hier -> http://mspgcc.sourceforge.net/baudrate.html kann man sich bequem 
die Werte ausrechnen lassen.

Ist dein Takt schnell genug für die eingestellte Rate?
Stellst du irgendwo überhaupt deine Taktquellen ein, oder verwendest du 
den internen? Der läuft defaultäßig so ca.(!) bei 800kHz denke ich. Was 
für 9600 baud eher problematisch ist ;)

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Christian: Ja, habe einen MAX3232 dazwischen.

@ Martin: Ich verwende den internen Takt. Welche Baudrate ist denn dann 
zu bevorzugen? Die Einstellungen für die Baudrate habe ich von einem 
Codeexample von TI.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Einstellungen für die Baudrate habe ich von einem
>Codeexample von TI.

Dann muss man aber auch die Hardware wie im TI-Bsp. verwenden, nämlich 
einen 32kHz-Uhrenquarz!

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ok, aber den habe ich nicht. Ich möchte zunächst erst mal ohne 
externen Quarz arbeiten. Was für eine Baudrate muss ich denn dann am 
besten nehmen?

Übrigens schon mal vielen Dank für die rege Beteiligung, weiß ich 
wirklich zu schätzen!

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohje...naja, 9600 kriegt man meistens noch recht gut hin mit dem 
internen Takt. Aber mehr ist schwierig, dann darf sich die Temp nicht 
ändern. Schließ lieber einen Quarz an.

Autor: MartinH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du keinen externen Quarz hast, musst du erstmal den internen DCO 
(Digital Controlled Oscilator) einstelln. Wie gesagt defaultmäßig läuft 
er auf ein paar kHz. Müsste aber auf bis zu 4MHz einstellbar sein.
Hier ( Beitrag "MSP430 DCO einstellen" ) gibts einige Infos 
dazu.

In den Ergebnissen vom Baudratenrechner ist auch der Fehler in Prozent 
angegeben. Der sollte unter 1% liegen.

Ich habe z.b. einen externen 4MHz Quarz habe UART mit 57600 baud laufen. 
Das sind dann so 0,8% Fehler, klappt wunderbar.

Es gibt auch einen Pins, an dem du direkt die Taktfrequenzen der 
verschiedenen Takleitungen des MSP abgreifen kannst. Damit kannst du 
dann deine Takteinstellungen prüfen.

An deiner Stelle würde ich mir erstmal die wichtigsten Kapitel des 
Family User´s Guide zu deinem MSP durchlesen. Also UART, Basic Clock 
Module(!)

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aller Anfang ist schwer... OK, zumindest nicht ganz leicht... das wissen 
wir alle. Aber was um Himmels Willen hindert Dich daran, mal das 
entsprechende Kapitel (USCI - UART mode) im User Guide von vorne bis 
hinten durchzulesen?
Da steht alles -wirklich alles- was Du wissen musst drin, auch wie man 
die Baudrate einstellt!

Zuvor solltest Du dann vielleicht noch das Kapitel Basic Clock Settings 
durch lesen, um herauszufinden, wie man den internen Clock konfiguriert, 
denn davon hängt letzendlich auch Deine Baudrate ab!

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
JAAAAAAAAAAA, ich kann immerhin schon mal was raussenden!!! Die 5 kommt 
am Hyperterminal an!!!! Es lag tatsächlich an der Baudrate. Habe jetzt 
folgende Einstellung gewählt:


  UCA0BR0 = 0x09;                           // 1MHz 115200
  UCA0BR1 = 0x00;                           // 1MHz 115200
  UCA0MCTL = 0x02;                          // Modulation

Damit gehts. Jetzt werde ich nach und nach versuchen, das ganze mit 
Interrupts aufzubauen.

Vielen vielen dank für die Tipps!
Viele Grüße
Johannes

P.S.: Ich hoffe, das ich den Rest alleine hinbekomme :-)

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ehrenwort, den User Guide kann ich schon fast auswendig... :-I Aber das 
eine Baudrate von 9600 beim internen Takt problematisch ist, steht da 
nicht drin... :-(

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber das eine Baudrate von 9600 beim internen Takt problematisch ist,
>steht da nicht drin... :-(
Weil das auch Quatsch ist !!!
Es geht darum, dass
  UCA0BR0 = 0x03;                           // 32k/9600 - 3.41
  UCA0BR1 = 0x00;                           //
  UCA0MCTL = 0x06;
bei einem internen Takt ungleich 32kHz nicht passt!

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ok. Da hast du Recht. Ich beschäftige mich damit halt erst seit einer 
Woche und so was liest man, aber versteht bzw. erkennt man nicht 100%ig 
und dann macht man so doofe Fehler...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ja ok. Da hast du Recht.
Einsicht ist der erste Schritt zur Besserung :-))

Es gibt als "Anfänger" keine "doofen" Fehler...
Aber man sollte sich nicht verführen lassen, blindlings jeden 
Sample-Code einfach so zu übernehmen, ohne ihn zu hinterfragen, bzw. 
zumindest mal im User-Guide nach zu schauen, was die Kollegen da 
programmiert haben. Genau dadurch lernt man ja!
Viel Erfolg weiterhin!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.