www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit UART


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich hab Probleme bei der UART Übertragung. Empfangen alleine klappt, 
senden alleine auch, nur beides zusammen haut nicht hin.

Das empfangen mach ich per Daten-empfangen-Interrupt. Das senden ohne 
Interrupt in der main in der main(). Controller Atmega48

Hab leider den kompletten Code jetzt nicht zur Hand, sonst würd ich den 
auch mal schnell posten.

Hier nur ein paar Ausschnitte:

void uart_init()
{

DDRB |= (1 << PB2) | (1 << PB4) | (1<<PB1);

/* Aktivieren des Empfängers, des Senders und des "Daten 
empfangen"-Interrupts */
UCSR0B = (1<<RXCIE0) | (1<<RXEN0)|(1<<TXEN0);

/* baud rate*/
UBRR0H = (unsigned char) (UBRR>>8);
UBRR0L = (unsigned char) UBRR;

/* frame format: 8data, 2stop bit*/
UCSR0C =  (1 << USBS0) | (3 << UCSZ00);
}


void uart_transmit()
{
while(!(UCSR0A & (1<<UDRE0)))
{
}
UDR0 = AD_WERT_AKKU;
}


ISR(USART_RX_vect)
{
static unsigned char state = STATE_IDLE;

  c = UDR0;

  switch (state)
         ..............
         ...............
         ............usw.
}


Irgendwie scheinen die sich gegenseitig zu stören.... Sieht jemand den 
Fehler?




Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus den paar Code-Fetzen kann man nicht wirklich was rauslesen.
Das was du gepostet hast, ist soweit ok.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In ca. ner Stunde bin ich Zuhause, dann poste ich den ganzen Code.

Können die(empfangen und senden) sich denn irgendwie gegenseitig stören?

Vielleicht liegt es an meiner STATE, die ist ziemlich lang. Wenn ich ihm 
nur zwei Byte über die serielle schicke klappt auch beides zusammen.

Nur bei 16Bytes vom einen Controller zum anderen tauchen die Probleme 
auf. Und dabei sieht es so aus, das die ersten 16Byte empfangen werden, 
danach aber nix mehr.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ALte Regel:
Interrupt Service Funktionen so kurz wie möglich. Während eine ISR
läuft sind alle Interrupts gesperrt.

Normalerweise holt man in der ISR einfach nur das Zeichen ab und
stellt es in einen Buffer (Queue). Verarbeitet werden die Daten
dann erst in der Hauptschleife in der main().

Wenn du dich an dieses einfache Schema hältst, kann eigentlich nichts
schief gehen.

Autor: Christian Schoch (kriki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Wie schauts mit der Gegenseite aus ? Auch ein Mega oder was hängt 
dort dran?

2. Probier mal, wenn du vor dem Senden den RX-Int abdrehst, TXCIE an und 
auf Tx-Complete wartest, und dann den RX-Int wie an, Tx aus.

Könnte sein, dass wenn ein Interrupt von RX kommt, das dir die Daten von 
UDRE verschmeisst.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das ist anscheinend das Problem. Der UDR0 Wert.

Wenn ich Daten Empfange schreibe ich ja das erste Byte aus UDR0 in eine 
Variable und verarbeite diese mit einer STATE. Beim zweiten Empfangen 
Interrupt springt er dann in die entsprechende STATE und verarbeitet 
wieder UDR0. Das passiert 16 mal, also 16 empfangene Bytes.

Zwischendurch wird aber mal die Senden Routine aufgerufen. Da dort auch 
UDR0 verarbeitet wird, stimmen dann die Werte in der Empfangen Routine 
nicht mehr.

Könnte höchstens mit einem Interrupt arbeiten, welches am Anfang des 
Interrupts ausgeschaltet und nach 16 empfangenen Bytes wieder 
eingeschaltet wird.

Oder gibt es noch ne andere Möglichkeit?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass der Inhalt des "Sende-UDR0" nichts (aber auch überhaupt nichts!) 
mit dem Inhalt des "Empfangs-UDR0" zu tun hat, ist dir klar, oder?
Das sind zwei Register, die über die gleiche Adresse angesprochen 
werden. Wobei man das eine nur beschreiben und das andere nur lesen 
kann.

Eine State-Machine gehört nicht in eine ISR! Dafür sollte die 
Hauptschleife genug Platz und Zeit bieten. (Schliesse mich somit 
Karl-Heinz an.)
Dass dein gepostetes Programm etwas spärlich ausfällt, hat Karl-Heinz ja 
auch schon "bemängelt".

Was soll dein Programm machen bzw. wie sieht dein Protokoll aus?
Je nach Protokoll würde ich in der Empfangs-ISR ein Flag setzen, dass 
entweder bei jedem empfangenen Byte gesetzt wird, oder dann gesetzt 
wird, wenn alle 16 Bytes empfangen wurden. Die zweite Variante erfordert 
auf jeden Fall einen Puffer... Dann könnte die State-Machine aber auch 
anders aussehen...

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

Bewertung
0 lesenswert
nicht lesenswert
>Dass der Inhalt des "Sende-UDR0" nichts (aber auch überhaupt nichts!)
>mit dem Inhalt des "Empfangs-UDR0" zu tun hat, ist dir klar, oder?

Doch doch, eigentlich schon. Aber das Programm funktioniert nur nicht, 
sobald ich in der Sende-Routine UDR0 veränderen.

Hab es jetzt mal mit nem Senden_Interrupt versucht. Haut aber auch nicht 
hin.

Das Programm ist nun dabei. ist wahrscheinlich dann einfacher 
nachzuvollziehen.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0) | (1 << UDRIE0);
Wenn du UDRIE0 setzt, springt der Controller dauernd in die 
USART-Transmit-ISR.

Besser:
.
.
.

AD_WERT_AKKU = ADCH;
UDR0 = AD_WERT_AKKU;
UCSR0B |= (1 << UDRIE0);
.
.
.

ISR(USART_UDRE_vect)
{
  UCSR0B &= ~(1 << UDRIE0);
}

Und Kommentare würden die Lesbarkeit erhöhen...

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, mit Kommentaren hab ich es nicht so. Werd ich aber gleich mal 
ändern.

Klappt so auch nicht, sobald UDR0 mit dem AD-Wert überschrieben wird.

Wenn ich diese Zeile "//UDR0 = AD_WERT_AKKU; "ausblende, dann geht der 
Empfang. Wenn sie mit ausgeführt wird, läuft er nicht.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"c" würde ich noch ein "voltile" bei der Deklaration spendieren.
Eigentlich solltest du allen Variablem, die du in ISR und woanders 
benutzt, das volatile spendieren.

Wenn du den Funktionen c als Parameter übergeben würdest, wäre die 
State-Abfrage etwas kürzer.... (eher ein Schönheitsproblem...)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut.

Aber woran mag es liegen, dass diese einzelne Zeile das Empfangen 
komplett lahm legt, wenn die Inhalte von UDR0 beim Senden + Empfangen 
nichts miteinander zu tun haben?

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also es muss daran liegen, dass ich dem UDR0 zum senden einen Wert 
zuweise.

Sobald dieses irgendwo im Programm geschieht, funktioniert das Empfangen 
nichbt mehr....

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eher nicht.
Was du siehst sind die Auswirkungen eines anderen Problems.
Ich steig aber noch nicht komplett durch den Code durch.
Werde mich in der Nacht mal dazusetzen und das mit realer Hardware
durchprobieren. Ich hab allerdings keinen Mega48, nur einen Mega16.
Sollte aber keinen Unterschied machen.

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

Bewertung
0 lesenswert
nicht lesenswert
Das wäre echt super!

Hab den Code noch mal angehangen und etwas ausführlicher beschrieben + 
übersichticher gestaltet.

Schon mal vielen Dank!

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.