www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430x169 und serielle Schnitstelle


Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich versuche die Serielle Schnittstelle von meinen MSP430x169 zum laufen 
zu bekommen. Leider bisher ohne Erfolg. Ich habe schon viele 
Beispielprogramme  ausprobiert nur bis jetzt hat nichts geklappt. Ich 
benutze das MSP430169STK Board von Olimex. Die Serielle Schnittstelle am 
PC habe ich auch schon getestet und die macht es noch. Auch habe ich 
mein Programm schon auf einen anderen Board laufen lassen und dies 
ebenfalls ohne Erfolg.
//------------------------------------------------------------------------------
// Init USART0  
void init_USART0 (unsigned char IR0)  
//------------------------------------------------------------------------------
{
  P3SEL |= 0x30;    // enable special funktion on PIN3.4, 3.5
  P3DIR |= 0x10;     // set direction
    
  UTCTL0 = CHAR;    // set 8bit
  UTCTL0 = SSEL0;    // set ACLK as USART0_CLK
  
  UBR00 = 0x03;
  UBR10 = 0x00;
  UMCTL0 = 0x4A;
  
  ME2 |= UTXE0+URXE0;       // enable UART0 RX&TX
  if (IR0 == 1) IE2 |= URXIE0;   // enable UART0 RX ISR
  if (IR0 == 2) IE2 |= UTXIE0;   // enable UART0 TX ISR
  if (IR0 == 3) IE2 |= UTXIE0+URXIE0;   // enable UART0 TX&RX ISR
  
  UCTL0 &= ~SWRST;
  _EINT();                      // interrupt enable
}

//------------------------------------------------------------------------------
// send character  
void send_USART0 (unsigned char out_char)  
//------------------------------------------------------------------------------
{
  while((IFG2 & UTXIFG0) != UTXIFG0);
  TXBUF0 = out_char;
}
Vielleicht kann ja mal jemand ueber meinen Code schauen. Auf jeden Fall 
freue ich mich ueber jede Hilfe! Und einen Dank schon mal von mir


mfg
Stephan

Autor: Ampfing (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Stephan,

als erstes fällt mir mal auf, dass Du zu Beginn der Routine die 
Schnittstelle nicht zurücksetzt (also das SWRST Bit nicht setzt). Dies 
wird explizit im Datenblatt empfohlen.
Außerdem wählst Du den ACLK als Quelle für die Schnittstelle. Der Takt 
ist da, oder??

Viele Grüße

Autor: Wolfgang-G (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welche Baudrate wurde gewählt?

Autor: Richard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das geht bei mir:

#define USART0_ENABLE       1
#define RX_INT_ENABLE       0
#define TX_INT_ENABLE       1
#define RXTX_INT_ENABLE     2
#define INIT_INT_REMOVE     1   // Init. interr.-flag loesch. (UTXIFG0)
#define INIT_INT_NOT_REMOVE 0   // Init. interr.-flag nicht loesch. // 
(UTXIFG0)

--> bei  BCSCTL1 = 0x00;              // ACLK = NO CLK !!!
--> BCSCTL2 = SELM_2 | SELS;        // MCLK = LFXT1 (safe)

Init_USART (USART0_ENABLE, 9600, RX_INT_ENABLE, INIT_INT_NOT_REMOVE);

void Init_USART(unsigned char USART0, unsigned int baudrate1, unsigned 
char IR0, unsigned char IR1)
{

  //================ USART 0 =====================//
  if (USART0)
  {
    UCTL0 |= CHAR;        // 8 Data Bits, 1 Stop Bit, no parity (8N1)
    UTCTL0 |= SSEL1;      // SMCLK als UCLK festlegen
  }

  if (baudrate1 == 19200)       Bei 7372800Hz --> Quarz !!
  {                 // - Baud rate control register 0
    // 19200 baud aus 7,3728 Mhz/19200 (0x180) MHz erzeugen
    UBR00 = 0x80;
    UBR10 = 0x01;    // Baud rate control register 0
    UMCTL0 = 0x00;   // keine korrektur der division noetig
  }
  else if (baudrate1 == 9600)
  {
    UBR00 = 0x00; UBR10 = 0x03; UMCTL0 = 0x00;
  }
  else if (baudrate1 == 57600)
  {
    UBR00 = 0x80; UBR10 = 0x00; UMCTL0 = 0x00;
  }
  else // 19200 baud
  {
    UBR00 = 0x80; UBR10 = 0x01; UMCTL0 = 0x00;
  }

  if (USART0)
  {
    ME1 |= UTXE0 + URXE0;       // USART0 einschalten (TX- und RX-teil)
    P3SEL |= 0x30;              // P3.4,5 = USART0 TXD/RXD
    P3DIR |= 0x10;              // P3.4 = output direction
    UCTL0 &= ~SWRST;            // USART freigeben
  }

  if (IR0==0)  IE1 |= URXIE0;   // IR0: 0 -> nur RX-interrupt an
  if (IR0==1)  IE1 |= UTXIE0;   // 1 -> nur TX-interrupt an
  if (IR0==2)  IE1 |= URXIE0 + UTXIE0;  // 2 -> TX- und RX-interr. an
  if (IR1==1 || IR1==2) IFG1 &= ~UTXIFG0;  // init. interr.-flag loesch.

  //================ USART 0 ======================//
}

Gruß

Ricardo

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Ampfing
Bit habe ich jetzt vor der Initialisierung gesetzt. Der Takt ist da. Er 
wird ohne Vorteiler vom 32768kHz Quarz abgegriffen.

@ Wolfgang-G
Nach meiner Berechnung wurde eine Baudrate von 9600 gewählt. Errechnet 
sich aus der Quarzfrequenz(32768kHz)/9600Baud = 3.413. UBRx0 = 0x0003 
und das Modulationsregister mit 0x4A. Werte und Berechnung im Datenblatt 
zu finden.

Das ganze funktioniert jetzt ohne Probleme. Das Problem lag einzig darin 
das ich die P3SEL und P3DIR Register beschrieben habe bevor ich das 
SWRST Bit gelöscht habe. Um es euch zu zeigen hier mein Code der nun 
ohne Probs funzt.
// Init USART0  
void init_USART0 (unsigned int baudrate, unsigned char IR0)  
//------------------------------------------------------------------------------
{  
  UCTL0 = SWRST + CHAR;  // set 8bit, none parity and 1 stoppbit    
  UTCTL0 |= SSEL0;    // set ACLK as USART0_CLK
  
  UBR00 = 0x03;
  UBR10 = 0x00;
  UMCTL0 = 0x4A;
  
  ME1 |= UTXE0 + URXE0;   // enable UART0 RX&TX
  UCTL0 &= ~SWRST;
  
  P3SEL |= 0x38;      // enable special funktion on PIN3.3, 3.4, 3.5
  P3DIR |= 0x18;       // set direction, PIN3.3, 3.4 OUTPUT
  
  if (IR0 == 1) IE1 |= URXIE0;   // enable UART0 RX ISR
  if (IR0 == 2) IE1 |= UTXIE0;   // enable UART0 TX ISR
  if (IR0 == 3) IE1 |= UTXIE0+URXIE0;   // enable UART0 TX&RX ISR  
}

//------------------------------------------------------------------------------
// send character  
void send_USART0 (unsigned char out_char)  
//------------------------------------------------------------------------------
{
  while((IFG1 & UTXIFG0) != UTXIFG0);
  TXBUF0 = out_char;
}
Mein einziges Problem ist jetzt nur noch das ich den Clock der UART0 
nicht ausgegeben bekomme. Es ist der PIN3.3 welcher auch mit 
initialisiert wurde (P3SEL |= 0x38;  P3DIR |= 0x18;) Aber das spielt 
jetzt kaum noch eine Rolle.

mfg
Stephan

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UART Clock gints ja auch nicht. Höchstens USART Clock, im SPI Modus. Im 
UART MOdus gibts nur TXD und RXD.

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so ok, ich hatte das so verstanden das man den Clock mit dem die 
Schnittstelle arbeitet, sprich den eingestellten ACLK, ausgeben kann. 
Aber jetzt versteh ich das!

THX
Stephan

Autor: Jens B. (meddle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
hab jetzt auch ein bißchen mit der seriellen Schnittstelle rumprobiert. 
Habe folgende Funktionen für Initialisierung und Aufruf: (MSP430F1611 - 
TXD0 auf PIN 3.4 RXD0 auf Pin 3.5)

void InitUSART0()
{
  UCTL0 = SWRST + CHAR + PENA;
  UTCTL0 |= SSEL_2;                     // SMCLK als UCLK festlegen

  //http://mspgcc.sourceforge.net/baudrate.html
  UBR00=0xA0; UBR10=0x01; UMCTL0=0x00; /* uart0 8000000Hz 19198bps */


  ME1 |= UTXE0 + URXE0;   // enable UART0 RX&TX

  UCTL0 &= ~SWRST;

  P3DIR |= 0x10;
  P3SEL |= 0x30;

  IE1 |= UTXIE0+URXIE0;  //      2 -> TX- und RX-interrupt anschalten


}

void SendUSART0c(char c)             // ein einzelnes zeichen über die serielle schnittstelle (USART0) senden
                                     // FJG: Obacht: x12xx : IFG1 => IFG2 !
{
  while (!(IFG1 & UTXIFG0));           // warten, bis USART0 TX-buffer sendebereit
  TXBUF0 = c;
}


Die Interrupts wurden nach der Initialisierung mit _EINT(); aktiviert. 
Problem ist nun, dass der in der Send-Funktion in der While-Schleife 
hängenbleibt. Wenn ich die while-Schleife testweise weglasse, 
funktioniert es, das gesendete Zeichen kommt im Terminal an. Aber das 
klappt vielleicht bei einzelnen zeichen, aber wenn ich strings senden 
will, sollte man ja schon schauen, ob die Schnittstelle sendebereit ist. 
SMCLK ist 8Mhz, Baudrate 19200. Warum wird das TX-Flag nicht gesetzt und 
das Programm hängt damit in der While-Schleife?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UTXIE Bit setzen und dann keine ISR für USART0_TX...das kann nicht 
klappen. Je nach Compiler wird dann wenigstens ein RETI in die Interrupt 
Vector Tabelle eingetragen, allerdings wird eben dann das TF-Flag eben 
sofort gelöscht.

Autor: Jens B. (meddle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn ich diese Zeile weglasse, funktioniert es immernoch nicht.
IE1 |= UTXIE0+URXIE0;  //      2 -> TX- und RX-interrupt anschalten

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while (!(IFG1 & UTXIFG0));   // warten, bis USART0 TX-buffer sendebereit
UTXIFG0 ist 1 wenn der Buffer FREI ist. D.h. das "!" muss weg.

Autor: Jens B. (meddle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while(1) bleibt ja in der Schleife, aber der soll ja raus, wenn 
sendebereit. also while(!1). das müsste doch richtig sein

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Öhh, ja, ist richtig, war wohl zu früh am morgen :)

Was steht denn im IFG1 Register wenn du bei der while Schleife stehen 
bleibst?

Autor: Jens B. (meddle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da steht ne glatte "0"

Autor: Jens B. (meddle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach mist, da war vom vielen ausprobieren eine zeile, die da nicht 
hingehörte. jetzt scheint das was supachris sagte zu stimmen. IE1 raus 
und es funktioniert.

besten Dank.

Ist es eigentlich richtig so, dass ich meine Probleme an die schon 
bestehenden Threads zu bestimmten Themen hänge oder lieber einen neuen 
aufmachen? Denke, so ist es übersichtlicher

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist auch logisch. Wenn es der GCC ist, wird in die Stelle für den USART 
0 TX in die Vektor Tabelle ein RETI eingetragen (bzw. die Adresse des 
unexpected ISR handlers). Tritt nun der Interrupt ein (also Senden 
beendet), dann wird vor dem Einsprung in die ISR das Flag schon wieder 
gelöscht, weil es ein Single-Source Interrupt ist. Da die ISR nur den 
Rücksprungbefehl enthält, landest du gleich wieder im richtigen 
Programm, aber das Flag ist nie gesetzt.

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.