Hallo alle zusammen, bisher habe ich mich darauf beschränkt heimlich, still und leise im Forum rum zu stöbern und Euer Wissen zu schnorren ;o). Nun geht mir aber schlicht der Stoff aus, und ich sehe mich vor einem Problem, was wohl nur mit Erfahrung gut gelöst werden kann. Ich hab immer mal wieder diverse Controller programmiert, meist in Assembler. Eigentlich nie was Großes, eher so Gebastel und Spielereien. Nun habe ich eine konkrete Anwendung und habe beschlossen das in C zu programmieren, weil ja viel einfacher, und weil ich mich an ein größeres Projekt hier aus dem Forum wagen möchte, was eben so programmiert ist. Zum Einstieg habe ich daher erstmal was eigenes kleines angefangen, da ich zwar in C auch schon relativ viel Erfahrung habe, nur leider nicht auf Controller Basis. Soweit zu mir, jetzt zum eigentlichen Problem: Ich habe einen Bitstream von einem DCF77 Modul den ich auswerten möchte. Also habe ich zunächst in einem Array mit 60 Byte die einzelnen Bits als Boolean abgelegt und dann ausgewertet. Natürlich relativ ungeschickt, da ich für ein Bit ein ganzes Byte opfere und zudem das ganze in BCD rein kommt und es ziemlich dumm ist, ein nibbel zunächst in vier Boolean zu zerlegen, wenn man es anschließen dann wieder als nibbel haben will. Also habe ich in dem großen AVR Tutorial gestöbert und das geniale Konstrukt des Bitfeldes für mich endeckt um damit den Stream abzubilden. Die Idee: Über das dcfIn-Bit (sieh unten) jedes eingehende Bit über alle 8 Byte mit Hilfe des Carry-Bits weiter zu schiften (Inline-Assembler) bis das Telegramm vollständig ist, und dann ganz bequem über den .-Operator auf die einzelnen BCD-Werte zuzugreifen. Soweit die Theorie. Das Bitfeld //Bitfeld für 64 Bit typedef struct{ unsigned long long dcfRes:2; //Reservebits unsigned long long dcfNewPackage:1; //Neues Packet wurde empfangen unsigned long long dcfValid:1; //DCF Packet ist gültig unsigned long long dcfIn:1; //Eingangsbit zum Schiften unsigned long long dcfPDatum:1; //Letztes DCF Bit unsigned long long dcfJahr:8; unsigned long long dcfMon:5; unsigned long long dcfWd:3; unsigned long long dcfTag:6; unsigned long long dcfPStd:1; unsigned long long dcfStd:6; unsigned long long dcfPMin:1; unsigned long long dcfMin:7; unsigned long long dcfSb:1; //Startbit unsigned long long dcfSs:1; //Schaltsekunde unsigned long long dcfMez:1; unsigned long long dcfMesz:1; unsigned long long dcfSwitch:1; //erstes DCF Bit unsigned long long dcfRuf:1; unsigned long long dcf0_14:15; }typeDcf77Stream; Die Variable: typeDcf77Stream dcfBuffer; Das Schiften der 8 Byte mittels Inline-Assembler, wobei vorher das letzte Eingangsbit in das dcfIn hinterlegt wurde: asm volatile ( /*asm*/ "ldi r16 , 0x08" "\n\t" //Über 8 Byte "clc" "\n\t" "0:" "\n\t" // In einer Schleife "ld r2 , %a0" "\n\t" // den Inhalt des Adresszeigers "ror r2" "\n\t" // über Carry nach rechts schiften "st %a0+, r2" "\n\t" // und wieder abspeichern "dec r16" "\n\t" "brne 0b" "\n\t" // bis alle 8 Bytes durch "" "\n\t" : /*Output*/ : /*Input*/ "b"(&dcfBuffer) : /*Changed*/"r2", "r16" ,"memory" ); Der komfortable Zugriff: printf("\n%d: %d.%d.%d %d:%d",dcfBuffer.dcfPDatum,dcfBuffer.dcfTag, dcfBuffer.dcfMon,dcfBuffer.dcfJahr,dcfBuffer.dcfStd,dcfBuffer.dcfMin); Praktisch habe ich dann festellen müssen, dass meine Annahme, dass der Compiler das Bitfeld schön artig in der gegebenen Reihenfolge aufsteigende im Speicher ablegt, nicht zutrifft, wie ich dann später auch in einigen Posts hier gelesen habe. Idee soweit gescheitert. Hier habe ich auch den Hoffnungsvollen hinweis gelesen, dass es wohl Anweisungen gibt den Compiler hier zu beeinflussen, wobei da nichts weiter zu finden war. Meine Frage ist also, ob, und ggf. wie ich den Compiler hier beeinflussen kann, und ob es eine noch geschicktere Variante gibt, wie ich den Bitstream sammeln und comfortabel auf die Einzelnen Nibbel zugreifen kann. Vielen Dank schonmal, MfG, Nico
Mal nur so ne Idee: Die DCF-77 Bits kommen ja mit ner atemberaubenden ultra high speed von sagenhaften 1 Baud rein. Was spricht dagegen, jedes einzelne Bit "on the fly", also direkt nach Empfang auszuwerten ? Dann kann man ne wesentlich effektivere Struktur aus einzelnen Bytes (Minuten ... Jahre) definieren. So mache ich es jedenfalls. Peter P.S.: Der AVR-GCC kann zwar theoretisch long long, macht es aber jedoch sehr ungeschickt (ist sogar wesentlich teurer als float).
Hallo Peter, währe eine Idee. Bevor ich auf die Probleme mit der Reihenfolge im Speicher gestoßen bin, hielt ich dies für eine geschickte Lösung, da ich mir damit erspare mich im Telegramm zu orientieren und bei der Auswertung die einzelnen Bestandteile zu unterscheiden, da ja alle an einer definierten Stelle liegen. Du musst zugeben, das hat seinen Scharm ;o). Ich müsste dann nur die Werte in die Uhr rüber kopieren, wenn ich das Telegramm vollständig erhalten habe und habe somit immer ein konsistentes Abbild. Außerdem will ich das dann über I2C an eine RTC rausschieben, und den Bitstream wollte ich ähnlich zusammenbauen, wobei ich mir dazu noch keine weiteren Gedanken gemacht habe. Und wenn es so auch mit Tricks gehen würde, fänd ich die Lösung echt gut. MfG, Nico
Nico Spieckermann wrote: > Ich müsste dann nur die Werte in die Uhr rüber kopieren, wenn ich das > Telegramm vollständig erhalten habe und habe somit immer ein > konsistentes Abbild. Das mußt Du in jedem Fall machen, denn die empfangene Zeit wird ja erst zum 0. Sekundenimpuls des nächsten Datenpakets gültig. Nicht, daß Du noch die Silvesterraketen zu früh abfeuerst. Peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.