Forum: Mikrocontroller und Digitale Elektronik Problem bei UART einlesen


von A. R. (and)


Lesenswert?

Hallo,

ich empfange aktuell über die serielle Schnittstelle Werte.
Wenn ich das Programm so schreibe, das der Programmdurchlauf blockiert 
wird vom Lesebefehl, d.h. ich warte bis neue Daten empfangen wurde, dann 
funktioniert alles.

Verwende ich aber jetzt den Befehl das ich nur die Daten einlese wenn 
neue Daten vorhanden sind:
1
if ( (UCSR0A & (1<<RXC0)) ){
2
   ......

Empfange ich die Werte nicht mehr korrekt. Woran kann das liegen?

von Georg G. (df2au)


Lesenswert?

Syntaxfehler in Zeile 42 von main()

von Cyblord -. (cyblord)


Lesenswert?

A. R. schrieb:
> Hallo,
>
> ich empfange aktuell über die serielle Schnittstelle Werte.
> Wenn ich das Programm so schreibe, das der Programmdurchlauf blockiert
> wird vom Lesebefehl,
Zeig mal DEN Code. Inwiefern unterscheidet sich das blockieren vom 
aktuellen Ansatz? Die Abfrage sollte gleich bleiben. Lediglich eine 
while Schleife sollte hinzugekommen sein.

Und poste mal den ganzen Code.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Verwende ich aber jetzt den Befehl das ich nur die Daten einlese wenn
>neue Daten vorhanden sind

Warum nicht einfach den RX Complete-Interrupt benutzen?

MfG Spess

von A. R. (and)


Lesenswert?

Hier das Programm in kurzer zusammenfassung:

Das funktioniert:
1
int main(void){
2
3
  uart_init();
4
5
while(1){
6
....
7
  a = uart_empfange();  //Low-byte
8
  b = uart_empfange();  //High-byte
9
  c = a+ (b<<8);
10
  ... 
11
  itoa(c,buffer,10);
12
  lcd_string(buffer);
13
  ....
14
 }
15
}



Das funktioniert nicht:
1
int main(void){
2
3
  uart_init();
4
5
while(1){
6
....
7
if ( (UCSR0A & (1<<RXC0)) ){
8
  a = uart_empfange();  //Low-byte
9
  b = uart_empfange();  //High-byte
10
  c = a+ (b<<8);
11
   
12
  ... 
13
  itoa(c,buffer,10);
14
  lcd_string(buffer);
15
  ....
16
  }
17
 }
18
}

: Bearbeitet durch User
von A. R. (and)


Lesenswert?

Habe mit Interrupt noch nie gearbeitet, da ich noch nicht so erfahren 
bin.
Hast du ein Beispiel, bzw. eine gute Anleitung dafür?

von spess53 (Gast)


Lesenswert?

HI

>Hast du ein Beispiel, bzw. eine gute Anleitung dafür?

Ich benutze Assembler. Ein Beispiel in C gibt es hier:

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Empfangen_.28RX.29

MfG Spess

von A. R. (and)


Lesenswert?

Ok danke schonmal für eure Hilfen.
Werde mich mit dem Interrupt mal beschäftigen.

Jetzt wäre aber zum Verständnis meine Frage:
Warum bekomm ich die Daten denn falsch rein wenn ich diese Abfrage mit 
drin habe? Ist das ein Timing Problem? Und warum sollte das beim 
Interrupt anders sein?

von Flip B. (frickelfreak)


Lesenswert?

A. R. schrieb:
> a = uart_empfange();  //Low-byte
>   b = uart_empfange();

weil nur dann daten gelesen werden, wenn sie zufällig im richtigen 
moment eintreffen. ansonsten tut uart_empfange nichts. du musst also 
solange  uart_empfange anspringen, bis deine 2 bytes empfangen wurden. 
dann am ende die berechnung ausführen.

von Georg (Gast)


Lesenswert?

Flip B. schrieb:
> uart_empfange anspringen, bis deine 2 bytes empfangen wurden.

Die können aber genausogut in falscher Reihenfolge gelesen werden, b vor 
a. Da fehlt jede Synchronisation. Beim blocckierenden Lesen auch, aber 
da fällt das weniger auf, wenn der Sender nach dem Empfänger startet.

Georg

von Georg G. (df2au)


Lesenswert?

Wie sieht uart_empfange() aus?

von Georg (Gast)


Lesenswert?

A. R. schrieb:
> if ( (UCSR0A & (1<<RXC0)) ){
>   a = uart_empfange();  //Low-byte
>   b = uart_empfange();  //High-byte

Die if-Bedingung heisst nur, dass 1 Byte empfangen wurde - nicht beide.

Georg

von A. R. (and)


Lesenswert?

Wenn ich die IF bedinungen nutze,
dann springt er rein wartet aber auf neue Werte im Puffer, wenn ich 
erneut werte sende, also seriell an den µC, dann liest er den letzten 
Wert ein und der Rest ist irgenndetwas komisches. Und danach springt er 
immer in die IF rein weil immer irgendwas im Puffer steht.

1
uint8_t uart_empfange (void){
2
  while (!(UCSR0A & (1<<RXC0)));
3
  return UDR0;
4
}

von Eric B. (beric)


Lesenswert?

so was?
1
state = EMPFANGE_A;
2
while(1)
3
{
4
  // check UART
5
  if (UCSR0A & (1<<RXC0))
6
  {
7
    if (state == EMPFANGE_A)
8
    {
9
      a = UDR0;
10
      state = EMPFANGE_B;
11
    } else if (state == EMPFANGE_B) {
12
      b = UDR0;
13
14
      // Tue was mit a und b
15
16
      state = EMPFANGE_A;
17
    }  else {
18
      error(WRONG_STATE);
19
      state = EMPFANGE_A;
20
    }
21
  }
22
23
  //
24
  // do other stuff here
25
  //
26
}

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Eric B. schrieb:
> a = UDR0;
>       state = EMPFANGE_B;

Da bist du auf der richtigen Spur, aber woher weisst du was a und was b 
ist?

Ich sehe da 2 Möglichkeiten:

1. Das MSB entscheidet, 0=a, 1=b. Aber dann bleiben bloss 14 Bit an 
Daten.

2. Nach a und b kommt eine deutlich längere Pause als dazwischen. Aber 
dann musst du diese Zeit messen und auswerten, du brauchst also 
mindestens ein Timeout, das zwischen a,b und a,b anspricht.

Georg

von A. R. (and)


Lesenswert?

Also di funktion das ich zweimal den uart lese und anschließend 
High-Low-Byte zusammen setzte funktioniert ja an sich.

Was mich gerade etwas irretiert oder noch unklar ist, warum funktioniert 
das uart_empfange(); nicht mehr wenn ich es nur dann mache, wenn neue 
Daten im Eingangspuffer steht?

Georg schrieb ja, das die If-Anweisung ja nur aussgat, das 1-byte 
vorhanden ist. Und ich frage erst dann ab. D.h. ich lese ja wenn ich 
zweimal Byte ein, wenn aber jetzt nur noch ein Byte vorhanden ist wartet 
das Program ja. und beim nächsten senden von zwei Byte erhält läuft das 
Programm weiter und springt im nächsten durchlauf direkt wieder in die 
IF-Anweisung.

Bedeuted doch eigentlich, das durch die IF-Anweisung mir vermutlich das 
erste Byte verloren geht oder?

von Eric B. (beric)


Lesenswert?

Georg schrieb:
> Da bist du auf der richtigen Spur, aber woher weisst du was a und was b
> ist?

Ist mir schon klar. Das Problem bin ich auch gar nicht angegangen.

A. R. schrieb:
> Was mich gerade etwas irretiert oder noch unklar ist, warum funktioniert
> das uart_empfange(); nicht mehr wenn ich es nur dann mache, wenn neue
> Daten im Eingangspuffer steht?

Das können wir nur beantworten wenn du den Code von /uart_empfange/() 
zeigst.

von A. R. (and)


Lesenswert?

Hatte ich oben schon gepostet:
1
uint8_t uart_empfange (void){
2
  while (!(UCSR0A & (1<<RXC0)));
3
  return UDR0;
4
}

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.