Forum: Mikrocontroller und Digitale Elektronik Lokdecoder AT90S2313


von Christian (Gast)


Lesenswert?

Hallo

Ich habe ein paar Fragen wegen einer Programmierung.
Also ich möchte in nächster Zeit mal versuchen ob ich einen Lokdecoder
(DCC-Format) programmieren kann (bzw. vorerst nur Funktionsdecoder).
Mit dem DCC-Protokoll mach ich mich momentan vertraut, verstehe es auch
relativ weit.
Ich habe auch schon an einigen Stellen im Internet gesucht (google...),
dabei ist mir aufgefallen, das als Signaleingang immer der
Interupteingang gewählt wird.
Ich programmieren schon einige Zeit mit dem AT90S2313 in Assembler
(Atmel-Studio), jedoch eher in einer niedrigeren Schwierigkeitsstufe.
Deshalb werfen sich nun auch ein paar Fragen auf.

Meine erste Frage wäre, kann ich also Signaleingang nicht den Uart
nehmen?
Als Startpfiff bzw. Achtungspfiff (Präambel) werden ja von der
"Station" min. 10 1-Bits ausgesannt.
Kann ich nun mit dem Uart des AT90S2313 diese 14 1-Bits einlesen, wenn
ja wie?
oder sind es nur max. 8Bits = 1 Byte.
Ist es überhaupt möglich über den Uarteingang (ohne es
programmtechnisch schwieriger zu machen) die exakten Zeiten
einzuhalten, die das DCC-System mit sich bringt oder muss ich da auch
einen Softwareuart zurückgreifen, der dann über den INT-Eingang läuft?

Desweiteren werden auch Nullbits und ein Endbit (1) ausgesannt.
Mit dem Uart habe ich natürlich schon gearbeitet, jedoch weis ich nicht
ob ich einzelne Bits auch versenden bzw. eher empfangen kann.

Leider gibts halt nicht so viele Threads zu diesem Thema/Themen und
anhand Beispielen lässt es sich immer noch am besten lernen :-)

Danke im Voraus!!!

Gruß
Christian

von crazy horse (Gast)


Lesenswert?

Uart kannst du komplett vergessen, das kann nicht funktionieren. Int-
oder ICP-Eingang sind schon richtig. Mit einem MC kannst du nur
bitweise empfangen, der Rest ist Software-Sache. Da die
Übertragungsrate ziemlich niedrig liegt und auch sonst kaum
Anforderungen an den MC bestehen, ist das kein Problem.

von Christian (Gast)


Lesenswert?

Dank
Aber wie stelle ich das dann an, wie kann ich die Bits empfangen und
wie kann ich sie dann zu Bytes zusammen setzen.
Oder gibt es vieleicht ein Beispiel dazu/ hier im Forum?
Ich habe halt bis jetzt noch nicht mit anderen Pins/Eingänge des
AT90S2313 Bits richtig ausgewertet, was ich ja hier tun muss.

Gruß
Christian

von Wolle (Gast)


Lesenswert?

Ich kenne das DCC-Protokoll nicht, aber nur mal so zum Prinzip :

es werden Daten (Bits) in einer bestimmten Zeit und von einer
bestimmten Länge gesendet. Dazu gehört irgendwie ein Clock-Signal.
Dieses bestimmt, wann Daten gültig sind.

Du musst also als erstes diese Clocksignal identifitzieren, falls es
nicht bekannt ist.
Ist es bekannt, mußt du den µC damit synchronisieren. D.h., du musst
das Einlesen der Daten (Bits) mit diesem Clock-Signal abstimmen.
Jetzt brauchst du nur einen bestimmten Startpunkt suchen/setzen. Ab
diesem Zeitpunkt zählst du die eingehenden Takte und schiebst die
anliegenden Datenbits in ein Register. Immer 8 Stück, dann das nächste
Register.
Wenn die Übertragung beendet ist, also die Stop-Information gekommen
ist, fängst du an, die gespeicherten Daten zu entschlüsseln.
Dann gehst du in eine "Warteposition" und bei der nächsten Start-Info
geht es wieder los.
Für dieses kleine Prinzip brauchst du also zwei Ports - einen für das
Clock-Signal und einen für die Daten.
Ist das Clocksignal bekannt (Frequenz) kannst du im Prinzip auf einen
Port verzichten und brauchst nur einen für die Daten. Dann müssen aber
die Clock-Signale vom Sender und vom µC die gleichen sein.

von Hannes L. (hannes)


Lesenswert?

Nööö...

Es gibt kein Clock-Signal.

Die Information ist in der Zeitdauer (Periodendauer) versteckt. Einsen
haben eine kürzere Periode, Nullen eine längere. Die genauen Werte
findest du im DCC-Protokoll.
Telegramme sind mindestens 3 Bytes lang, wobei das letzte Byte die
Prüfsumme ist (EXOR über alle vorherigen Bytes). Da der DCC-Standard
für Erweiterungen offen ist, gibt es auch längere Befehlstelegramme.

...

von crazy horse (Gast)


Lesenswert?

http://www.dcc.info/standards_rps/index.html

da findest du alles, was du brauchst. Ich habe auch mal was damit
gamacht (Weichendekoder mit Tiny12), finde es im Moment aber nicht.
Die einzige kleine Tücke: das stretched-0-bit.

Im Prinzip folgendes:
Bei jeder fallenden Flanke einen Int auslösen und die Zeiten dazwischen
mit dem Timer1 messen, schon weisst du, ob es ein 0- oder 1-bit war,
insofern ist auch ein Anschluss an den ICP-Eingang möglich/sinnvoll.
Dann eine Schleife einbauen, die die 1bits zählt, wird verlassen, wenn
entsprechende Anzahl erreicht und ein 0bit empfangen wurde (Preambel).
Dann jeweils 8bit einlesen und zu einem Byte zusammenfügen.
Adressüberprüfung, Funktionsauswahl, Checksumme prüfen, ggf. Aktion
ausführen, und dann wieder von vorn.

von plitzi (Gast)


Lesenswert?

Schau Dir mal die Seite von Gerhard Clemens an, der hat DCC-Dekoder mit
AVR gemacht und recht gut dokumentiert. Quelltext gibt es aber glaube
ich leider nicht.

http://bahn-in-haan.de/modell.html

Jörg

von Christian (Gast)


Lesenswert?

Danke bis jetzt!

Die Seite bahn-in-haan... kenn ich, von dort habe ich eigendlich das
meiste vom DCC-Protokoll verstanden.
Das DCC-Protokoll ist nicht das Problem, dort verstehe ich die Abläufe,
es geht nur um das Umsetzen in Assembler, bzw bestimmte Teile, wie z.B.
das ich einzelne Bits lese und diese dann zu Bytes zusammen setze...
Die Abläufe selbst im uC sind auch klar, wie was ablaufen müsste, bis
jetzt konnte ich von z.B. dem Tutorial oder anderen Beispielen schön
meine Sachen ableiten bzw. selbst ausprobieren und testen, was zum
lernen dazu gehört, aber zu diesem Thema finde ich leider keine
Beispiele :-(

Gruß
Christian

von Christian (Gast)


Lesenswert?

kann mir denn keiner helfen :-(

von Hannes L. (hannes)


Lesenswert?

Na dir wurde doch bereits geholfen...

Wo klemmt es denn jetzt noch?

- Periodendauer messen, lkeiner 87µs ist eine 1, größer ist 'ne 0
- Präambel erkennen (Einsen zählen, Gültigkeitsflag manipulieren)
- Null erkennen, Gültigkeitsflag prüfen, Bitschieberei vorbereiten
- 8 Bits in ein Register schieben, danach sichern
- Trennbit auswerten (0: es kommt noch ein Byte, 1: fertig)
- weitere Bytes einlesen bis Trennbit 1 ist
- Gültigkeitsflag aus, jetzt wird Präambel erwartet
- Prüfsumme über alle Bytes testen und Telegramm evtl. verwerfen
- Adresse auswerten und prüfen, ob das Telegramm für "mich" ist
- Falls ja, Schalthandlung ausführen
- und im Hintergrund fleißig weiter Impulse messen und zählen...

Achja, das war jetzt aus dem Hut, kann sein, dass ich noch diesen oder
jenen Punkt vergessen habe.

...

von Christian (Gast)


Lesenswert?

jo theoretisch habe ich das alles verstanden, es hapert an dem
praktischen, wie schon gesagt, ich müste dazu erstmal wissen, wie ich
überhaupt bits einzeln bzw als byte oder bei der präambel verarbeiten
bzw. überhaupt lesen kann.
Ich habe halt wenn es ums bit bzw byte lesen nur mit dem uart
gearbeitet, klar ist schon das das schalten von ausgängen auch über
bits geht, bzw das diese in die register usw. geladen werden...

gruß
christian

von Christian (Gast)


Lesenswert?

ich bin nochmal :-)
Ich wollte nur nochmal sagen, es geht nicht darum einen kompletten code
zu bekommen, ich will ja selbst probieren und programmieren.
kleine beispiele und hilfen können wunder bewirken :-)

gruß
christian

von Hannes L. (hannes)


Lesenswert?

UART ist völlig anders, da steckt die Info im Pegel zur bestimmten
Zeit.

Bei DCC steckt die Info in der Periodendauer des Eingangssignals.
Perioden kleiner 87 Mikrosekunden sind Einsen, Perioden größer 87µs
sind Nullen.
Um die zu messen bietet sich die Input-Capture-Funktionalität des
Timer1 an, damit kann man im Hintergrund die Pegelwechsel erfassen und
die Zeitdauer seit dem letzten Pegelwechsel ermitteln (und auswerten).
Also im ICP-Interrupt "Zeitstempel" auslesen, Differenz zum
vorherigen ermitteln, für nächste Differenzbildung "aufheben".
Anhand der Differenz (Vergleich mit Konstante, die 87µs entspricht)
entscheiden, ob es Null oder Eins war. (Das Vergleichsergebnis steht
dann ja im Carryflag.) Dieses dann in ein Register schieben
(Verschiebebefehle, mal den Befehlssatz des AVRs genauer ansehen, z.B.
in der Onlinehilfe des AVR-Studios) und sozusagen "einsammeln". So
wird aus einem Bit ein Byte.
Und da die Präambel zu groß für ein Byte ist, müssen eben zwei Register
zu einem 16-Bit-Register kaskadiert werden. Das geht dadurch, dass beim
Verschieben/Rotieren das letzte Bit aus dem Register "ins Carry
fällt" und somit sofort in ein anderes Register hineingeschoben
(rotiert: rol/ror) werden kann.

Lass also den ICP-Interrupt die ermittelten Bits in ein Register
schieben und was da raus fällt gleich in ein Zweites. Erhöhe oder
vermindere ein weiteres Register als Zähler, den du zum Erkennen der
Bitanzahl (Byte) brauchen könntest. Setze dann noch ein reserviertes
Bit in einem reserviertem Register (heißt bei mir meist "flags"),
damit das Hauptprogramm (Hauptschleife) erkennen kann, dass ein neues
Bit empfangen wurde und wieder auf Präambel oder so geprüft werden
muss.
Du brauchst vermutlich sowiso einige Flags, an denen du markierst in
welcher Phase sich das Programm gerade befindet. Phasen wären z.B.:

- Warten auf Gültigkeitsfenster der Präambel (warten auf x Einsen)
- Präambel gültig (mehr als x Einsen, aber weniger als y Einsen)
  (x und y deshalb, weil ich die Spezifikation nicht exakt im Kopf
  habe und nicht festgenagelt werden will, wenn 11 und 15 nicht
  stimmen sollte...)
- Startbit (erste Null bei gültiger Präambel) Hier Zähler setzen, um
  exakt 8 Bits Daten zu "sammeln", danach Byte aus dem
  Schieberegister auslesen und woanders sichern.
- Nutzbyte einlesen (also die Phase, in der die Nitzbits abgezählt
  werden)
- Trennbit/Stopbit erwarten (0: Trennbit, es kommt noch ein Byte,
  1: Stopbit, fertig, erstes Bit der nächsten Präambel)
- Warten auf gültige Präambel...

Das ist auch der Startschuss, die empfangenen Bytes (Ringbuffer im
SRAM?) auszuwerten, also zuerst Prüfsumme, dann Adresse (für
"mich"?), dann Schaltfunktion ausführen.
Telegramme, bei denen die Prüfsumme nicht stimmt werden dann genauso
ignoriert wie Telegramme an einen anderen Decoder.

Mit Bits & Bytes müsstest du dich allerdings erstmal gründlich
auseinandersetzen. Falls es da hapert, solltest du dich vielleicht
erstmal mit kleineren Projekten befassen.

...

von Hannes L. (hannes)


Lesenswert?

Dann nimm das Datenblatt, und erkunde, wie die ICP-Funktionalität von
Timer1 funktioniert. Das ist die einfachste Möglichkeit, im Hintergrund
Zeiten zu messen.

Wie man die neu eingelesene Zeit mit der von der letzten Messung
verrechnet, um die Differenz zu ermitteln, dürfte klar sein.

Auch der Vergleich der Differenz mit 87µs dürfte nicht das Problem
sein, Aus Taktfrequenz und Vorteiler kann man 87µs in die Einheit der
Timerticks umrechnen und dann als Konstante zum Vergleich nehmen.

Wie du die Bits in ein (zwei) Register schiebst, habe ich oben bereits
beschrieben.

...

von Christian (Gast)


Lesenswert?

ich danke dir für diese ausführliche hilfe und werde dann mal die
angegebenen Orte durchsuchen...

gruß
Christian

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.