Hallo AVRler,
ich habe gerade ein Projekt, bei dem bidirektional Daten über eine
größere Distanz übertragen werden müssen. Leider steht dafür lediglich
eine einzige Ader zur Verfügung, so dass Kreativität gefragt war.
Zum Glück konnte ich das Problem inzwischen lösen. Im Anhang befindet
sich das Ergebnis:
Eine leicht portierbare Software in C, die den differentiellen
Manchestercode implementiert. Dieser ist dadurch gekennzeichnet, dass er
den Takt mitüberträgt. So wird eine binäre Null durch zwei Flanken, eine
binäre Eins aber nur durch eine Taktflanke gekennzeichnet.
Damit der Empfänger die Taktrate des Senders ermitteln kann, wird vor
jedem Datum ein Startbit als 0 gesendet, so dass dabei zwei Flanken
entstehen, an denen die Bitrate des Senders im Empfänger gemessen werden
kann. Anschließend können zwischen 1 und 16 Bit Daten übertragen werden.
Der Code beinhaltet Sender und Empfänger in einem (schließlich ist es ja
bidirektional). Gesendet wird einfach durch Aufruf der Routine
suart_putc, empfangene Daten werden der Anwendung durch eine
Callbackfunktion übergeben.
Vor dem Verwenden unbedingt die Datei "suart_hw.h" anpassen (ausführlich
Erklärt). In einer Zielanwendung könnte das Programm dann z.B. so
aussehen:
suart_hw.h: --Auschnitt--
1 | #define SUART_INPUT_HANDLER(x) suart_rx_handler(x)
|
2 | void suart_rx_handler( uint16_t x );
|
main.c:
1 | #include "suart.h"
|
2 | #include <stdint.h>
|
3 | #include <avr/delay.h>
|
4 |
|
5 | void main( void ) {
|
6 | DDRB = 0xFF; // Ausgabe der empfangenen Daten hier
|
7 | suart_init();
|
8 |
|
9 | while(1) {
|
10 | suart_putc( 0x12 );
|
11 | _delay_ms( 20 );
|
12 | }
|
13 | }
|
14 |
|
15 | void suart_rx_handler( uint16_t x ) {
|
16 | PORTB = (x & 0xFF); // AUsgabe der Daten an PORTB
|
17 | }
|
Zum einfachen Demonstrieren bräuchte man zwei Controller, die man
einfach verbindet und die unterschiedliche Werte senden. Dann erscheint
an beiden Controllern immer der Wert an PORTB de zuletzt empfangen
wurde. Da beide Controller unterschiedliche Werte senden (z.B. 0x12 und
0x34), wird sich der PORTB also ändern.
Das Modul unterstüzt ein lokales Echo. Dies kann z.B. dazu dienen, die
gesendeten Daten zu überprüfen und notfalls nochmal zu senden (bei
Kollisionen). Das zurückgegebene Datum wurde vom Bus eingelesen und
enthält unter Umständen auch Fehler, wenn die Leitung bswp.
zwischendurch Kurzgeschlossen wird.
Kollisionen treten äußerst selten auf, da die kritische Zeit sehr kurz
ist. Werden viele Knoten angeschlossen, ist es u.U. Ratsam, einen
Zufallsanteil in die Wartedauer nach dem Freiwerden des Busses
einzubauen.
Der Code unterstüzt auch das Senden von Paketen. Dies wird erreicht,
indem ein nicht sendender Knoten einen sendenen Knoten erst nach einer
Totzeit auf dem Bus unterbrechen darf. Während dieser Totzeit hat der
sendene Knoten Zeit, sein Paket (welches dann aus mehreren
suart_putc()-Aufrufen besteht) fortzusetzten.
Konstruktive Kritik und Kommentare erwünscht!
Clemens