www.mikrocontroller.net

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


Autor: geloescht (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht hilft dir das weiter:
http://www.embeddedforth.de/emb6.pdf

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: geloescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Beitrag wurde auf Wunsch des Autors geloescht.

Autor: thkaiser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mathias G. (mgiaco82)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.