www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interruptbehandlung MSP430


Autor: Daniel S. (nasenschleim)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);
}

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
_BIS_SR(LPM0_bits + GIE);               // in den LPM0 wechseln
durch
_BIS_SR(GIE);
ersetzt, geht's nicht mehr?

Autor: Daniel S. (nasenschleim)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/Formatieru...

> 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!

Autor: Daniel S. (nasenschleim)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, vielen Dank.
Hat mir sehr geholfen.
Es sind halt immer die Kleinigkeiten die man vergisst.

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.