www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mehrere Bytes über UART empfangen


Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein vllt ganz triviales Problem. Ich bekomme seriell Daten 
(9600)von einem PC auf einen Mega16 (8MHz). Das Problem ist jetzt, dass 
ich nur das erste Byte mitbekomme. Danach empfange ich nur noch Nullen. 
Kann es sein dass der MC zu langsam ist? Die ISR wird ja auch erst 
aufgrufen wenn Daten im Puffer sind oder? Dann kommen je bereits die 
nächsten an, während ich noch die ersten verabreiten will? Stimmt das so 
weit und wie kann man das lösen?


Vielen Dank schon mal
Florian

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du bei 9600 Baud einen Buffer-Overflow kriegst, dann stimmt mit 
großer Wahrscheinlichkeit in Deinem Programm etwas fundamentales nicht. 
Da Du uns den Programmcode aber nicht zeigst, kann man da auch nicht 
viel zu sagen!

Bei 9600 Baud dauert die Übertragung eines Zeichens ungefähr 1 ms. Das 
ist für einen µC ne halbe Ewigkeit, wenn man nicht gerade innerhalb der 
ISR mit sperrigen Bibliotheksfunktionen arbeitet, was man generell nicht 
tun sollte. Einen Buffer-Overflow kann man übrigens detektieren, dafür 
gibts ein extra Flag...

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenigstens den Inhalt der ISR könntest du mal Posten.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich habe ein vllt

Ein was?

> Ich bekomme seriell Daten (9600)von einem PC auf einen Mega16 (8MHz).
> Das Problem ist jetzt, dass ich nur das erste Byte mitbekomme. Danach
> empfange ich nur noch Nullen. Kann es sein dass der MC zu langsam ist?

Eher nicht. Bei 9600 Baud und 8 Mhz hat dein AVR pro Byte über 8000 
Taktzyklen zur Verfügung.

> Die ISR wird ja auch erst aufgrufen wenn Daten im Puffer sind oder?

Ja.

> Dann kommen je bereits die nächsten an, während ich noch die ersten
> verabreiten will?

Ja, aber das macht nichts, da die Schnittstelle double buffering 
verwendet. Die beiden Puffer werden nicht getauscht, solange du nicht 
gelesen hast.

> Stimmt das so weit und wie kann man das lösen?

Keine Ahnung. Du hast ja nicht gezeigt, wie du es machst.

Autor: Nicht Bekannt (florian01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal allen. Hier mein Programm:
#include <avr/io.h>
#include <avr/interrupt.h>


#define SYSCLK    8000000
#define BAUD    9600UL
#define UBRR_BAUD  ((SYSCLK/(16*BAUD))-1)

void uart_init(void);

uint8_t BYTE0 = 0;
uint8_t BYTE1 = 0;


int main(){

  uart_init();
  sei();
  

  while(1){

    if(BYTE1 != 0){
      while ( !( UCSRA & (1<<UDRE)) );                    
      UDR = BYTE0;
      while ( !( UCSRA & (1<<UDRE)) );                    
      UDR = BYTE1;

      BYTE0 = 0;
      BYTE1 = 0;
    }                                

  }  

return 0;
}


void uart_init(void)
{
 
  UBRRH = (unsigned char) (UBRR_BAUD>>8);                  
  UBRRL = (unsigned char) UBRR_BAUD;

  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);                  
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);                
}




ISR(USART_RXC_vect)                          
{  
  uint8_t tmp_sreg = SREG;                                                      

  cli(); 
                                          
  if (BYTE0 == 0){
    BYTE0 = UDR;
  } else {
    BYTE1 = UDR;
  }

  SREG = tmp_sreg;                               
}

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

Bewertung
0 lesenswert
nicht lesenswert
Nicht Bekannt wrote:
> Danke erstmal allen. Hier mein Programm:

> ISR(USART_RXC_vect)
> {
>   uint8_t tmp_sreg = SREG;
>
>   cli();
>
>   if (BYTE0 == 0){
>     BYTE0 = UDR;
>   } else {
>     BYTE1 = UDR;
>   }
>
>   SREG = tmp_sreg;
> }


Lass das SREG in Ruhe. Du programmierst in C und musst dich
nicht mit so niedrigen Dingen wie den tatsächlichen CPU
Registern herumschlagen.
Auch der cli() ist unnötig. Wenn eine ISR betreten wird, dann
werden die Interrupts von Haus aus disabled und beim verlassen
der ISR wieder angeschaltet.

Mach mal die beiden Variablen BYTE1 und BYTE0 als volatile
Variablen:

volatile uint8_t BYTE0 = 0;
volatile uint8_t BYTE1 = 0;

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das cli() und das SREG-Sichern in der ISR übernimmt der Compiler(*). Das 
solltest Du weglassen.

Abgesehen davon solltest Du mal überlegen, wie das mit senden und 
empfangen läuft und v.a. dran denken, was passiert, wenn gerade nach dem 
Ende des Sendens die ISR aufgerufen wird und nach dem Rücksprung beide 
BYTEs auf 0 gesetzt werden...

(*)Das cli() macht genaugenommen die Hardware und nicht der Compiler...

Autor: Nicht Bekannt (florian01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es leider erst wieder am WE testen, werden dann berichten...

Autor: Nicht Bekannt (florian01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Senden ist im Moment nur um zu sehen ob er beide bekommen 
hat.

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.