mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 Problem mit UART Empfang


Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin gerade dabei eine Kommunikation zwischen PC und MSP über RS232 
zu erstellen. Ich möchte im Hyperterminal eine Taste drücken und das 
entsprechende Zeichen dann auf dem Display ausgeben. Leider bekomme ich 
das nicht so ganz hin.

Wenn ich das ganze wie folgt mache, funktioniert es:

#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx (void)
{
    LCDOutc(RXBUF0);
}

Das entsprechende zeichen wird dann auf dem Display ausgegeben. Ich 
würde nun aber gerne das empfangene Zeichen in einer Variablen speichern 
und dann später ausgeben.

void main(void)
{
  ...
 for(;;)
  {
    ThirdLine();             // In die dritte Zeile des Displays 
springen
    SpaceOut(7);                 // Leerzeichen auf dem Display ausgeben
    //LCDOutc(temp_str);           // Temperatur auf Display ausgeben
    LCDOutc(temp);
    LCDOuts("°C");               // Grad Zeichen auf Display ausgeben
  }/* for(;;) */
}/* void main(void) */

#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx (void)
{
    temp= RXBUF0;
}

Leider funktioniert das nicht. Kann mir jemand sagen, wie ich das 
umsetzen kann?

Ich wollte auch schon einen ganzen String emspangen und dann in einer 
Variablen speichern:

char temp_str[]="0000";
temp_str= RXBUF0;

Aber da wird schon beim copilen gemeckert. Jemand eine Idee, was ich da 
falsch mache?

Vielen Dank.

Gruß
Uwe

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Leider funktioniert das nicht. Kann mir jemand sagen, wie ich das
> umsetzen kann?

Zunächst mal solltest du uns mal sagen, was du unter
'funktioniert nicht' verstehst.

> char temp_str[]="0000";
> temp_str= RXBUF0;
>
> Aber da wird schon beim copilen gemeckert.

Wieder. Der Compiler gibt die Fehlermeldung nicht nur
zum Spass aus.

Aber in dem Fall ist alles klar.
temp_str ist ein Array. RXBUF0 ist nur ein einzelner
popeliger char. Einem Array kann man aber keinen char
zuweisen. Einem Array als ganzes kann man überhaupt
nichts zuweisen. Wohl aber einem Element des Arrays:

   temp_str[0] = RXBUF0;


Bitte besorge die C-Literatur. Deine Fragen sind in
der Kategorie: In jedem noch so billigen C-Buch ausreichend
genau erklärt.

Autor: Alain (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo.
versuch mal eine abfrage mit einer While schleife in dein for(;;) 
schleife zu setzen. in der While schliefe fragst du immer ab ob ein neue 
zeichen ankommt, wenn ja dann soll er das auf dein temp[i] speichern 
dann i incrementieren und weiter nächste zeichen.

Autor: Uwe (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe das ganze nun ein wenig umgeschrieben. Funktioniert nun schon 
ganz gut. Ich würde nun noch gerne eine Sache ändern. Die Ausgabe der 
empfangenen Zeichen steht in der Interrupt routine (siehe Code). Ich 
würde das nun so realisieren, dass ich das Auslesen und speichern der 
empfangenen Zeichen in der Interrupt routine habe aber die 
Zeichenausgabe in der "main".

Wie gesagt, so wie ich es jetzt habe, funktioniert es, würde das gerne 
aber noch ändern, wenns geht.

Gruß
Uwe

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ziemlich einfach. Mach eine globale Variable, die du beim 
String-Ende in der ISR setzt. in der Main-Schleife fragst du die ab, 
wenn sie gesetzt ist, dann Ausgabe des Strings und löschen der Variable.

Übrigens musst du nicht sinnlos auf das RX-Flag der UART warten, die ISR 
wird doch ausgelöst, wenn was kommt. Also die While-Schliefe da is bissl 
sinnlos.

Zwischendurch kannst du den MSP auch schlafen schicken, der LPM0 
schaltet die CPU ab, alle Peripheriekomponenten bleiben an.

Da musst du aber dann beachten, dass du in der ISR am Ende den MSP 
aufweckst.

Autor: Alain (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
einfachen interrupt abfrage in MAIN setzen: so zum beispiel.
for(;;)
{
blabla
.
.
> if ((IFG2 & URXIFG1)) // warte auf neues zeichen. wenn ja dann in Receive
  speichern. diese Receive in dein temp[i] nochmal speichern.
>    {
>      Receive = RXBUF1;
>     }
.
.
...blabla
}

hoffe das hilft dann.

Autor: Alain (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und noch was, du brauchst dann dein Pragma nicht mehr.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So einen Pollig-Mist sollte man in der µC-Welt tunlichst schnell 
vergessen und die ganze Sache sauber interruptgesteuert bauen. Zumal 
dann die Stromsparmechanismen völlig für den Popo sind.

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe die abfrage nun in die main gepackt wie oben angegeben. Das 
funktioniert.

Vielen Dank.

Gruß
Uwe

Autor: Alain (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi UWE.
wie hast du es gemacht?

Autor: Uwe (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

im Anhang mal mein Code, zumindest einen Teil davon.

@ Christian R.:

Das habe ich ja versucht, aber leider nicht hin bekommen. Wenn du weißt 
wie es geht oder was ich in meinem Code, den ich weiter oben schon 
einmal gepostet habe, noch ändern muss oder falsch mache, würde ich mich 
freuen, wenn du mir da weiter helfen könntest.
Das die jetzige Lösung nicht sooo super ist, weiß ich selbst, weil das 
nämlich schöner "Blocking-Code" ist. Wie gesagt, das mit den INterrupts 
hab ich nciht hin bekommen, bin aber für jede Hilfe dankbar.

Grüße
Uwe

Autor: Alain (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also doch wie ich dir gesagt habe. :)
> if ((IFG2 & URXIFG1))

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klar, so läufts auch!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das habe ich ja versucht, aber leider nicht hin bekommen. Wenn du weißt
> wie es geht oder was ich in meinem Code, den ich weiter oben schon
> einmal gepostet habe, noch ändern muss oder falsch mache, würde ich mich
> freuen, wenn du mir da weiter helfen könntest.

Wie Christian schon sagte:
Du benutzt eine globale Variable, die dem Hauptprogramm anzeigt,
dass eine komplette Eingabezeile empfangen wurde.
Im Interrupt empfängst du also zeichen:
Wenn es kein 0x0D ist, dann wird das Zeichen im
(ebenfalls) globalen Empfangsbuffer zwischengespeichert.
Wenn es ein 0x0D war, dann wird diese zusätzliche Variable
auf irgendeinen Werte gesetzt, der dem Hauptprogramm
ermöglicht zu erkennen, dass jetzt im Buffer eine
komplette Zeile vorliegt. Nachdem das Hauptprogramm
die Zeichen in diesem Buffer nicht mehr braucht, setzt
es diese Variable wieder zurück und erlaubt so der
Interrupt Funktion die nächste Zeile in diesem Buffer
zusammenzusetzen.

...

char tmp_str[40];
unsigned char NextStr;
volatile unsigned char StringReady;

#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx (void)
{
  if( StringReady == 1 )
  {
    /* Der vorher empfangene String wurde
       noch nicht verarbeitet
       Für den Fall musst du dir noch was einfallen lassen:
       Fehler LED setzen oder was auch immer.
    */
  }

  else
  {
                     
    if(RXBUF0 == 0x0D)
    {
      temp_str[NextStr] = '\0';
      StringReady = 1;
      NextStr = 0;
    }
    else
    {
      temp_str[NextStr++] = RXBUF0;     // Ankommendes Zeichen speichern
    }
  }
}

int main()
{
  ....

  StringReady = 0;
  NextStr = 0;


  /* Initialisierung fortsetzen und UART freigeben */

  ...

  for( ;; )
  {
    if( StringReady == 1 )
    {
      ThirdLine();
      SpaceOut( 7 );
      LCDOuts( temp_str );

      StringReady = 0;     /* wichtig: Das ist das Signal für die
                              Interrupt Routine, dass der String
                              abgeholt wurde, und dass wieder Zeichen
                              in temp_str abgelegt werden können.
                              Das können wir hier machen, weil der
                              Inhalt von temp_str schon bearbeitet
                              wurde und in Folge nicht mehr gebraucht
                              wird.
                           */
      LCDOuts( "°C" );
    }
  }
}


  

Autor: Christian R. (supachris)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Naja, musst den Interrupt für die UART freigeben, wie das geht, steht ja 
in den C-Demos.

Ich hab mal was geschrieben. Sollte klappen, wenn der UARTRX Int 
eingeschaltet ist.

Sowas klappt bei mir problemlos mit vielen verschiedenen Flags und auf 2 
USART Schnittstellen. ich muss mit jedem µA geizen, da ist das sehr 
hilfreich.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, der Meister war wieder schneller ;)

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen Dank. So funktioniert es!


Grüße
Uwe

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian R. wrote:
> Oh, der Meister war wieder schneller ;)

Dafür hast du ein vollständiges Progaramm gebaut
und die CPU zwischendurch auch noch schlafen gelegt.

Allerdings hast du vergessen, den Buffer im Interrupt
mit einem '\0' zu terminieren :-)


Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An die Null hab ich nicht gedacht, stimmt.

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.