Forum: Mikrocontroller und Digitale Elektronik Manchester Code - wer kann mir mal helfen?


von geloescht (Gast)


Angehängte Dateien:

Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von crazy horse (Gast)


Lesenswert?

vielleicht hilft dir das weiter:
http://www.embeddedforth.de/emb6.pdf

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Hi Guido,

das Dekodieren ist eigentlich sehr einfach, wenn man erstmal synchron 
ist.

Wenn Du bei jedem Startbyte neu synchronisieren willst, sollte es mit 
01xxxxxxb anfangen. D.h. Du wartest so lange, bis eine lange Pulszeit 
erkannt wird.
Bei 400 Zyklen Takt, läßt Du T0 mit Vorteiler 1/64 laufen, dadurch 
ergeben sich T0-Werte von 6 bzw. 12.

Und wenn Du dann synchron bist, kannst Du ähnlich wie meine RC5-Routine 
die weiteren Bits empfangen.
Statt im Timerinterrupt eben im externen Interrupt und statt rc5_time 
wertest Du CT0 aus und statt 13 Bits eben alle 8 Bits.

Damit Du auch sicher auf 01xxxxxxb synchronisieren kannst, sollte davor 
ein 00000000b Byte gesendet werden.


Peter

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von Peter D. (peda)


Lesenswert?

Ja, diesen Unsinn mit dem 3/4-Takt machen die meisten.
Ist aber unnötig und viel zu kompliziert.

Wenn Du Dir mal das Taktdiagramm genauer ansiehst, merkst Du, daß eine 1 
immer bei einem 1-0 Wechsel und eine 0 immer beim 0-1-Wechsel erfolgt. 
D.h. der invertierte Zustand nach dem Wechsel ist bereits das Bit !

Du must bloß eben die Hilfimpulse ausblenden, die bei 00 oder 11 
benötigt werden. Und das geht am einfachsten, wenn Du sie ignorierst, 
weil sie zu kurz sind:


static unsigned char old_ct0, data, bitcount;

if( (TCNT0 - old_ct0) < 8 ) // zu kurz
 return;
old_ct0 = TCNT0;
data <<= 1; // schieben
if( (PIND & 1<<PD2) == 0 ) // nach 1-0-Wechsel
 data++; // bit = 1 setzen
if( --bitcount == 0 ){
 dataout = data; //1 byte fertig
 bitcount = 8; // die naechsten 8 bits
}

usw.

TCNT0 muß man auch setzen können (in Assembler geht es).
Aber oft braucht man den Timer ja noch für andere Sachen. Deshalb ist es 
besser, man läst ihn durchlaufen und merkt sich einfach den alten Stand. 
Dann hat man mit (TCNT0 - old_ct0) die vergangene Zeit seit dem letzen 
old_ct0 = TCNT0;.


Peter

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von Peter D. (peda)


Lesenswert?

Der Interrupt muß natürlich auf beide Flanken triggern.
Bei einigen AVRs ist dafür nötig, die Flankenerkennung bei jedem 
Interrupt umzuschalten. Dann muß man auch nochmal den Pegel des Pins 
prüfen ob nicht gerade während des Umschaltens eine Flanke 
durchgerutscht ist.

Dann funktioniert die 1- und 0-Erkennung ohne Probleme.

Sieh Dir doch Dein eigenes Taktdiagramm mal an und denke alle 
Flankeninterrupts weg, die zwischen den Bits sind.

Der Manchestercode ist auch sehr tolerant in Bezug auf die Frequenz. Bei 
Deinem Beispiel muß man nur erkennen, ob die Zeit ~6 oder ~12 ist und 
das macht die Zeile:

if( (TCNT0 - old_ct0) < 9 ) // zu kurz
 return;
old_ct0 = TCNT0;

Eine genauen Timer braucht man also nicht.
Du kannst sogar AVRs mit internem RC-Oszillator nehmen.


Peter

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von Peter D. (peda)


Lesenswert?

Zu den Zahlen:

Du must nichts berechnen, das kann doch alles der Compiler für Dich tun:

#define XTAL 8e6 // 8MHz

#define T0_PRE 64 // Vorteiler 1/64

#define MAN_BAUD 20e3 // Manchester mit 20kHz

// und jetzt laß ihn rechnen:

#define T0_MAN_SHORT ((unsigned char)(XTAL  MAN_BAUD  T0_PRE)) //= 6 
(6,25)

#define T0_MAN_LONG (2 * T0_MAN_SHORT) //= 12

#define T0_CHECK_LONG_SHORT ((T0_MAN_SHORT + T0_MAN_LONG) / 2) //= 9

if( (TCNT0 - old_ct0) < T0_CHECK_LONG_SHORT ) // zu kurz
 return;
old_ct0 = TCNT0;


Also mit 9 bist Du in der Mitte zwischen kurz und lang. Damit hast Du 
die maximale Toleranzbreite.


Wenn der Impuls kurz ist, dann kommt return bevor old_ct0 neu gesetzt 
wird. Dadurch wirds mit dem nächsten kurzen als ein langer erkannt, die 
Hilfsflanke zwischen den Bits wurde also ausgeblendet.

Ist der Empfänger noch nicht synchronisiert, kann es sein, daß gerade 
ein kurzer ausgeblendet wurde, bevor der lange vom Startbyte kommt. Dann 
sind eben 6+12=18 Takte von CT0 vergangen, aber das ist ja auch >9 und 
wird somit erkannt.
Danach ist dann alles synchron.

Ich hoffe, das war jetzt verständlich.



Peter

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von geloescht (Gast)


Lesenswert?

Dieser Beitrag wurde auf Wunsch des Autors geloescht.

von thkaiser (Gast)


Lesenswert?

Ich habe eine noch viel einfachere Methode. Ist zwar kein "sauberer" 
Manchester-Code, aber man kann sich viel Software-Bastelei sparen. Ich 
wandle jedes zu übertragende Byte in zwei Bytes Manchester um - das ist 
eine einfache Bit-Schieberoutine, und sende diesen Code über den 
stinknormalen UART raus. Zwar hat man dann Start- und Stop-Bit mit drin 
und auch die Timing-Toleranz wird schlechter, aber es funktioniert. 
Beispiel: Ein Byte $CA = 0b11001010 wird umgewandelt in die Bytes 
0b10100101 und 0b10011001, über den UART gesendet, auf der 
Empfängerseite empfangen und dekodiert. Um ungültige Übertragungen 
auszufiltern, schaut man sich die empfangenen Daten einfach 2-Bit weise 
an: 10 = 1, 01 = 0, 11 und 00 sind ungültig und damit fehlerhaft. Die 
Synchronisation mache ich über eine gezielte Sendung eines fehlerhaften 
Bytes mit Kennung.

von Mathias G. (mgiaco82)


Lesenswert?

Hallo eine Frage zu dem Code von oben.

Was macht man eigentlich wenn TCNT0 wechselt, also ich meine nach dem
überlauf fängt er ja wieder bei null an. Dadurch gibts doch einen
Fehler bei

current_t=TCNT0-last_t; // Timer merken

oder sehe ich da was falsch?

mfg mathias

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.