Forum: Mikrocontroller und Digitale Elektronik RC5-Decoder Quellcode Verständnisprobleme


von anubis (Gast)


Lesenswert?

Hi ich habe mal ein paar Fragen zu dem Code eines RC5-Decoders, das 
ursprüngliche Projekt kann man unter 
http://www.roboternetz.de/wissen/index.php/RC5-Decoder_f%C3%BCr_ATMega 
betrachten, ich habe das ganze ein bisschen (stümperhaft) an die GCC 4 
Version angepasst und auch zum Laufen gebracht, leider weiß ich nicht 
WARUM es läuft ;-)
Ich habe meinen Code mal hier gepostet
C Datei: http://nopaste.debianforum.de/7636
Header Datei: http://nopaste.debianforum.de/7637

Meine erste Frage:

Zeile 30 ##define RC5_TICKS ((uint8_t) ((uint32_t) (F_CPU / 1000 * 
RC5_BIT_US  1000  RC5_PRESCALE)))

Warum wird hier 2 mal gecastet? Ich sehe bei diesem Codeteil keinen Sinn 
darin...
bei F_CPU von 1Mhz = 10^6 müsste das Ergebnis 27 sein richtig?? heißt 
das, dass man 27 Controller Takte braucht um die Zeitdauer eines 
RC5-Bits zu durchlaufen? Wie kommt man auf die Rechnung??

Hier noch die Beschreibung des RC5-Standards: 
http://www.roboternetz.de/wissen/index.php/RC5-Code
Danke für eure Hilfe
Greetz Anubis

von Matthias Kölling (Gast)


Lesenswert?

Hallo!

#define RC5_BIT_US   (64*27)
Bei RC5 wird die Information auf eine Trägerfrequenz aufmoduliert. Ein 
Bit besteht immer aus einem High- und einem Low-Teil. Die Phasenlage 
gibt dann die Bedeutung ob High oder Low an. Ein Halbbit hat immer 32 
Schwingungen der Trägerfreuenz. Damit hat ein ganze Bit 64 Schwingungen. 
Die 27 scist dann Dauer einer Trägerschwingung. (da käme ich dann auf 37 
kHz, was mir etwas komisch erscheint, weil ich eher mit 36 oder 38kHz 
gerechnet hätte)
Somit beschreibt der Ausdruck die Länge eines Bits in µs. Die 
Trägerfrequenz wird übrigens vom Empfänger eliminiert.

#define RC5_TICKS \ ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 
1000 / RC5_PRESCALE)))
Die Berechnung wird dazu genutzt, die µs in Takte des Timers (nicht der 
CPU) umzurechnen. Die casts müsstest Du Dir eigentlich selbst erklären 
können, wenn Du etwas Programmiererfahrung hast. Es ist doch klar, dass 
F_CPU selbst bei 1MHz also 1 000 000 niemals in ein uint8_t passt. Durch 
die Divisionen ergibt sich dann ein Wert, der klein genug ist, dass er 
in 8 bit passt. Dieser cast wird gemacht, damit der Controller, er hat 
ja nur 8 bit, nicht den unnötigen Ballast mitschleppen muss.

Respekt, wenn Du ohne diese Kenntnisse das Programm zum Laufen gebracht 
hast. Ich habe letzte Woche das gleiche für ein Sony-Protokoll gemacht 
und war schon am Verzweifeln. Letztendlich war es eine falsche 
Subtraktion.

Gruß Matthias

von anubis (Gast)


Lesenswert?

hmm also um genau auf 32kHz zu kommen müsste man 31,25 nehmen, heißt das 
dann dass man eigentlich auch 64*32 nehmen könnte und es müsste immer 
noch funktionieren und hier wurden halt 27 genommen, dass man noch ein 
bisschen mehr Spiel hat??

von anubis (Gast)


Lesenswert?

zur Zeile 30: im Prinzip ist die Rechnung ja so: (Takte die der Mega8 
pro Sekunde gibt) * (Dauer eines bits) / (Vorteiler, da ich ja nur jeden 
64. Takt zähle) warum teile ich die Takte und die Dauer dann nochmal 
durch 1000?
Das Casten macht bei 1MHz meines Erachtens aber keinen Sinn, da ich ja 
erst alles ausrechne und dann erst caste und bei einem Gesamtergebnis 
von 27 reicht mir ein 8 bit Datentyp ja locker aus. Oder ist es so, dass 
man als "ersten" Datentyp immer den größten der gesamten Rechnung nehmen 
muss?

Was ich leider immer noch nicht verstehe ist warum ich überhaupt von 
einem großen in einen kleinen caste, angenommen ich habe das Ergebnis 
500 und behalte dann nur die hinteren 8 bit, dann erhalte ich als 
Ergebnis ja 244, was ja ein TOTAL anderer Wert ist??

Ich sollte dazu sagen, dass ich aus der Java Programmierung komme und 
mich bisher in keinster weise um einzelne Bits gekümmert habe ;-)

von Matthias Kölling (Gast)


Lesenswert?

Der cast auf uint32_t schließt die ganze Rechnung ein. Das heißt, dass w 
ä h r e n d dieser Berechnung mit 32 bit gerechnet wird, da manche 
Operanden doch recht groß sind. Erst n a c h der Berechnung liegt ein 
Ergebnis vor, dass wieder auf 8 bit gecastet werden kann.

Warum 2 mal durch 1000 teilen? - ist auch einfache Mathematik! Das 
define für F_CPU gibt die Takte pro S e k u n d e an. Dein define für 1 
Bit ist in µs angegeben. Zwei mal durch 1000 teilen heisst durch 1 
Million teilen. Und 1µs ist eine millionstel Sekunde. Warum teilt man 
nicht gleich durch 1 Million wirst Du fragen. Das ist ganz einfach: Bei 
Ganzzahlberechnungen sollte man immer erst die Multiplikationen und dann 
die Divisionen ausführen, um keine Auflösung zu verlieren. Das ist in 
dem Makro natürlich nicht ganz konsequent gemacht - aber sei's drum.
Als kleines Beispiel rechne doch mal 1050 / 100 * 3 bzw. 1050 * 3 / 100 
ganzzahlig. Der Unterschied ist 30 zu 31.

Wenn Du sicher bist, dass Dein System mit 32kHz Trägerfrequenz arbeitet, 
dann kannst Du das define natürlich anpassen. Dein Code funktioniert bei 
Dir aber trotzdem, weil als Toleranz immer die Mitte eines Halbbits 
genommen wird. Da bei jeder Flanke neu gemessen wird akkumuliert sich 
der Fehler auch nicht auf.

Gruß Matthias

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.