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
> 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?
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?
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.
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...
1 | >U1CTL &= ~BIT7 + BIT5; // no parity, 1 Stopbit |
aktiviert Parity, Listen-Mode und vorallem SPI ! Ich vermute mal, Du wolltest:
1 | U1CTL &= ~BIT7; |
2 | U1CTL |= BIT5; |
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
Bist du dir sicher das du dir das Senden mit Interrupt antuen willst? Senden würde ich "normal" machen.
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.
>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" ;-)
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...
Ä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
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!
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...
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?
1 | 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"
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?!
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 ;)
@ 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.
>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!
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!
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.
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(!)
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!
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 :-)
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... :-(
>Aber das eine Baudrate von 9600 beim internen Takt problematisch ist, >steht da nicht drin... :-( Weil das auch Quatsch ist !!! Es geht darum, dass
1 | UCA0BR0 = 0x03; // 32k/9600 - 3.41 |
2 | UCA0BR1 = 0x00; // |
3 | UCA0MCTL = 0x06; |
bei einem internen Takt ungleich 32kHz nicht passt!
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...
>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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.