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
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.
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.
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.
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.
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
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
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...
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
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.
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
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
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ß.
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?
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.
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
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