Erklärungen zum 1-Wire Emulator bis 2014
Einige Erklärungen zum grundsätzlichen Ablauf:
Reset-Impuls erkennen
Eine 1-Wire-Sequenz beginnt immer mit einem Reset-Impuls. Dies ist der längste Low-Pegel im ganzen Protokoll. Im "Ruhezustand" (OWM_SLEEP) wird bei jeder fallenden Flanke ein Interrupt ausgelöst. Gleichzeitig wird ein Timer gestartet der nach der angegebenen minimalen Länge des Reset-Impulses eine Leitungsanfrage auslöst. Ist die Leitung dann immer noch auf Low, so wird der Pegel-Interrupt auf die Detektion einer steigenden Flanke umgestellt und sozusagen auf das Ende des Reset-Impulses gewartet.
Was passiert, wenn das 1-Wire Device im Ruhezustand ist, weil der 1-Wire Master mit einem anderem Gerät kommuniziert?
Jede fallende Flanke löst einen Interrupt aus. Der Timer wird immer wieder zurückgesetzt, oder am Ende der Kommunikation wird ein High-Pegel detektiert.
UML für den Kommunikationsbeginn (pdf)
Presence-Impuls
Nach dem Reset-Impuls mus jedes angeschlossene Gerät den 1-Wire Bus eine bestimmte Zeit auch Low ziehen. So erkennt der Master, ob überhaupt Geräte angeschlossen sind. Dieser Vorgang ist komplett über den Timer-Interrupt gesteuert. Der Interrupt für den 1-Wire Eingang ist dabei deaktiviert.
Zeitlicher Ablauf und Zustände im Mikrocontroller (pdf)
Empfangen von Bits und Bytes
Die Übertragung eines Bits im 1-Wire-Bus geht immer mit einer fallenden Flanke einher, die vom Master vorgegeben wird. Damit wird der Bus synchronisiert. Diese Flanke löst den Interrupt aus und stellt den Timer entsprechen ein für die Überprüfung ob das entsprechende Bit eine 1 (High-Pegel) oder eine 0 (Low-Pegel) ist. Der Interupt für das Bus-Pin wird dann deaktiviert und auf den Timer-Interupt gewartet. Die Timer-ISR list dann das Bit aus Speichert es und aktiviert wieder den Pin-Change-Interrupt. Das gleiche wiederholt sich für alle 8 Bits. Danach wird in der Timer-ISR der Befehl geprüft und die Zustandsvariable entsprechen gesetzt.
1-Wire Timing
Fünf Zeiten müssen für das Protokoll eingestellt werden:
Name | Beschreibung | Vorgegebene Zeit | Wert bei 8 MHz/64 | Erklärungen |
OWT_MIN_RESET |
Minimale Dauer des Reset-Impulses | 480 µs normal Wert Annahme 440 µm | 55 | |
OWT_RESET |
Minimale Dauer des Reset-Impulses | Master samples den Presence-Impuls nach 70 µs |
4 (32µs) | Basierent auf Messwerte |
OWT_PRESENCE |
Pause zwischen Reset Presence-Impuls | 410 µs bis Master fallende sendet | 20 (80µs) | Bei Problemen erhöhen |
OWT_READLINE |
Zeit zwischen fallander Flanke vom Master und dem Auslesen | 15 µs | 3-4 (24-32 µs) | Für lange Leitungen sind längere Zeiten sinnvoll |
OWT_LOWTIME |
Dauer des Slave Low-Pegels | 60 µs | 3-4 (24-32 µs) | Schnelle Master (z.B. DS9490) funktionieren nur mit 24 µs korrekt, da der AVR für die Berechnungen für das nächste Bit Zeit braucht (DS2423 read, Countercopy, CRC16...) |
Zu Problemen kam es bei der DS2423-Emulation bei zu langer LOW-TIME. Offensichtlich ist der AVR dann noch nicht fertig mit der Berechnung, die erst nach dem Ende des Low-Signals erfolgt. Mit 24 µs funktionierte es aber bisher ganz gut. Es besteht aber noch die Möglichkeit, Berechnungen oder das Kopieren der Zählervariablen in die PIN_INT Funktion zu verschieben. Weiterhin gibt es auch die Möglichkeit die LOW-TIME zu splitten, so dass die Berechnungen wärend des Low-Signals ausgeführt werden. Wer Probleme hat, soll sich bitte melden, dann pflege ich die Änderungen ein.
Kommentare
it is no problem to use this code with ATmega2560. I have checked it with ATmega644 and 16 and 20 MHz. The Problem is that the Arduino uses a special programming API. I think it is difficult to transform it in for this API. Every single statement in this code has a particular intention. Changes may disarrange timings and bits.
Tobias
I am new to Arduino and using Mega 2560. How can I use it for Mega 2560 ?
Thanks & Regards,
Sachin