www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik USART, die 4220.


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Ralf G. (ralg)
Datum:
Angehängte Dateien:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Mahlzeit - ich häng' fest!
Ein Master (atmega162) soll ein Datenpaket über RS485 an einen Slave 
(attiny2313) schicken.
Nach dem Einschalten und auf Tastendruck funktioniert das auch genau 
einmal. Gaaanz selten mehrmals hintereinander. Danach kommen (am 
meisten) nur noch (Datenlänge-1)Bytes (kontrolliert mit Pinwackeln an 
PIND6 vom tiny) oder weniger an. Extrem selten mal ein komplettes 
Datenpaket. Ein Übertragungsfehler (DatenUSARTin() mit 'return false') 
wird nie angezeigt. Nach längerer Pause (ca. 1min kein Tastendruck) 
hängt sogar die Senderoutine (kontrolliert mit PINB7 am mega).
Die obigen Dateien gehören folgendermaßen zusammen:
- Projekt 'Master': MainMaster.c, Timer0.c, USART.c
- Projekt 'Slave': MainSlave.c, USART.c

Ist alles etwas amateurmäßig, vielleicht kann trotzdem mal jemand 
drüberschauen und mich auf die richtige Fährte schicken.
Vielen Dank.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Neue Erkenntnis: Es muss (müsste) am Master liegen.
Habe den Slave 'im laufenden Betrieb' neu geflasht: Master gestartet - 
Taste - ordentliche Datenübertragung - Taste - Slave schließt Empfang 
nicht ab, da letztes Byte fehlt - Slave neu beschrieben - Taste - Slave 
schließt Empfang nicht ab, da letztes Byte fehlt ... - Taste - Master 
schließt Senden nicht ab, bleibt im USART-Busy-Status. Also alles wie 
immer.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Noch was neues: Es kommt im Fall der Übertragung von (n-1)Bytes immer 
das 3.Byte nicht an!?

Autor: Markus Weber (Firma: guloshop.de) (m-w)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Noch was neues: Es kommt im Fall der Übertragung von (n-1)Bytes immer
> das 3.Byte nicht an!?

Moin!
Ich hab zwar keine Ahnung, aber ich werf mal Fragen in den Raum:
- Zeitbasis verlässlich (Quarzoszillator bei beiden AVR)?
- Anzahl der Stoppbits mal verändert (verschiedene Kombinationen 
probieren)?

P.S.: Hast du einen Schaltplan zur Hand?

Autor: Stefan M. (celmascant)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Ein Master (atmega162) soll ein Datenpaket über RS485 an einen Slave
> (attiny2313) schicken.

Welche RS485-Treiber benutzt du denn?
Ich habe vor kurzem ein RS485 Bussystem mit dem SN75176 als Treiber 
aufgebaut. An den Slaves kam nurnoch Murks raus.
Die Ursache war ziemlich einfach: Die Ausgangsspannung des SN75176 war 
zu niedrig. Der MC hat das nur sporadisch als High erkannt.
Abhilfe hat das einschalten des Pullups des Rx-Pins geschaffen. Seitdem 
geht das Problemlos (mittlerweile 2 Monate).

Gruss Stefan

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich teste dann mal weiter.

Markus W. schrieb:
> Ich hab zwar keine Ahnung, aber ich werf mal Fragen in den Raum:
> - Zeitbasis verlässlich (Quarzoszillator bei beiden AVR)?

ja, die 6.144MHz

> - Anzahl der Stoppbits mal verändert (verschiedene Kombinationen
> probieren)?

noch nicht.

Stefan M. schrieb:
> Welche RS485-Treiber benutzt du denn?

MAX485

> Ich habe vor kurzem ein RS485 Bussystem mit dem SN75176 als Treiber
> aufgebaut. An den Slaves kam nurnoch Murks raus.
> Die Ursache war ziemlich einfach: Die Ausgangsspannung des SN75176 war
> zu niedrig. Der MC hat das nur sporadisch als High erkannt.
> Abhilfe hat das einschalten des Pullups des Rx-Pins geschaffen.

auch mit Pullups dasselbe.

Micht wundert eins sehr stark:
ISR:
ISR(V_USART_TXC_vect)
{
 V_UCSRB &= ~(1 << B_TXCIE);
 IRStatus |= 1 << B_USART_TXC;
 IRStatus &= ~(1 << B_USART_BUSY);
};

in der Hauptschleife:
...
  if (IRStatus & (1 << B_USART_TXC))
  {
   IRStatus &= ~(1 << B_USART_TXC);
 /* TEST */ PORTB |= (1 << 5);
  }
...
Wieso kann das gelegentlich passieren, dass die if-Abfrage 
abgearbeitet wird - also das Bit
B_USART_TXC
 gesetzt ist - aber das
B_USART_BUSY
-Bit nicht gelöscht wird? Erkennbar daran, dass die LED an PINB7 nicht 
mehr blinkt und die Taste nicht mehr reagiert.
In der Hauptschleife am Anfang:
...
  if ( !(IRStatus & (1 << B_USART_BUSY)) )
  {
 /* TEST */ if (!verz)
 /* TEST */ PORTB ^= (1 << 7);
...

An das Ende der while-Schleife habe ich zum Rücksetzen nochmal mit 
eingefügt:
  if ( TasteGedrueckt1(0,2) )
  {
   IRStatus &= ~(1 << B_USART_BUSY);
 /* TEST */ PORTB &= ~(1 << 5);
   _delay_ms(200);
 /* TEST */ PORTB |= (1 << 5);
  }

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich habe das Ganze nur überflogen (also nicht bis ins letzte Detail 
nachvollzogen), dabei sind mir drei Dinge aufgefallen:

1) IRStatus wird sowohl im Interrupt-Kontext, als auch im Main-Kontext 
verändert, aber keiner der Main-Kontext-RMW-Zugriffe ist geschützt.

2) Der TXC-Interrupt wird verwendet, ist aber nur zeitweise 
eingeschaltet. Es wird aber nirgendwo das Interrupt-Flag "von Hand" 
gelöscht. Wenn also zum Zeitpunkt des Einschaltens das Flag bereits 
gesetzt ist (*), dann hast du ein Problem.
(*): z.B. weil ein UDRE-Interrupt so lange verzögert wurde, dass der 
UART "zwischendrin" schon mal "leer gelaufen" ist.

3) Du verwendest sleep_mode(), was potenzielle Race-Conditions 
beinhaltet. Überhaupt bringt man so was erst mal ohne Sleep zum laufen, 
und baut das dann danach ein.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> 1) IRStatus wird sowohl im Interrupt-Kontext, als auch im Main-Kontext
> verändert, aber keiner der Main-Kontext-RMW-Zugriffe ist geschützt.
Könnte sein. Ist auf jeden Fall sicherer, wenn ich mal eine 
Interruptsperre einbaue.

> 2) Der TXC-Interrupt wird verwendet, ist aber nur zeitweise
> eingeschaltet. Es wird aber nirgendwo das Interrupt-Flag "von Hand"
> gelöscht. Wenn also zum Zeitpunkt des Einschaltens das Flag bereits
> gesetzt ist (*), dann hast du ein Problem.
> (*): z.B. weil ein UDRE-Interrupt so lange verzögert wurde, dass der
> UART "zwischendrin" schon mal "leer gelaufen" ist.
Der TXC-Interrupt wird nach Übernahme des letzten Bytes nach UDR 
eingeschaltet und der UDRE-Interrupt abgeschaltet. Das TXCIE-Bit wird im 
TXC-Interrupt wieder gelöscht. Ist nach meiner Ansicht erstmal eine 
logische Reihenfolge.

> 3) Du verwendest sleep_mode(), was potenzielle Race-Conditions
> beinhaltet. Überhaupt bringt man so was erst mal ohne Sleep zum laufen,
> und baut das dann danach ein.
Ich habe da gleich in den Sendepausen den Timer0-Interrupt 
(Tastenentprellung) als Zeitbasis für Kontrollblinken der LEDs.

Also, ich leg dann mal los.

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Der TXC-Interrupt wird nach Übernahme des letzten Bytes nach UDR
> eingeschaltet und der UDRE-Interrupt abgeschaltet. Das TXCIE-Bit wird im
> TXC-Interrupt wieder gelöscht. Ist nach meiner Ansicht erstmal eine
> logische Reihenfolge.

Ich habe auch nichts anderes behauptet.
Aber ich an deiner Stelle würde auf Nummer sicher gehen und zusätzlich 
das TXC-Flag direkt nach dem Schreiben des letzten Bytes nach UDR 
löschen.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> 1) IRStatus wird sowohl im Interrupt-Kontext, als auch im Main-Kontext
> verändert, aber keiner der Main-Kontext-RMW-Zugriffe ist geschützt.

Äähm...
Das war's! Der Timer-Interrupt hat mir dazwischengefunkt. Dort wird auch 
ein Bit gesetzt. (Brauch ich später noch, habe das Programm zur 
Fehlersuche erstmal eingekürzt) Hab' ich völlig ignoriert.

Vielen Dank, für den Hinweis. Liest man (also ich) zwar ständig, dass 
man sowas beachten muss, aber es betrifft einen ja nicht ;-)

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Aber ich an deiner Stelle würde auf Nummer sicher gehen und zusätzlich
> das TXC-Flag direkt nach dem Schreiben des letzten Bytes nach UDR
> löschen.

Da ist es doch aber noch gar nicht gesetzt? An der Stelle schalte ich 
den Interrupt doch erst ein. Denk' ich jedenfalls.

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Da ist es doch aber noch gar nicht gesetzt? An der Stelle schalte ich
> den Interrupt doch erst ein. Denk' ich jedenfalls.

Du verwechselst hier Interrupt-Flag mit Interrupt-Enable-Bit.
Das Flag wird immer beim Eintreten des entsprechenden Ereignisses 
gesetzt, egal ob der dazugehörige Interrupt gerade eingeschaltet ist, 
oder nicht. Und wenn das Flag dann schon gesetzt ist, wenn der 
entsprechende Interrupt eingeschaltet wird, kommt der Interrupt sofort. 
Daher zur Sicherheit vor dem Einschalten das Flag löschen.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Du verwechselst hier Interrupt-Flag mit Interrupt-Enable-Bit.

Ich meinte: Der TXC-Interrupt ist ja noch gar nicht aktiviert! Wird erst 
im UDRE-Interrupt eingeschaltet um sich dann selbst in der ISR wieder 
auszuschalten.

Meinst du IR aktivieren und gleich das Interrupt-Flag löschen? Aber ich 
will doch gerade sicher sein, dass ich die Meldung vom µC bekomme, dass 
die Daten richtig raus sind. Wegen späterer Sende-/Empfangsumschaltung.

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Ich meinte: Der TXC-Interrupt ist ja noch gar nicht aktiviert!

Spielt keine Rolle. Auch ohne aktivierten Interrupt wird das TXC-Flag 
gesetzt, falls mal die Daten nicht schnell genug nach UDR nachgeliefert 
werden können, so dass auch zwischendurch der Zustand "alles ist raus" 
(aus Sicht des µC) eintrifft. Und wenn du dann den TXC-Interrupt 
einschaltest, kommt er sofort (weil das Flag ja gesetzt ist), obwohl zu 
dem Zeitpunkt dann noch gesendet wird.

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Aaaah!
Also, das (jedes?) IR-Flag wird gesetzt, wenn das entsprechende Ereignis 
eintritt. Mit dem entsprechenden Enable-Flag zeige ich sozusagen nur an, 
ob's mich interessiert. Wenn das so ist, dann verstehe ich deine 
Erklärung. Ich bin davon ausgegangen, dass das Eintreten eines IR 
durch das Enable-Flag gesteuert wird.

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ralf G. schrieb:
> Also, das (jedes?) IR-Flag wird gesetzt, wenn das entsprechende Ereignis
> eintritt. Mit dem entsprechenden Enable-Flag zeige ich sozusagen nur an,
> ob's mich interessiert.

Richtig.
Das sind im Grunde zwei unabhängige Vorgänge:
a) Ereignis tritt auf -> Flag wird gesetzt
b) Flag und Enable-Bit gleichzeitig 1 -> Interrupt wird ausgelöst

Autor: Ralf G. (ralg)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Das sind im Grunde zwei unabhängige Vorgänge:
> a) Ereignis tritt auf -> Flag wird gesetzt
> b) Flag und Enable-Bit gleichzeitig 1 -> Interrupt wird ausgelöst

Na, da hat sich die Zusatzstunde doch gelohnt :-)

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net