Forum: Mikrocontroller und Digitale Elektronik MSP430 Problem mit UART Empfang


von Uwe (Gast)


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

von Karl H. (kbuchegg)


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.

von Alain (Gast)


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.

von Uwe (Gast)


Angehängte Dateien:

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

von Christian R. (supachris)


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.

von Alain (Gast)


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.

von Alain (Gast)


Lesenswert?

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

von Christian R. (supachris)


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.

von Uwe (Gast)


Lesenswert?

Hallo,

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

Vielen Dank.

Gruß
Uwe

von Alain (Gast)


Lesenswert?

hi UWE.
wie hast du es gemacht?

von Uwe (Gast)


Angehängte Dateien:

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

von Alain (Gast)


Lesenswert?

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

von Uwe (Gast)


Lesenswert?

Klar, so läufts auch!

von Karl heinz B. (kbucheg)


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.
1
...
2
3
char tmp_str[40];
4
unsigned char NextStr;
5
volatile unsigned char StringReady;
6
7
#pragma vector=UART0RX_VECTOR
8
__interrupt void usart0_rx (void)
9
{
10
  if( StringReady == 1 )
11
  {
12
    /* Der vorher empfangene String wurde
13
       noch nicht verarbeitet
14
       Für den Fall musst du dir noch was einfallen lassen:
15
       Fehler LED setzen oder was auch immer.
16
    */
17
  }
18
19
  else
20
  {
21
                     
22
    if(RXBUF0 == 0x0D)
23
    {
24
      temp_str[NextStr] = '\0';
25
      StringReady = 1;
26
      NextStr = 0;
27
    }
28
    else
29
    {
30
      temp_str[NextStr++] = RXBUF0;     // Ankommendes Zeichen speichern
31
    }
32
  }
33
}
34
35
int main()
36
{
37
  ....
38
39
  StringReady = 0;
40
  NextStr = 0;
41
42
43
  /* Initialisierung fortsetzen und UART freigeben */
44
45
  ...
46
47
  for( ;; )
48
  {
49
    if( StringReady == 1 )
50
    {
51
      ThirdLine();
52
      SpaceOut( 7 );
53
      LCDOuts( temp_str );
54
55
      StringReady = 0;     /* wichtig: Das ist das Signal für die
56
                              Interrupt Routine, dass der String
57
                              abgeholt wurde, und dass wieder Zeichen
58
                              in temp_str abgelegt werden können.
59
                              Das können wir hier machen, weil der
60
                              Inhalt von temp_str schon bearbeitet
61
                              wurde und in Folge nicht mehr gebraucht
62
                              wird.
63
                           */
64
      LCDOuts( "°C" );
65
    }
66
  }
67
}

  

von Christian R. (supachris)


Angehängte Dateien:

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.

von Christian R. (supachris)


Lesenswert?

Oh, der Meister war wieder schneller ;)

von Uwe (Gast)


Lesenswert?

Hallo,

vielen Dank. So funktioniert es!


Grüße
Uwe

von Karl heinz B. (kbucheg)


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 :-)


von Christian R. (supachris)


Lesenswert?

An die Null hab ich nicht gedacht, stimmt.

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
Noch kein Account? Hier anmelden.