mikrocontroller.net

Forum: Compiler & IDEs Welche Bedingung um UART RXC zurückzusetzen ?


Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe folgendes Problem. Ich emfpange per UART etwas und möchte die 
empfangenen Daten in ein Array speichern (siehe Code). jedoch hänge ich 
immer in der WHILE Schleife fest, in der geprüft wird ob der 
Empfang(RXC1 Flag) erfolgreich abgeschlossen ist.

Was ist die Bedingung dafür um das RXC1 Flag zurück zu setzen ?

Im Datenblatt steht folgendes:
the RXCn flag can be used to check that there are no unread data in the 
receive buffer.

Aber ich lese die Daten doch mit der FOR-Schleife aus, also sind die 
Daten nicht ungelesen?!
uint8_t diag_data[7];

uint8_t Receive_Byte()
{
  while (!(UCSR1A & (1 << RXC1)))
  ;
  return UDR1; //Zeichen aus UDR zurueckgeben
}

for(int u=0 ; u<7 ; u++)
{
   diag_data[u] = Receive_Byte(); //nächstes Byte empfangen
}

Autor: hdd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das RXC-Flag wird gesetzt, wenn die Daten vollständig in UDR stehen und 
wieder gelöscht wenn du diese Daten gelesen hast. Allerdings wartest du 
in der While-Schleife darauf, dass das Flag gelöscht ist und das 
Auslesen der Daten würde ja erst passieren, wenn du die Schleife 
verlässt.
Du solltest lieber warten, solange es nicht gesetzt ist und wenn es dann 
gesetzt wurde, auslesen.

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb im Beitrag #1883497:
> Es gibt ein perfektes Bit, welches anzeigt ob im UART ein Zeichen
> empfangen wurde oder nicht und welches durch Auslesen aus UDR gelöscht
> wird.

Aha und wie heißt dieses, mir noch unbekannte, Zauberbit ? :-)

Hab keine Zeit mich jetzt komplett durch die UART Seiten durchzuwühlen!

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

Bewertung
0 lesenswert
nicht lesenswert
Ich hab den Post zurückgezogen.
Man sollte nicht unter Zeitdruck antworten.
Du hast schon das richtige Bit.

Zeig mal mehr Code, insbesondere die Initialisierung der UART

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Karl,

habe mich auch schon gewundert, da ich mir die UART Teile schon ziemlich 
gut angeschaut habe ;)

Hier noch die UART_Init.
Also der Empfang mit UART ISR geht, Senden tu ich NICHT mit ISR.

Nachdem ich über UART eine Anfrage versende, erwarte ich die Nachrichten 
die ich bis jetzt noch nicht mit der ISR verarbeiten kann. Als Antwort 
kommen zwischen 1-3 Nachrichten zurück mit je 8Byte größe. Jede dieser 
1-3 Nachrichten landet in der FOR-Schleife.... kann das Problem damit 
zusammen hängen ?

void USART_Init()
{
  BAUD_Init(NORMB);  // Baudrate setzen

  // Receiver und Transmitter einschalten UND Receive Interrupts einschalten
  UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);

  //Frameformat setzen: Asynchron 8 Daten, Keine Parität 1 Stop bit (8N1)
  UCSR1C = (1 << UCSZ11) | (1 << UCSZ10);
}

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

Bewertung
0 lesenswert
nicht lesenswert
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
                                       *************

Wenn du keinen Interrupt Handler hast, darfst du ihn auch nicht 
freigeben! Wenn du aber einen Interrupt Handler hast, dann musst du den 
kompletten Empfang über Interrupts abwickeln. Pollen des RXC Flags ist 
dann nicht mehr

(Ich wusste doch, das ich im Eröffnungsposting irgendwas von Interrupt 
gelesen hatte)

Zeig mal alles!

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum habe ich keinen ISR Handler ?
Also hier mal die ISR_RX...
Das Erste Datenbyte kann ich auswerten (0x5D) was mit "Byte = 
Receive_Byte();" ausgelesen wird... aber an den weiteren Bytes scheiter 
ich.
uint8_t Receive_Byte()
{
  while (!(UCSR1A & (1 << RXC1)))
  // warten bis Zeichen verfuegbar
    ;
  return UDR1; //Zeichen aus UDR zurueckgeben
}


ISR(USART1_RX_vect)
{  
  uint8_t diag_data[7];
  Byte = Receive_Byte();

  if(Byte == 0x5D)  //1. Datenbyte
  {    
    for(int u=0 ; u<7 ; u++)
    {
      diag_data[u] = Receive_Byte(); //nächsten 7 Datenbytes empfangen
    }
  }
  else
    .....
}

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

Bewertung
0 lesenswert
nicht lesenswert
Andi schrieb:
> Warum habe ich keinen ISR Handler ?

Weil du ihn noch nicht hergezeigt hast?


> [c]
> uint8_t Receive_Byte()
> {
>   while (!(UCSR1A & (1 << RXC1)))
>   // warten bis Zeichen verfuegbar
>     ;
>   return UDR1; //Zeichen aus UDR zurueckgeben
> }
>
>
> ISR(USART1_RX_vect)
> {
>   uint8_t diag_data[7];
>   Byte = Receive_Byte();

Das ist Unsinn.
Du bist in der ISR weil ein Byte empfangen wurde. Du brauchst hier 
nicht mehr abfragen, ob ein Byte empfangen wurde bzw. darauf warten. Wir 
wissen, das eines empfangen wurde, sonst wäre die ISR nicht aufgerufen 
worden.

>
>   if(Byte == 0x5D)  //1. Datenbyte
>   {
>     for(int u=0 ; u<7 ; u++)
>     {
>       diag_data[u] = Receive_Byte(); //nächsten 7 Datenbytes empfangen
>     }

das geht nicht.
Du bist in der ISR

In der ISR holst du dir das empfangene Zeichen und speicherst es weg. 
Danach gehts wieder raus aus der ISR. Sobald das nächste Zeichen 
empfangen wird, wird die ISR erneut aufgerufen.

Du musst weg vom Denken in Schleifen und hin zum Denken in Ereignissen: 
Jetzt ist das Ereignis 'Zeichen empfangen' eingetreten. Was mach ich mit 
dem Zeichen?
Und warten in einer ISR geht gar nicht.

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt kommt auch bei mir das Licht an :-)
Bin erst seit paar Wochen in der Thematik... daher diese Fragen!

Ok, werde es mal kurz umschreiben und das Erg. posten !

THX schonmal im vorus !!

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaub ich steh grad etwas auf dem Schlauch.... also in UDR wird 
immer nur EIN Byte von meiner 8Byte großen Nachricht gespeichert.
Das muss ich jetzt Zwischenspeichern und sobald das nächste Byte kommt, 
wird die ISR erneut aufgerufen in der ich das Byte zwischenspeichern 
muss...u.s.w.
.... Ich bekomm grad nix mehr hin!

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

Bewertung
0 lesenswert
nicht lesenswert
Andi schrieb:
> Ich glaub ich steh grad etwas auf dem Schlauch.... also in UDR wird
> immer nur EIN Byte von meiner 8Byte großen Nachricht gespeichert.
> Das muss ich jetzt Zwischenspeichern und sobald das nächste Byte kommt,
> wird die ISR erneut aufgerufen in der ich das Byte zwischenspeichern
> muss...u.s.w.

Ganz genau


volatile uint8_t bytesReceived;
volatile uint8_t diag_data[7];

ISR(USART1_RX_vect)
{  
  uint8_t nextByte = UDR1;

  if( bytesReceived == 0 ) {    // warten wir auf das Startbyte?
    if( nextByte == 0x5D )
      bytesReceived = 1;        // die restlichen Bytes sind Daten
  }

  else {
    if( bytesReceived <= 7 ) {
      diag_data[ bytesReceived - 1 ] = nextByte;
      bytesReceived++;
    }
  }
}

Wenn bytesReceived den Wert 8 erreicht hat, sind alle Bytes da. In der 
Hauptschleife die Daten auswerten und bytesReceived zum Schluss wieder 
auf 0 setzen.

....


int main()
{
  ....

  while( 1 ) {

    ...
    if( bytesReceived == 8 ) {
      // mach was mit diag_data
      bytesReceived = 0;
    }

    ...
  }
}

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl,

habe es im Detail so übernommen und es läuft... muss jetzt das drumherum 
noch bisschen anpassen, da ich nicht nur Nachrichten bekomme die mit 
0x5D anfangen!

Top Sache, hast mir echt geholfen !!

Gruß & Danke
Andi

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.