\documentclass[11pt,a4paper]{article} % save as utf-8-emacs-unix % 2006-07-07 EW Adventures-1.tex % 2006-07-22 EW Adventures-2.tex % 2006-08-14 EW Adventures-2a.tex % 2007-01-10 EW Adventures-3.tex % 2007-01-13 EW Adventures-4.tex % 2008-11-14 EW Adventures-5.tex % 2011-01-07 EW Adventures-6.tex: rs485+mpc % 2011-02-14 EW Adventures-7.tex: list % 2011-04-30 EW Adventures-8.tex: vocabulary % 2011-07... EW+MB Adventures-9.tex: rfm12 1/3 % % % language support \usepackage[german]{babel} %\usepackage{german} \usepackage[utf8]{inputenc} % can use Umlauts now ü instead of "u %\usepackage{lmodern} % better fonts %\usepackage{pslatex} % use native PostScript fonts %\usepackage{cm-super} \usepackage{url} % \url{} \path{} with correct "hyphenation" %\usepackage{fancyvrb} % for code examples % \voffset-10mm % \pagestyle{empty} % \pagestyle{plain} % \pagestyle{headings} % \renewcommand{\baselinestretch}{1.08} %\usepackage{xspace} \parindent=0pt \renewcommand{\amforth}{\texttt{amforth}} %\newcommand{\zB}{z.\,B.\ } \begin{document} \title{Adventures 9: Funklöcher!} \shorttitle{Adventures 9: Funklöcher} \author{Erich Wälde und Martin Bitter} \maketitle %\begin{multicols}{2} % -------------------------------------------------------------------- %\section{Intro} %\label{sec:intro} \begin{abstract}\itshape Es kommt der Tag im Leben eines \emph{Kontrollettis}\footnote{a. zwanghaft Kontrolle ausübender Mensch; b. Mikrokontroller programmierender Mensch; c. Geld-- oder Erbsenzähler}, wo es was zu messen gibt, an einer Stelle, an der ein Kabel (Strom, Kommunikation) keine Option ist. Das ist der Tag, wo er sich vielleicht daran erinnert, dass es bei Pollin [\ref{pollin}] so nette kleine Module mit dem Namen \emph{rfm12} gibt, die auf den ISM--Funkbändern senden und empfangen. Also flugs welche bestellt und bekommen und damit geht der Ärger richtig los. Stellt sich heraus, dass die Module kleine Primadonnen sind, die richtig gestreichelt werden wollen, bevor das mit der hauseigenen \emph{remote sensing}--Lösung einigermaßen funktioniert. Dieser Artikel beleuchtet die Grundlagen. Ein weiterer Artikel zeigt, wie man käufliche Außensensoren für übliche Wetterstationen (Technoline, \ref{techoline}) erfolgreich belauscht. Ein dritter Teil wird zeigen, wie man seine eigene Funkstrecke aufzieht, beispielsweise um damit den aktuellen Wasserstand aus der dunklen Zisterne im Hellen zu vermelden. \end{abstract} \begin{multicols}{2} % -------------------------------------------------------------------- \section{Grundsätzliches} \label{sec:intro} Die Vergabe des Funkspektrums wird bekanntlich von diversen, strengen Behörden geregelt. Für den \emph{freieren} Gebrauch gibt es vorgegebene Frequenzbänder, etwa die sogenannten ISM (\textit{industrial, scientific, medical})--Bänder [\ref{ism}], von denen zwei bei $434$\,MHz und $868$\,MHz liegen. Die Übertragung kann in Frequenzmodulation stattfinden, z.B.\ wählt man einen Frequenzhub von $\pm90$\,kHz. Damit können zwei Zustände 0 und 1 kodiert werden. Die zeitliche Abfolge dieser beiden Zustände leiht man sich von der seriellen Schnittstelle aus (4800 Baud). Für die ISM--Funkbänder gibt es vorgefertigte Module zu kaufen, etwa von der Firma Hope [\ref{hoperf}]. Sie werden über den SPI-Bus an einen Mikrokontroller angeschlossen. Für den Versuchsaufbau auf dem Schreibtisch benötigt man keine Antenne, ansonsten einen Draht von ca. 17\,cm Länge (entspricht $\lambda/4$ bei $434$\,MHz). Auf mikrocontrollernet.de [\ref{mikrocontrollernet}] finden sich längliche Forumseinträge, die sich mit den Tücken der Initialisierung und des Betriebs beschäftigen [\ref{mic-net}]. Der Hersteller bietet ein Datenblatt [\ref{rfm12.datasheet}] und Beispielprogramme [\ref{rfm12.sample.code}] zum Herunterladen an. Einen guten Einstieg bietet auch ein Artikel in Elektor [\ref{elektor}] vom Januar 2009. % -------------------------------------------------------------------- \section{Verbindung zum Funkmodul} Bevor man hier vorschnell zum Lötkolben greift, und den delikaten Seitentaschen der Module irgendwelche Drähte verpasst: Die Seitentaschen brechen bei zu viel Kraft aus und dann ist leider Schluss mit lustigen Kontakten. Es empfiehlt sich, die ebenfalls erhältlichen Adapterplatinen zu verwenden. \begin{figure} \centering \includegraphics[scale=0.1]{2011-03/adv9/1_module_adapter} \caption{Funkmodul und Adapterplatine} \end{figure} Außerdem muss an dieser Stelle gesagt werden, dass es die Funkmodule in dreierlei Ausführung gibt: den Sender rfm01, den Empfänger rfm02 und den Transceiver rfm12, welcher senden und empfangen kann, wenn auch nicht gleichzeitig. Alle hier beschriebenen Experimente wurden mit dem rfm12 gemacht. Die Fähigkeiten der verschiedenen Module unterscheiden sich minimal, aber entscheidend. Die Funkmodule werden über den SPI--Bus [\ref{spibus}] angeschlossen. Der Kontroller fungiert als \textit{master} und initiiert alle Datentransfers. Daten zum Funkmodul werden über den Pin \texttt{MOSI} (\textit{master out slave in}) übertragen. Gleichzeitig werden Daten vom Funkmodul am Pin \texttt{MISO} (\textit{master in slave out}) empfangen. Der Transfer wird mit dem vom \textit{master} getriebenen Pin \texttt{SCK} synchronisiert. Jeder Puls auf \texttt{SCK} erzeugt den Transport von einem Bit. Damit sich das Funkmodul angesprochen fühlt, legt der Kontroller die \textit{chip--select--}Leitung \texttt{/CS} des Funkmoduls auf \textit{low}. In der einfachsten Konfiguration braucht man lediglich vier Verbindungen zwischen Kontroller und Funkmodul: \begin{tabular}{lcl} {\small\texttt{MOSI}} & $\rightarrow$ & {\small\texttt{DIN}} \\ {\small\texttt{MISO}} & $\leftarrow$ & {\small\texttt{DOUT}} \\ {\small\texttt{SCK}} & $\rightarrow$ & {\small\texttt{CLK}} \\ {\small\texttt{PORTC.2}} & $\rightarrow$ & {\small\texttt{/CS}} \\ \end{tabular} \begin{figure} \centering \includegraphics[scale=0.1]{2011-03/adv9/2_module_adapter} \caption{Funkmodul auf Adapterplatine aufgelötet} \end{figure} % \bigskip % \begin{figure} % \centerline{\includegraphics[scale=0.5,angle=0]{2011-03/p_spi_rfm12.eps}} % \caption{Einfachster Anschluß des Funkmoduls am Kontroller.} % \end{figure} Man kann den Pin \texttt{/CS} auch auf den Pin \texttt{/SS} des Kontrollers legen. Das hat aber den Nachteil, dass das Funkmodul beim Programmieren des Kontrollers dazwischenredet, wenn man nicht mit Widerständen dagegen vorgeht. Ich habe mich entschieden, den \texttt{/CS} des Funkmoduls über den Pin C 2 anzusteuern. Der Preis ist allerdings, dass ich die JTAG--Verbindung mit \texttt{-jtag} stilllegen muss. Selbstverständlich besteht freie Auswahl, was den für \texttt{/CS} verwendeten Kontrollerpin angeht. {\small \begin{verbatim} PORTC 2 portpin: _rfm12 \ rfm select, needs -jtag PORTB 5 portpin: _mosi PORTB 6 portpin: _miso PORTB 7 portpin: _clk \end{verbatim} } \section {Mit dem Funkmodul reden} Die SPI--Schnittstelle des Mikrokontrollers wird in den \textit{master mode} gebracht. Dazu muss man den Pin \texttt{/SS} unbedingt vorher auf \textit{high} setzen, sonst lässt sich der \textit{master mode} nicht aktivieren. {\small \begin{verbatim} \ ewlib/spi.fs PORTB 4 portpin: /ss : +spi ( -- ) /ss high \ activate pullup! _mosi high _mosi pin_output _clk low _clk pin_output \ _miso pin_pullup_on \ not needed, see datasheet $53 SPCR c! \ enable, master mode, f/128 data rate ; : -spi ( -- ) 0 SPCR c! ; \end{verbatim} } %$ Das Funkmodul wird mit 2--Byte--Daten angesprochen. Der Befehl \texttt{spirw} überträgt aber nur ein Byte. Also definieren wir dazu das Wort \verb|>< spirw swap spirw swap >< + ; \end{verbatim} } Um mit dem Funkmodul zu reden, aktiviert man zuerst den \textit{chip select} (\texttt{\_rmf12 low}) und wartet dann darauf, dass das Funkmodul die Leitung \texttt{DOUT} auf \texttt{high} legt. Danach darf man die nächsten zwei Byte übertragen. Die Übertragungsroutinen sehen so aus: {\small \begin{verbatim} \ wait for wireless data tx ready : w? ( -- ) _rfm12 low begin _miso pin_high? until ; \ write 1 cell to wireless control : (>wc) ( x -- x' ) _rfm12 low >wc ( x -- ) (>wc) drop ; \ read wireless status : wc? ( -- x ) 0 (>wc) ; : w.status wc? 4 hex u0.r ; \ write wireless data (1 byte) : >w ( c -- ) $00ff and $b800 + w? (>wc) drop ; \ read wireless data (1 byte) : wc) ; \end{verbatim} } Das Wort \texttt{w?} wartet darauf, dass das Funkmodul seine Bereitschaft signalisiert. Das Wort \texttt{(>wc)} kontrolliert den \textit{chip select} für das Funkmodul und benutzt \verb|>wc) drop \end{verbatim} } der Wert \texttt{\$5aa5} an das Funkmodul übertragen und die Antwort verworfen. \section{Initialisierung} Bevor sich aber irgendetwas rührt, muss das Funkmodul richtig initialisiert werden. Man kann die Sequenz aus dem Beispielprogramm [\ref{rfm12.sample.code}] übernehmen. Das ist auch erst mal gut so, denn das Datenblatt der Funkmodule liest sich nicht sehr flüssig. {\small \begin{verbatim} : rfm12.init $80d7 >wc \ EL, EF, 434 MHz band, 12.0pF $82d9 >wc \ !er, !ebb, ET, ES, EX, !eb, !ew, DC $a67c >wc \ 434.150 MHz; Band Mitte: 433.920 MHz $c647 >wc \ 4800 baud $94a0 >wc \ VDI, FAST, 134 kHz, 0dBm, -103dBm $c2ac >wc \ AL, !m1, DIG, DQD4 $ca81 >wc \ FIFO8, SYNC, !ff, DR $c483 >wc \ @PWR, NO RSTRIC, !st, !fi, OE, EN $9850 >wc \ !mp, 90kHz, MAX OUT $e000 >wc $c800 >wc $c000 >wc ; \end{verbatim} } Schon an der Anzahl der Bytes kann man sehen, dass man sich hier leicht vertun kann. Das Ergebnis ist dann fast immer, dass die Übertragung nicht funktionieren will. Erschwerend kommt dazu, dass wir dabei nichts \emph{sehen} können. % -------------------------------------------------------------------- \section{Rauschen empfangen} Solchermaßen ausgestattet versuchen wir, ob unser Funkmodul etwas empfängt. Bei der Initialisierung des Funkmoduls ist es zwingend notwendig, den Status des Moduls zu lesen. Damit werden die Interrupts des Moduls gelöscht. Wenn sich beim Probieren so gar nichts rührt, dann kann das Lesen des Status die Angelegenheit deutlich verändern. {\small \begin{verbatim} : rfm12.rx $82d9 >wc ; : rfm12.off $8201 >wc ; : rfm12.rx.all -jtag +spi +rfm12 rfm12.init w.status cr rfm12.rx $ca87 >wc \ ??? hex begin ver amforth 4.5 ATmega32 ok > rfm12.rx.all 0120 FF FD FF FF FF FF FD F9 FF F9 FD FF F9 FF FF FD FF F9 FB FF FD F9 FF FF FD FF F9 FD FD FD FF FF FF FD FF FD F9 FF FF FF FF FF FF FF FD FF FF FD FD FB FF F9 FF FF FF FF FF F9 FF FD FD FF FF FF FD F9 F9 FF FF FD FD F9 FF FF F9 FF FF F9 FD FD FD FD FF F9 FF FD FD F9 FB FF FF FF F9 FB F9 FD FF FD F9 FB F9 F9 FF FF FD FF FF FD F9 FF FF FB FF F9 FF FF FF FB F9 F9 FF FF F9 FF FD FD FF FF F9 FD FD F9 FF FF FD F9 FD F9 FF FF FF FF FD FF FF FF F9 FF FF FF FF FD F9 FF F9 FF FF FD FD FB FB FF FF FD FF FF FF FF FB FF FD F9 FF FD FB F9 FF FF FD FF ... FF FD F9 FF ok > \end{verbatim} } Für meinen Geschmack sind hier zu viele \texttt{F} drin, aber das hängt u.U.\ von der Mittenfrequenz und der eingestellten Empfindlichkeit ab. % -------------------------------------------------------------------- \section{Nullen senden} Dem Ätherrauschen zuzuschauen ist nicht für jeden beruhigend, also machen wir uns daran, den Äther mit Nullen zu füllen, damit sich das Rauschen ändert. Dazu braucht man eine zweite Station, die als Sender konfiguriert wird. Dabei ist zu beachten, dass es im ISM--Band nicht gestattet ist, den Sender dauernd anzuschalten. Vorgesehen ist, dass ein Sender lediglich 1\,\% der Zeit aktiv ist, also höchstens eine halbe Sekunde pro Minute. Für erste Tests werden wir uns daran nicht halten, aber sobald wir die Nullen gesichtet haben. Auf der Sendestation definieren wir Worte, um den Sender bequem ein- und ausschalten zu können: {\small \begin{verbatim} : rfm12.tx.on ( -- ) $8238 >wc ; : rfm12.tx.off ( -- ) $8208 w? >wc ; : init -jtag +spi +rfm12 rfm12.init w.status cr ; \end{verbatim} } Auf der Empfängerstation starten wir wie oben das Empfangsprogramm \verb|rfm12.rx.all|. Auf der Sendestation starten wir den Sender {\small \begin{verbatim} > init 0120 ok > rfm12.tx.on ok \end{verbatim} } Jetzt sollten auf dem Empfänger lauter \verb|00| Bytes empfangen werden. Nach {\small \begin{verbatim} > rfm12.tx.off ok \end{verbatim} } verschwinden sie wieder und das Rauschen kehrt in Gestalt von mehr oder weniger zufälligen Bytes zurück. Wenn an dieser Stelle tatsächlich Nullen empfangen worden sind, solange der Sender eingeschaltet war, dann ist die erste große Hürde geschafft: Der Empfänger sieht die Informationen der Sendestation. Stellt sich sofort danach die Frage, wie man denn nun ein richtiges Datenpaket verschickt, und nicht nur Nullen. % -------------------------------------------------------------------- \section{Ein Datenpaket versenden} Ein wohlgestaltetes Datenpaket besteht aus der Präambel (\texttt{\$aa} Bytes), den magischen FIFO start Bytes \texttt{\$2d \$d4}, den zu übertragenden Daten \texttt{\$30 \$31 \$32 \$33 \$34} und einer Postambel (Post--Präambel ???). Diese gehört lediglich zum guten Ton. Auch darf man das Funkmodul nicht zu früh abschalten --- die Bytes werden schließlich irgendwann verschickt und der Kontroller wartet nicht auf das Ende, wenn man ihm das nicht beibringt (\texttt{w?}). Die zu verschickende Bytefolge soll so aussehen: \texttt{aa aa aa aa 2d d4 30 31 32 ... 3F aa aa aa} Die Präambel hat die Aufgabe, dem Empfänger die Chance zu geben, sich auf ein gültiges Signal einzuregeln. Den Empfänger kann man so konfigurieren, dass er zwar zuerst das große Rauschen, und dann die Präambel empfängt, diese Daten aber verwirft. Erst der Empfang der magischen Bytes \texttt{\$2d \$d4} führt dazu, dass der Empfänger den Empfang der nachfolgenden Bytes an den Kontroller signalisiert. {\small \begin{verbatim} : rfm12.tx.data ( xN .. x1 N -- ) rfm12.tx.on $aa >w \ sync pattern $aa >w $aa >w $2d >w \ magic bytes $d4 >w $10 0 do \ payload data i $30 + $b800 + w? >wc loop $b8aa w? >wc \ sync pattern $b8aa w? >wc $b8aa w? >wc rfm12.tx.off ; \end{verbatim} } % -------------------------------------------------------------------- \section{Ein Datenpaket empfangen} Der Empfänger kann alle Bytes empfangen, so wie vorher gezeigt. Allerdings können die Daten bitweise verschoben sein und sind dann schlecht zu finden. Leichter geht es, wenn man den Empfänger so konfiguriert, dass er auf die oben erwähnten magischen Bytes wartet und danach Datenbytes empfängt. Um den Empfang eines Bytes anzuzeigen, wird wie beim Senden die Leitung \texttt{MISO} auf \textit{high} und die Interrupt--Leitung des Funkmoduls auf \textit{low} gezogen. Beides kann benutzt werden, um das Abholen der empfangenen Daten durchzuführen. Der Kontroller entscheidet, wann er genug Daten gesehen hat. Dann teilt er dem Funkmodul mit, dass es auf die nächsten magischen Bytes warten soll. {\small \begin{verbatim} : rfm12.rx.clearfifo $ca81 >wc $ca83 >wc ; : rfm12.rx.data ( n -- ) \ start rx, wait for "2d d4" pattern $82c8 >wc rfm12.rx.clearfifo hex w? \ wait for wireless to become "ready" \ read n bytes ( n ) 0 ?do init 2120 ok > &20 rfm12.rx.data \end{verbatim} } Dann verschicken wir auf dem Sender einen 16 Byte langen Datenblock: {\small \begin{verbatim} > rfm12.tx.data ok > \end{verbatim} } Dann solle auf dem Empfänger eben dieses Datentelegramm plus weitere 4 Bytes erscheinen (von Hand umgebrochen): {\small \begin{verbatim} > &20 rfm12.rx.data 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F AA AA FF FF ok > \end{verbatim} } Man sieht am Ende zwei der drei angehängten \verb|AA|--Bytes, dann wird der Sender ausgeschaltet, bevor das dritte verschickt wurde. Die hier gezeigte Empfangsroutine blockiert so lange, bis tatsächlich ein Datenblock empfangen wurde. Das ist brauchbar, aber vielleicht auch unpraktisch. In einem späteren Teil wird die Verwendung einer Interrupt--Service--Routine für den externen \texttt{INT0}--Interrupt gezeigt. Dann kann der Mikrokontroller in der Wartezeit bequem andere Dinge erledigen. \section{Paketinhalt} Bei der Gestaltung des Datenblocks hat man freie Hand. Es gibt auch schon jede Menge Protokolle (z.B.\ [\ref{snap}]), die für diesen Einsatzzweck erfunden wurden. Im Moment verwende ich folgende Definition für Datenpakete mit der konstanten Länge 16\,Bytes. Darin ist ausreichend Platz, um den Datensatz für einen Sensor zu übertragen. \begin{tabular}{r|l} Größe & \\ \hline 1 & Adresse Sender \\ 1 & Adresse Empfänger \\ 1 & derzeit unbenutzt (Pakettyp?) \\ 1 & derzeit unbenutzt (Datenlänge?) \\ 10 & Daten \\ 2 & Checksumme \\ \end{tabular} Im Pakettyp könnten Informationen von der Bauart \texttt{ACK}, \texttt{NACK}, \texttt{BUSY} etc.\ transportiert werden. \section{So Sachen\ldots} Und dann gibt es natürlich noch die Dinge, die man nur sehr mühsam herausfindet. Ich konnte recht bald Datenpakete von einem Kontroller zu einem anderen senden. Allerdings funktionierte das nicht über Tage hinweg. Irgendwas blieb nach ein paar Stunden mehr oder weniger hartnäckig stecken. Mehrere Dinge habe ich mühselig herausgefunden: \begin{itemize} \item Funk ist eine analoge und keine digitale Technik. Es kommt vor, dass eine regelmäßige Übertragung, sagen wir mal jede Minute ein Datenpaket, stundenlang gut funktioniert. Dann ändert man \emph{irgendetwas}, und nichts geht mehr, obwohl es doch gerade eben noch ging. Normalerweise hat man ja sein Programm als erstes im Verdacht, aber das ist nicht unbedingt der Fall. \item Der Abstand zwischen den Stationen spielt eine Rolle, vor allem auf dem Schreibtisch. Die Wellenlänge bei $434$\,MHz beträgt knapp $70$\,cm. Stationen, die auf dem Schreibtisch stehen, sind normalerweise näher zusammen. Die Situation kann sich stark verändern, wenn man die Stationen verrückt oder dreht. \item Ich habe mich lange gescheut, Antennen ($17$\,cm Draht) zu spendieren, weil ja bei Abständen von ein paar $20$\,cm alles auch so funktioniert. Dachte ich zumindest. Und manchmal hat es ja auch funktioniert. Aber Antennen dran und die Sendeleistung reduzieren (z.B.\,$-12$\,dB), dann klappt das viel besser. %\item das Empfängermodul/Programm (Abholung der Daten) hängte sich % regelmäßig komplett auf. %\item Die sendenden Stationen machen sich ohne weitere Maßnahmen zeitweise % ihre Telegramme gegenseitig kaputt (Uhrendrift, gleichzeitig senden ohne % vorher zu lauschen, ob der Luft rein ist.) %\item Wenn ich in der sendenden Station das rfm12 Modul abschalte % (\texttt{\_w\_pwr low}), dann steigt der Stromverbrauch von $40$ auf % $190$\,mA (primär an $12$\,V). Sehr erstaunlich, weil eigentlich wollte % ich damit doch den Verbrauch reduzieren. Mit \texttt{\_w\_pwr pin\_highZ} % funktioniert das auch gleich viel besser. \end{itemize} \end{multicols} % -------------------------------------------------------------------- \section{Referenzen} \begin{enumerate} %\item \label{Adv1} E. Wälde, Adventures in Forth, Die 4. Dimension 3/2006, Jahrgang 22 % gforth-ec r8c, i2c von Hand, Thermometer %\item \label{Adv2} E. Wälde, Adventures in Forth 2, Die 4. Dimension 4/2006, Jahrgang 22 % timeup Uhr und Kalender, twotask %\item \label{Adv3} E. Wälde, Adventures in Forth 3, Die 4. Dimension 1/2007, Jahrgang 23 % usart0, redirection %\item \label{Adv4} E. Wälde, Adventures in Forth 4, Die 4. Dimension 1/2007, Jahrgang 23 % dcf-77 Uhr %\item \label{Adv5} E. Wälde, Adventures in Forth 5, Die 4. Dimension 4/2008, Jahrgang 24 % Umstieg auf amforth, bit flags, sensor:, filter_mean: %\item \label{Adv6} E. Wälde, Adventures in Forth 6, Die 4. Dimension 1/2011, Jahrgang 27 % rs485, -emit, mpc %\item \label{Adv7} E. Wälde, eine einfache Liste, Die 4. Dimension 2/2011, Jahrgang 27 % list.add list.walk %\item \label{Adv8} E. Wälde, amforth: Wortliste sperren, Die 4. Dimension 3/2011, Jahrgang 27 % also sealed %\item \label{r8c-ds} Renesas R8C/13 datasheet auf \url{www.renesas.com} %\item \label{Koenig} A.\ König und M.\ König, Das PICmicro Profi Buch, Franzis % Verlag 1999, ISBN 3-7723-4284-1 %\item \label{SPelc} Stephen Pelc, Programming Forth, \\ \url{http://www.mpeforth.com/arena/ProgramForth.pdf} %\item \label{Deliano} \url{http://www.embeddedforth.de/emb3.pdf} S.\ 9 %\item \label{dcf} \url{http://de.wikipedia.org/wiki/DCF77} und Verweise darin %\item \label{willem} ByteForth von Willem Ouwerkerk,\\ \url{http://www.forth.hccnet.nl/byteforth.htm} \item \label{amforth} \url{http://amforth.sourceforge.net/} %\item \label{ron} Ron Minke, Forth von der Pike auf Die 4. Dimension 3+4/2005 \ldots 4/2006, sowie Sonderheft AVR und 3+4/2007 %\item \label{namedbits} M. Kalus, M. Trute, Named Bits, Die 4. Dimension 2/2007, Jahrgang 23 %\item \label{lubos} Lubo\v{s} P\v{e}kn\'{y}s Seite: \url{http://www.forth.cz} %\item \label{RS485} Wikipedia (RS485) \url{de.wikipedia.org/wiki/RS485} %\item \label{RS485a} \url{www.mikrocontroller.net/articles/RS-485} %\item \label{g4.fs} Michael Kalus: g4.fs \url{www.forth-ev.de/repos/g4/g4.fs} %\item \label{atmega32} atmega32 Datenblatt (doc2503.pdf) \url{www.atmel.com} % %\item \label{brodie1} Leo Brodie --- Starting Forth, 1987, Prentice Hall, S.\,219ff %\item \label{rather} Elizabeth D.\ Rather --- Forth Application Techniques, 2006, Forth Inc., S.\,107ff %\item \label{vack} Gert--Ulrich Vack --- Programmieren mit FORTH, 1990, Verlag Technik Berlin, S.\,189ff \item \label{pollin} \url{http://www.pollin.de} \item \label{techoline} technoline TX3-TH o.ä. \item \label{ism} \url{http://de.wikipedia.org/wiki/ISM-Band} \item \label{spibus} \url{http://de.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus} \item \label{mikrocontrollernet} \url{http://mikrocontrollernet.de} \item \label{mic-net} \url{http://www.mikrocontroller.net/articles/RFM12} \item \label{hoperf} \url{http://www.hoperf.com} \item \label{rfm12.datasheet} \url{http://www.hoperf.com/upload/rf/RFM12.pdf} \item \label{rfm12.sample.code} \url{http://www.hoperf.com/upload/rf/RF12_code.pdf} \item \label{elektor} Funk für den Controller --- Elektor Januar 2009 (\url{www.elektor.de}) \item \label{snap} \url{http://www.hth.com/snap/} \end{enumerate} %\end{multicols} \newpage % -------------------------------------------------------------------- \section{Listings} \begin{quote} \begin{small} \begin{multicols}{2} \listinginput[1]{1}{2011-03/adv9/adv9_1.fs} \listinginput[1]{1}{2011-03/adv9/spi.fs} \listinginput[1]{1}{2011-03/adv9/rfm12.fs} Die folgenden Zeilen müssen in der Datei \verb|dict_appl.inc| hinzugefügt werden: \listinginput[1]{1}{2011-03/adv9/dict_appl.inc} \end{multicols} \end{small} \end{quote} \end{document}