\documentclass[german]{article} \begin{document} \title{Dallas 1–Wire mit Forth ansprechen} \author{Bernd Paysan} \maketitle \begin{multicols}{2} \begin{abstract} Das 1-Wire-Interface von Dallas/Maxim ist eine etwas neuere Alternative zu Bussen mit zwei oder drei Drähten (I²C oder SPI). Es gibt inzwischen eine Reihe von kleinen Geräten, die man mit dem Interface ansprechen kann. Der Artikel zeigt, wie das von Forth aus geht. \end{abstract} \section{Einleitung} Wie bereits im Bericht von der Münchner Forth--Gruppe im letzten Heft kurz angesprochen, beschäftige ich mich zur Zeit mit dem 1--Wire--Interface von Dallas. Am Beispiel eines iButton--Thermometers zeige ich hier, wie man mit so einem 1--Wire--Gerät spricht. Ähnlich wie I²S ist 1--Wire ein Open--Drain--Bus, d.h. ein Pullup zieht die Leitung nach oben (und versorgt einfache Geräte wie iButtons mit ein wenig Strom). Die Busteilnehmer haben alle einen NMOS--Transistor, der die Leitung kurz auf 0 ziehen kann --- ein ganz kurzer Puls ist eine 1, ein etwas längerer Puls ist eine 0, und zwei wesentlich längere Pulse kennzeichnen Reset und die Present--Antwort eines Gerätes. \section{Serielle Schnittstelle} Als Interface nutze ich den Dallas DS2480B\footnote{Datasheet: \url{http://datasheets.maxim-ic.com/en/ds/DS2480B.pdf}}, der zunächst USB auf seriell umsetzt, und dann die serielle Schnittstelle auf 1--Wire. Vom Betriebssystem (Linux) wird die USB--Zwischenschicht im Treiber versteckt, d.h. man öffnet \verb|/dev/ttyUSB0| wie eine serielle Schnittstelle. Lesen und Schreiben wird dann über \verb|read-file| und \verb|write-file| erledigt. Die serielle Schnittstelle muss ich dann noch auf die richtige Geschwindigkeit setzen, und auch sonst noch einige Flags setzen --- schließlich ist der DS2480B kein Terminal. Stattdessen nimmt er Kommandos an --- solche zum Konfigurieren (die sind alle in \verb|'stuff| untergebracht), oder solche, um den 1--Wire--Bus anzusprechen (die sind mit Konstanten benannt). Ich lege mir noch ein paar Buffer an, mit denen ich Daten hin- und herschicken kann, ein \verb|>cmd|, um Kommandos zu schicken, und eine Routine \verb|>results|, um die Resultate ohne blockierendes Warten vom DS2480B zurückzubekommen. Damit kann ich das Protokoll jetzt implementieren. \section{Das 1--Wire--Protokoll} Die Sequenz eines 1--Wire--Packets fängt mit dem Reset-- und Present--Puls an. Danach kommt ein Byte, das als ``Master ROM Function Command'' bezeichnet wird. Die möglichen Reaktionen: \begin{tabular}{llp{4.3cm}} \bf Cmd & \bf Name & \bf Daten \\ \hline 33h & Read ROM & Device schickt 64--Bit--Adresse zurück \\ 55h & Match ROM & Device erkennt 64--Bit--Adresse \\ F0h & Search ROM & Suche nach 64--Bit \\ ECh & Alarm search & Suche, wenn Alarm gesetzt ist \\ CCh & Skip ROM & Keine Adresse \end{tabular} Anschließend kommt dann die tatsächliche "`Nutzlast"', die Memory-- und Kontrollfunktionen. Derer gibt es bei einem iButton--Thermometer fünf, nämlich \begin{tabular}{llp{3.5cm}} \bf Cmd & \bf Name & \bf Daten \\ \hline 4Eh & Write Scratchpad & 2 Bytes Scratchpad \\ BEh & Read Scratchpad & 9 Bytes Scratchpad \\ 48h & Copy Scratchpad & --/-- (dauert 10ms) \\ 44h & Convert Temp. & --/-- (dauert 0.75s) \\ B8h & Recall & --/-- (Trigger Value nach Scratchpad) \end{tabular} In den ersten beiden Stellen des Scratchpads steht die Temperatur auf ein halbes Grad genau, die letzten beiden (vor der Checksumme) enthalten einen Bruch des Restwerts. Damit haben wir nun genügend Informationen, um den Sensor am Bildschirm anzuzeigen: \begin{figure} \centering \includegraphics{2007-0304/sensor} \caption{Sensor} \label{fig:sensor} \end{figure} Die Beschreibung der genauen Prozedur beim Auflisten der Devices überlasse ich lieber dem Datenblatt von Dallas. Nur soviel: Auf dem 1--Wire--Bus werden für jedes Bit des Geräts drei Bits versendet, dabei die ersten zwei vom Gerät, das letzte vom Master: Eins normal, eins invertiert, und der Master dann, wie er sich entschieden hat. Auf der seriellen Schnittstelle erhält man für diesen Vorgang zwei Bits zurück, eines für die gewählte Adresse, das andere, ob es bei diesem Bit einen Konflikt gab. \section{Zusammenfassung} Mit etwas mehr als hundert Zeilen bekommt man einen iButton--Sensor mit Forth zum Laufen. Dallas hat auch ein User--Mode--Dateisystem für Linux geschrieben, das die ganzen Geräte ansprechen kann. Da sind viele tausend Zeilen Code vergraben, die zwar alle wunderschön offengelegt sind, und auch kommentiert, aber einfach so viel, dass ich lieber ein Reverse--Engineering--Tool (strace) angeworfen habe, um damit dann schneller zum Ziel zu kommen. \end{multicols} \section{Listing} \begin{quote} \hrulefill 1wire.fs \hrulefill \listinginput[1]{1}{2008-01/1wire.fs} \hrulefill 1wire.m \hrulefill \listinginput[1]{1}{2008-01/1wire.m} \hrulefill \end{quote} \end{document}