Hallo, ich bin noch ziemlich neu auf dem Gebiet "uC" und habe mich jetzt mal mit dem MSP430f169 auseinander gesetzt. Die TI-Beispiele habe ich mir auch schon angeschaut. Kurz gesagt geht es darum über USART1 etwas über USB zu empfangen (benutze dazu den CP2103 (USB-Seriell-Chip)) und dadurch den uC zu steuern. Zum Beispiel eine Messung mit ein oder zwei Sensoren anzustoßen. Die Messwerte sollen anschließend über die USART Schnittstelle zum PC transferiert werden. Im einzelnen funktioniert die Kommunikation... Nun wollte ich die Kommunikation Interruptgesteuert ausführen. Also wenn der PC einen Befehl an den uC schickt, soll dieser in die ISR wechseln und erstmal die ankommenden Daten aufnehmen. Dies klappt aber nur wenn ich den uC in den LP Modus setze (als Beispiel LPM0), dann nimmt er die Daten, welche gesendet werden auf und verarbeitet diese durch einer Switch-Case Anweisung. Meine Frage warum, funktioniert dies nur in einem LPM Mode und nicht ganz normal aus dem Mainprogramm heraus. Ich dachte mir das er auch in die ISR springen kann, wenn er zum Beispiel gerade die Analogauswertung bearbeitet!? Ich hoffe ihr könnt mir bei meinem Problem weiterhelfen. Schon mal danke. Hier mal noch der C-Code: // MSP430 Programm #include "msp430f169.h" char string1[8]; char Auswahl; char test,Ende1; int j,i; int a=0; void delay(unsigned int a); // Wartezeitfunktion initialisiert void main(void) { // Allgemeine Einstellung WDTCTL = WDTPW + WDTHOLD; // WatchDogTimer anhalten // Einstellung ADC P6SEL |= 0x01; // Pin 6.0 mit AD Funktion nutzen ADC12CTL0 = ADC12ON+SHT0_8+REFON+MSC; // ADC12 einschalten ADC12CTL1 = SHP+CONSEQ_2; ADC12MCTL0 = SREF_1+INCH_0; // Referenzspgquelle zugewiesen + Daten in ADC12MEM0 schreiben ADC12IE = 0x01; // Interrupt einschalten für ADC 0 ADC12CTL0 |= ENC; // ADC Konfiguration abgeschlossen // Einstellung USART1 P3SEL |= 0xC0; // Port P3.6,7 = USART1 ME2 |= UTXE1 + URXE1; // Einschalten USART1 Modul UCTL1 |= CHAR; // USART 8Bit (Char) UTCTL1 |= SSEL0; // UCLK = ACLK UBR01 = 0x03; // 32k/9600 - 3.41 UBR11 = 0x00; // UBR11 = Baud Rate 1 //UMCTL1 = 0x4A; // Modulation Control (Korrektur der Baudratendivision) UMCTL1 = 0x49; // Verbesserung der Korrektur bei 9600 Baud UCTL1 &= ~SWRST; // SRST = USART Software Reset IE2 |= UTXIE1; // Enable USART1 TX-Interrupt IE2 |= URXIE1; // Enable USART1 RX-Interrupt IFG2 &= ~UTXIFG1; // initales interrupt-flag loeschen IFG2 &= ~URXIFG1; // initales interrupt-flag loeschen P4DIR = 0xFF; // Port 4 als Output (LEDs) P4SEL = 0x00; // Ports als GPIO benutzen (=0) P4OUT = 0x00; // Initialisierung Port4 (Low=0) j=0; for(;;) // Main-loop (Endlosschleife) { _BIS_SR(LPM0_bits + GIE); // in den LPM0 wechseln /* // ADC_Konvertierung starten ADC12CTL0 |= ADC12SC; // Konvertierung starten // Umformen vom ADC12MEM0 und senden der Ergebnisse unsigned char Part1,Part2; Part1 = ADC12MEM0; Part2 = (ADC12MEM0 >> 8); while (!(IFG2 & UTXIFG1)); // warten, bis USART1 TX-Buffer sendebereit TXBUF1= Part2; while (!(IFG2 & UTXIFG1)); // warten, bis USART1 TX-Buffer sendebereit TXBUF1= Part1; while (!(IFG2 & UTXIFG1)); // warten, bis USART1 TX-Buffer sendebereit TXBUF1= '/'; // Zeichen 1von2 Uebermittlung Ende while (!(IFG2 & UTXIFG1)); // warten, bis USART1 TX-Buffer sendebereit TXBUF1= '0'; // Zeichen 2von2 Uebermittlung Ende // Wartefunktion noch durch Timer ersetzen delay(60000); // Wartefunktion */ // Empfangenen String vergleichen if ((string1[0] == 'S') && (string1[1] == 'E') && (string1[2] == 'N') && (string1[3] == '1')) { Auswahl = '1';} if ((string1[0] == 'S') && (string1[1] == 'E') && (string1[2] == 'N') && (string1[3] == '2')) { Auswahl = '2';} if ((string1[0] == '0') && (string1[1] == 'S') && (string1[2] == 'E') && (string1[3] == 'N')) { Auswahl = '0';} if ((string1[0] == '2') && (string1[1] == 'S') && (string1[2] == 'E') && (string1[3] == 'N')) { Auswahl = '3';} switch(Auswahl) { case '0': test='a'; break; case '1': test='b'; break; case '2': test='c'; break; case '3': test='d'; break; default: test='0'; break; } } } // Interruptbehandlung bei einkommenden Daten(RX) #pragma vector=USART1RX_VECTOR __interrupt void usart1_rx (void) { string1[j++] = RXBUF1; if (RXBUF1==92) {a=1;} if ((RXBUF1=='0') && (a)) {j=0; a=0;} _BIC_SR_IRQ(LPM0_bits); }
1.) Halte Dich an die Reihenfolge im User Guide: Note: Initializing or Re-Configuring the USART Module The required USART initialization/re-configuration process is: 1) Set SWRST (BIS.B #SWRST,&UxCTL) 2) Initialize all USART registers with SWRST = 1 (including UxCTL) 3) Enable USART module via the MEx SFRs (URXEx and/or UTXEx) 4) Clear SWRST via software (BIC.B #SWRST,&UxCTL) 5) Enable interrupts (optional) via the IEx SFRs (URXIEx and/or UTXIEx) Failure to follow this process may result in unpredictable USART behavior. 2.) Möglicherweise ärgert Dich folgender Bug: US14 USART0, USART1 Module Function Lost character start edge Description When using the USART in UART mode with UxBR0 = 0x03 and UxBR1 = 0x00, the start edge of received characters may be ignored due to internal timing conflicts within the UART state machine. This condition does not apply when UxBR0 > 0x03. Workaround None 3.) Setze Deinen Code in [ c ]...[ /c ]. (Leerzeichen weglassen!) Dann kann man's auch lesen ;-) 4.) Soll das heißen, Dein geposteter Code funktioniert und sobald Du
1 | _BIS_SR(LPM0_bits + GIE); // in den LPM0 wechseln |
durch
1 | _BIS_SR(GIE); |
ersetzt, geht's nicht mehr?
zu 3. was meinst du damit? Soll ich die Leerzeichen in den Anweisungen weglassen oder meinst du nur die vielen Freiräume zwischen Anweisung und Kommentar, welche hier durch den Zeilenumbruch schnell zu einem kleinen Chaos mutieren? zu 4. ja, der Code funktioniert soweit. Ich sehe die Änderung des Strings und der Variablen im DebugModus des CodeComposers. Er funktioniert nicht mehr wenn ich _BIS_SR(LPM0_bits + GIE); und _BIC_SR_IRQ(LPM0_bits); auskommentiere. (Ich war die ganze Zeit der Meinung, das ich die Interruptbehandlung durch die anfangs gemachten Einstellungen schon aktiviert hatte und somit die Sache dann von alleine läuft. Ich habe die ganze Zeit gedacht das ich durch die erste Anweisung in den LPM0, inklusive eingeschalteten Interrupt wechsle und durch die 2. Anweisung (_BIC_SR_IRQ(LPM0_bits);) nach einer ISR wieder in den LPM wechsle... Habe ebend mal nur die Anweisung (_BIS_SR(GIE);) probiert und es funzt, so wie ich es mir vorstelle. Also muß ich diese Anweisung verwenden um endgültig die Interruptbehandlung zu aktivieren? Noch mal sorry für die vermeintlich blöden Fragen...
Daniel S. schrieb: > zu 3. > > was meinst du damit? > Soll ich die Leerzeichen in den Anweisungen weglassen oder meinst du nur > die vielen Freiräume zwischen Anweisung und Kommentar, welche hier durch > den Zeilenumbruch schnell zu einem kleinen Chaos mutieren? Du sollst Deinen Code formatieren, so dass man ihn hier besser lesen kann: http://www.mikrocontroller.net/articles/Formatierung_im_Forum > zu 4. > Er funktioniert nicht mehr wenn ich > _BIS_SR(LPM0_bits + GIE); > und > _BIC_SR_IRQ(LPM0_bits); > auskommentiere. Die Antwort hast Du Dir ja selbst schon gegeben: > Habe ebend mal nur die Anweisung (_BIS_SR(GIE);) probiert und es funzt, > Also muß ich diese Anweisung verwenden um endgültig die > Interruptbehandlung zu aktivieren? Ja sicher, mit dem G(lobal) I(nterrupt) E(nable) gibst Du die einzelnen Interrupts überhaupt erst global frei!
Okay, vielen Dank. Hat mir sehr geholfen. Es sind halt immer die Kleinigkeiten die man vergisst.
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.