Forum: Mikrocontroller und Digitale Elektronik RS485 UART sendet obwohl er nicht soll


von Mike (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem und befasse mich schon fast 2 Wochen damit.

Zur Erklärung: Ich möchte ein RS485-Netz aufbauen.
Nun habe ich mir ein Protokoll ausgedacht, welches ich erstmal über 
einen Sniffer lesen möchte. Aber daran hackt es schon.
Ein Atmega32 soll 10 Zeichen nacheinander auf den Bus senden. Sie liegen 
in einem Array von uint8_t
Danach soll er über Interrupts in den Receive-Modus wechseln.
Wenn ich allerdings über den TXC (Transmit Complete) Interrupt den 
MAX481 umschalte bekomme ich eine \0 auf den Bus.

Wenn ich den MAX 481 auf Transmit stehen lassen, kommt nach kurzer Zeit 
nur noch Müll über den BUS. Obwohl TXEN, TXCIE und UDRIE schon 
deaktiviert wurden.
Das letzte Byte wurde auch gesendet, sonst wird wird der TXC-Interrupt 
ja nicht ausgelöst.

Hier ein Teil meines Quellcodes.
1
//Transmit Interrupt Routine
2
ISR(USART_UDRE_vect)
3
{
4
  while (!(UCSRA & (1<<UDRE)))              // warten bis Senden moeglich ist
5
    {
6
    }
7
  UDR = outputbuf[sendbytes++];              //Zeichen senden aus Outputbuf
8
  
9
  if (sendbytes >= 10)
10
  {
11
    UCSRB &= ~(1 << UDRIE);                //Interrupt zum Senden deaktivieren
12
    UCSRB |= (1 << TXCIE);                //Transmit Complete Interrupt aktivieren                
13
  }
14
15
}
16
17
18
//Transmit Complete Interrupt Routine
19
ISR(USART_TXC_vect)
20
{     
21
  //PORTB &= ~(1 << PB2);                  //MAX485 auf Receive stellen
22
  UCSRB &= ~(1 << TXCIE);
23
  UCSRB &= ~(1 << TXEN);
24
  UCSRB &= ~(1 << UDRIE);                  //Transmit Complete Interrupt deaktivieren                            
25
  UCSRB |= (1 << RXCIE) | (1 << RXEN);          //Receiver und Interrupt zum empfangen wieder einschalten
26
}

Ich bin mit meinem Latain am Ende.
Kann mir jemand weiterhelfen? Icha hab schon Baudrate angepasst, 
kontrolliert, alles ausgemistet.

Gruß Mike

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:

> Wenn ich allerdings über den TXC (Transmit Complete) Interrupt den
> MAX481 umschalte bekomme ich eine \0 auf den Bus.
>

Ich seh in deinem Code nicht, das du den MAX481 umschalten würdest.

Auf der anderen Seite frage ich mich, wozu du da wie ein wilder die 
Interrupts umkonfigurierst? Um den MAX481 von Senden auf Empfang 
umzustellen musst du doch den /RE bzw. DE Eingang vom Max481 bedienen 
und nicht Interrupts umkonfigurieren.
Die Umschaltung zwischen Senden und Empfangen ist ja nichts anderes als 
die Umschaltung dessen, wer jetzt den Pegel auf den RS485 Leitungen 
bestimmen darf. Das hat aber doch nichts damit zu tun, wie der MAX481 an 
den µC angebunden ist. Genau deswegen nimmt man ja auch so einen 
Treiber, damit man sich nicht mit dieser Umschaltung rumschlagen muss.

Aus Softwaresicht sieht die Sache doch so aus:
Wenn der µC senden will, dann schaltet er den MAX481 mittels /RE bzw. DE 
Eingang (des MAX) auf Senden und wenn der µC in den 'Horch-Modus' geht, 
dann schaltet er den MAX481 ebenfalls mittels /RE bzw. DE auf Empfang. 
Warum da jetzt Interrupts umzukonfigurieren wären, sehe ich da nicht 
wirklich. Die Umschaltung beshränkt sich einzig und alleine darauf, dem 
MAX durch die /RE bzw. DE Eingänge bescheid zu geben, ob er Senden soll 
oder ob er empfangen soll.

: Bearbeitet durch User
von Mike (Gast)


Lesenswert?

Hallo,

folgende Zeile ist auskommentiert, aus dem oben stehenden Grund.
1
//PORTB &= ~(1 << PB2);                  //MAX485 auf Receive stellen

Dort schalte ich sonst den MAX485 bzw MAX481 um aufs Empfangen.
Er wird bei der Initallisierung auf TRUE gesetzt und somit auf Senden

von Mike (Gast)


Lesenswert?

Im Datenblatt des Atmels sowie auch auf dieser Seite im Tutorial wird 
empfohlen, bei RS485 den Transreceiver in dem TXC-Interrupt zu 
verwalten. Genau das mache ich doch auch.

Ich muss ja sicherstellen, dass das letzte Byte versendet wurde.

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> Im Datenblatt des Atmels sowie auch auf dieser Seite im Tutorial wird
> empfohlen, bei RS485 den Transreceiver in dem TXC-Interrupt zu
> verwalten. Genau das mache ich doch auch.
>
> Ich muss ja sicherstellen, dass das letzte Byte versendet wurde.

Ja, das ist schon ok.
Denn du darfst den MAX erst dann von Senden auf Empfang umstellen, wenn 
das auszugebende Zeichen auch tatsächlich den MAX schon passiert hat.

Aber steht dort auch, dass du den Transmitter abschalten sollst, bzw. 
die Interruptfreigaben umstellen musst?

Denn: wenn du den Transmitter abschaltest, dann kriegt der µC-Pin wieder 
seine ganz normale Bedeutung und wird durch das DDR bzw. PORT Register 
gesteuert. Will man das? Ich sehe keinen Grund warum das so sein soll. 
Lass doch den Transmitter eingeschaltet. Der MAX kümmert sich ja sowieso 
nicht drum, wenn er auf Empfang umgeschaltet wurde.

von Karl H. (kbuchegg)


Lesenswert?

Mike schrieb:
> Hallo,
>
> folgende Zeile ist auskommentiert, aus dem oben stehenden Grund.

Aus welchem obenstehenden Grund?

Ich kann mir kein Szenario vorstellen, in dem man die tatsächlich 
notwendige Umschaltung (und diese Umschaltung IST genau die, die wichtig 
ist) weglassen würde.

Sprich: genau das ist die entscheidende Umschaltung.
Das Geplänkel mit Transmitter ein/aus schalten ist hingegen unnötig. Das 
schaltet den MAX nicht um.
Du musst aber den MAX umschalten, nicht deine UART. Deine UART kann so 
weiterlaufen wie bisher. mit Sender und Empfänger aktiviert.

: Bearbeitet durch User
von Mike (Gast)


Lesenswert?

Hallo, danke erstmal für die Antwort.
Ich habe es jetzt auf folgendes Code gekürzt.
1
//Transmit Interrupt Routine
2
ISR(USART_UDRE_vect)
3
{
4
  while (!(UCSRA & (1<<UDRE)))              // warten bis Senden moeglich ist
5
    {
6
    }
7
  UDR = outputbuf[sendbytes++];              //Zeichen senden aus Outputbuf
8
  
9
  if (sendbytes >= 10)
10
  {
11
    UCSRB &= ~(1 << UDRIE);                //Interrupt zum Senden deaktivieren
12
    UCSRB |= (1 << TXCIE);                //Transmit Complete Interrupt aktivieren                
13
  }
14
15
}
16
17
18
//Transmit Complete Interrupt Routine
19
ISR(USART_TXC_vect)
20
{     
21
  PORTB &= ~(1 << PB2);                  //MAX485 auf Receive stellen
22
  UCSRB &= ~(1 << TXCIE);                  //Transmit Complete Interrupt deaktivieren                                            
23
  UCSRB |= (1 << RXCIE);                  //Receive-Interrupt zum empfangen wieder einschalten                
24
}

Leider schickt der µC trotzdem noch eine 0x00 mit.
Hier sind TXEN und RXEN nun die ganze Zeit auf 1.
Und diese 0x00 kommt nur dann, wenn ich umschalte. Wenn ich auf Transmit 
stehen bleibe, kommt nur noch Datenmüll. Also irgendwelche Zeichen, die 
ich nicht ansatzweise versenden möchte und auch nicht in meinem Code 
setehen.

Gruß Mike

von Mike (Gast)


Lesenswert?

Also Datenmüll ist nun weg. Scheint wirklich an dem rumschalten am 
Transmitter und Receiver gelegen haben.

Jetzt würde ich natürlich nur noch gern diese blöde 0x00 weg bekommen, 
beim umschalten.

Das /RE und DE zusammen geschaltet werden über einen PIN vom µC ist aber 
legitim oder?

Gruß Mike

von c-hater (Gast)


Lesenswert?

Mike schrieb:

> Ich habe es jetzt auf folgendes Code gekürzt.

[...]

Der sieht gut aus.

> Leider schickt der µC trotzdem noch eine 0x00 mit.

Das bezweifele ich. Nicht, daß da ein Nullzeichen zu sehen ist, das mag 
schon sein, aber daß der µC eins sendet.

> Und diese 0x00 kommt nur dann, wenn ich umschalte.

Eben.

> Wenn ich auf Transmit
> stehen bleibe, kommt nur noch Datenmüll.

Beide Effekte können auf die gleichen Ursache zurückgehen: fehlende 
Potentialtrennung zwischen Sender und Empfänger und/oder fehlende 
Terminierung der RS485-Strecke.

Da du für den Testbetrieb wohl keine 100m Kabel ausgerollt hast, um 
Sender und Empfänger an hinreichend unterschiedliche Potentiale zu 
bekommen, würde ich mal auf fehlende Terminierung als Ursache tippen. 
Ja, 120Ohm-Widerstände an der richtigen Stelle können wahre Wunder 
bewirken...

von Sascha W. (sascha-w)


Lesenswert?

Mike schrieb:
> Jetzt würde ich natürlich nur noch gern diese blöde 0x00 weg bekommen,
> beim umschalten.
kommt das Nullbyte zusätzlich zu deinen 10 byte?

> Das /RE und DE zusammen geschaltet werden über einen PIN vom µC ist aber
> legitim oder?
ja

Hast du die Busleitungen (A & B) vorgespannt?

Sascha

von Jürgen D. (poster)


Lesenswert?

Das 0x00 wird nicht vom Prozessor gesendet. Durch das Abschalten des 485 
Treibers meint der Empfänger noch ein Startbit empfangen zu haben. Das 
ist aber nur Datenmüll, sowas sollte deine Empfangssoftware einfach 
ignorieren.

von Mike (Gast)


Lesenswert?

Hallo zusammen,

danke für die Antworten.
c-hater schrieb:
> Mike schrieb:
>
>> Ich habe es jetzt auf folgendes Code gekürzt.
>
> [...]
>
> Der sieht gut aus.
>
>> Leider schickt der µC trotzdem noch eine 0x00 mit.
>
> Das bezweifele ich. Nicht, daß da ein Nullzeichen zu sehen ist, das mag
> schon sein, aber daß der µC eins sendet.
>
>> Und diese 0x00 kommt nur dann, wenn ich umschalte.
>
> Eben.
>
>> Wenn ich auf Transmit
>> stehen bleibe, kommt nur noch Datenmüll.
>
> Beide Effekte können auf die gleichen Ursache zurückgehen: fehlende
> Potentialtrennung zwischen Sender und Empfänger und/oder fehlende
> Terminierung der RS485-Strecke.
>
> Da du für den Testbetrieb wohl keine 100m Kabel ausgerollt hast, um
> Sender und Empfänger an hinreichend unterschiedliche Potentiale zu
> bekommen, würde ich mal auf fehlende Terminierung als Ursache tippen.
> Ja, 120Ohm-Widerstände an der richtigen Stelle können wahre Wunder
> bewirken...


Also 120 Ohm Widerstände sind an den Enden drin. Ich nutze ein 
Steckboard, auf welchem der Atmega sitzt.
Der Sniffer hängt 10cm über geschirmte Telefonleitung entfernt daneben.

Sascha Weber schrieb:
> Mike schrieb:
>> Jetzt würde ich natürlich nur noch gern diese blöde 0x00 weg bekommen,
>> beim umschalten.
> kommt das Nullbyte zusätzlich zu deinen 10 byte?
>
>> Das /RE und DE zusammen geschaltet werden über einen PIN vom µC ist aber
>> legitim oder?
> ja
>
> Hast du die Busleitungen (A & B) vorgespannt?
>
> Sascha

Ja genau er schickt quasi 11Byte. Vorgespannt? Also Pullup und Pulldown 
Widerstände? Die sind auf jeden Fall mit 680 Ohm drin.

Jürgen D. schrieb:
> Das 0x00 wird nicht vom Prozessor gesendet. Durch das Abschalten
> des 485
> Treibers meint der Empfänger noch ein Startbit empfangen zu haben. Das
> ist aber nur Datenmüll, sowas sollte deine Empfangssoftware einfach
> ignorieren.

Also ist das normal? Das wirft natürlich nur meine ganze Auswertung für 
den Anfang durcheinander.
Würde ich dann beim Empfang direkt abfragen, ob es um das Startzeichen 
handelt ja?

Danke.
Gruß Mike

von Sascha W. (sascha-w)


Lesenswert?

Mike schrieb:
> Hallo zusammen,
> Also ist das normal? Das wirft natürlich nur meine ganze Auswertung für
> den Anfang durcheinander.
nein das ist nicht nomal. Pullup/-down richtig rum? Im Ruhezustand (alle 
auf Empfang) sollte am Ausgang des MAX Richtung µC +5V liegen!

> Würde ich dann beim Empfang direkt abfragen, ob es um das Startzeichen
> handelt ja?
genaugenommen empfängst du kein Null-Byte, da am Empfänger durch eine 
Flanke ein Frameerror entsteht. Die meisten Terminalprogramme zeigen 
aber keine Fehler an, sondern eben ein Datenbyte.
Wenn du beim Empfang mit dem µC die Fehlerbits beim Empfang ordentlich 
auswerteset, dann wird kein sinnloses Byte an die "nächsthöhere 
Softwareschicht" weitegegeben.

Sascha

von c-hater (Gast)


Lesenswert?

Mike schrieb:

> Also ist das normal?

Nein, bei fehlerfreier RS485-Hardware ist das keinesfalls normal.

Ich befürchte aber, daß du ohne Oszi bei der Suche nach dem Fehler nicht 
weiter kommen wirst.

Ein Ansatz könnte allerdings der Hinweis von mike sein

> Das /RE und DE zusammen geschaltet werden über einen PIN vom µC ist aber
> legitim oder?

Es ist zumindest schnell gemacht, die Signale an getrennte Steuer-Pins 
zu legen und ein Delay zwischen ihrer Umschaltung zu programmieren. Die 
Idee dahinter: Die Typen von Maxim werden schon irgendeinen Grund dafür 
gehabt haben, getrennte Anschlüsse für diese Umschaltung vorgesehen zu 
haben. Es steht zu befürchten, daß sie schlicht über die Schwächen ihrer 
Lösung mehr wußten, als sie aus kommerziellen Gründen in's Datenblatt zu 
schreiben wagten...

Möglicherweise steht's sogar drinne, aber natürlich so gut getarnt, daß 
man es nur findet, wenn man zielgerichtet danach sucht UND die 
entsprechende Angabe in diesem Kontext zu interpretieren weiß.

von Konrad S. (maybee)


Lesenswert?

Sascha Weber schrieb:
> Pullup/-down richtig rum? Im Ruhezustand (alle
> auf Empfang) sollte am Ausgang des MAX Richtung µC +5V liegen!

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

Sascha Weber schrieb:
> Mike schrieb:
>> Hallo zusammen,
>> Also ist das normal? Das wirft natürlich nur meine ganze Auswertung für
>> den Anfang durcheinander.
> nein das ist nicht nomal. Pullup/-down richtig rum? Im Ruhezustand (alle
> auf Empfang) sollte am Ausgang des MAX Richtung µC +5V liegen!
>
>> Würde ich dann beim Empfang direkt abfragen, ob es um das Startzeichen
>> handelt ja?
> genaugenommen empfängst du kein Null-Byte, da am Empfänger durch eine
> Flanke ein Frameerror entsteht. Die meisten Terminalprogramme zeigen
> aber keine Fehler an, sondern eben ein Datenbyte.
> Wenn du beim Empfang mit dem µC die Fehlerbits beim Empfang ordentlich
> auswerteset, dann wird kein sinnloses Byte an die "nächsthöhere
> Softwareschicht" weitegegeben.
>
> Sascha

Mein Terminalprogramm kann auch Fehler anzeigen. Die Geschichte ist sehr 
rot.
(siehe Anhang)
Das ist doch wahrscheinlich auch schon nicht normal oder?

von c-hater (Gast)


Lesenswert?

Mike schrieb:

> Mein Terminalprogramm kann auch Fehler anzeigen. Die Geschichte ist sehr
> rot.
> (siehe Anhang)
> Das ist doch wahrscheinlich auch schon nicht normal oder?

"Falsches" Frameformat eingestellt.

Falsch steht deshalb in Anführungszeichen, weil es eigentlich kein par 
se falsches Frameformat gibt, sondern nur ein ABWEICHENDES. Oder 
anders ausgedrückt: Sender und Empfänger sprechen schlicht verschiedene 
Sprachen.

von Hans M. (Gast)


Lesenswert?

Ein PullUp ( intern oder extern ) am RX vom µC verhindert die pseudo 
0x00.

Grüße Hans

von Mike (Gast)


Lesenswert?

c-hater schrieb:
> Mike schrieb:
>
>> Mein Terminalprogramm kann auch Fehler anzeigen. Die Geschichte ist sehr
>> rot.
>> (siehe Anhang)
>> Das ist doch wahrscheinlich auch schon nicht normal oder?
>
> "Falsches" Frameformat eingestellt.
>
> Falsch steht deshalb in Anführungszeichen, weil es eigentlich kein par
> se falsches Frameformat gibt, sondern nur ein ABWEICHENDES. Oder
> anders ausgedrückt: Sender und Empfänger sprechen schlicht verschiedene
> Sprachen.

Danke, aber leider sprechen alle die gleich Sprache. Beide Teilnehmer 
laufen auf 8N1. Daran habe ich nämlich auch sofort gedacht.

Hans M. schrieb:
> Ein PullUp ( intern oder extern ) am RX vom µC verhindert die
> pseudo
> 0x00.
>
> Grüße Hans

Danke.
Leider bewirkt das in meinem Fall auch nichts. Wenn ich einen 10k 
Widerstand von +5V nach RX ziehe, sendet er genau so die 0x00.
10k sollte doch passen oder zu groß?

Gruß Mike

von Sascha W. (sascha-w)


Lesenswert?

Mike schrieb:
> c-hater schrieb:
> Danke, aber leider sprechen alle die gleich Sprache. Beide Teilnehmer
> laufen auf 8N1. Daran habe ich nämlich auch sofort gedacht.
wenn ich das richtig sehe ist immer nur das erste Byte fehlerfrei.
Zeig doch mal deinen Code, incl. UART-Init, wie du ihn jetzt verwendest.

> Hans M. schrieb:
>> Ein PullUp ( intern oder extern ) am RX vom µC verhindert die
>> pseudo
>> 0x00.
>>
>> Grüße Hans
>
> Danke.
> Leider bewirkt das in meinem Fall auch nichts. Wenn ich einen 10k
> Widerstand von +5V nach RX ziehe, sendet er genau so die 0x00.
> 10k sollte doch passen oder zu groß?
10k ist ok, verhindert ab nur, das der sendente AVR am RX-Pin einen 
ordentlichen Pegel hat, weil der DO des MAX währenddessen hochohmig ist.
Ist also für den TX Weg erst mal zweitrangig.

Sascha

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.