Hallo!
Folgende Funktion belegt fast 50% Speicher in einem ATTiny2313. Ich
kenne mich mit Embedded-Programmierung noch nicht so gut aus ... mache
ich da was falsch?
(ReceivedBits ist ein Array mit den empfangenen Bits, receivedBitsIndex
ist der Index des Startbits)
Optimierung einschalten, dann brauchts (aufgrund unvollständigen
Quellcodes testweise auf eine compilierbare Version umgemodelt..) nicht
mehr 1236 Bytes sondern nur noch etwa 658, also etwa ein Drittel statt
weit mehr als die Hälfte.
Wenn das nicht langt musst Du mehr Code zeigen.
> Dürfte schon Müll produzieren. 10,20,40 sollten mit Sicherheit> 0x10,0x20,0x40 sein.
Diese Behauptung ist mit Sicherheit falsch :-) Kuckst Du Referenz, steht
drin dass richtig ist.
Das ganze Rumdividieren (%) ist teuer bzw knabbert kräftig am Speicher,
die Multiplikationen tun ein restliches. Für ne DCF-Implementierung in C
würd ich so 300-350 Bytes veranschlagen. (Nur der reine DCF-Kram, also
bit-erkennung, Erkennung 59. Sekunde, BCD-Decodierung, Parity und
Fehlerbehandlung).
Eigentlich ist es besser, das alles "online" auszuwerten als
zwischenzuspeichern.
Im Anhang nur mal als Anregung. Bei Fragen: Fragen
Die zeile hat
a) Durch den Modulo eine Division drinnen und da der Wert kein
vielfaches von 2 ist, bekommst du hier eine SW-Division rein. Das kostet
dir sowohl viel Rechenzeit als auch viel Speicher.
b) Das *40 erzeugt dir wiederrum ein Multiplikator. Ich weiß nicht aus
dem Stegreif heraus, ob der Tiny ein Hardware Mul befehl hat, wenn
nicht, siehe Punkt a.
Einfacher und besser wirst du es decodieren können, wenn du jedes bit
mittels eines if-konstruktes abfragst. Wäre dann
Dann, wofür brauchst du eigentlich den Modulo? Ringbuffer? Wenn ja, dann
hast du die Größe deines Buffers extrem schlecht gewählt. Und vor allem,
in diesen passen nur 1 Paket rein, d.h. du kannst dir das ganze Spiel
mit dem Ringbuffer ersparen (und damit den Overhead für das Modulo). Ein
DCF Paket fängt immer bei index 0 an und dann kannst du deine Pulse
eines nach dem Anderen auslesen.
grüße
Simon
@Johann:
Der Quellcode sieht ziemlich böse aus...
Wo sind die Kommentare? ;-)
@Simon:
Ich habe mal das "? 40 : 0"-Konstrukt eingebaut. Da ist der
Speicherbedarf gleich nochmal um 2% gestiegen :-(
Kiaa schrieb:> @Johann:> Der Quellcode sieht ziemlich böse aus...> Wo sind die Kommentare? ;-)
Im Quellcode. Die beiden lezten Funktionen sind noch nicht dokumentiert.
Sie kümmern sich um Bit-Anfang bzw. -Ende.
Die Ticks-Funktion wird 100x pro Sekunde aufgerufen mit dem Wert vom
Port (bitte nicht aus einer ISR raus :-)). Eine "1" ist also 20 Ticks
lang und eine "0" 10 Ticks. Die Toleranz ist bei +/- 3 Ticks, daher die
10+3 bzw, 10-3.
Die eigentliche DCF-Decodierung ist in der ersten Funktion. Ein Bit
gehört zu einem bestimmten Byte in der time-Struktur. Der Byte-Index
wird in der Tabelle am Anfang nachgeschaut, die zu jedem Bit angibt, zu
welchem Byte es gehört. Ist das Bit gesetzt, wird zu diesem Byte der
Bit-Wert (1,2,4,8,10,20,40,80) addiert. Das ist alles, also keine böse
Magie...
Johann L. schrieb:> Eigentlich ist es besser, das alles "online" auszuwerten als> zwischenzuspeichern.
Stimmt.
Bei ner wahnsinns Datenrate von 1Bit/s langweilt sich die CPU zu Tode.
Wenn man die Bits gleich dekodiert (Zeit+Datum), braucht man dafür etwa
140 Bytes Code.
Beitrag "DCF77 Uhr in C mit ATtiny26"
Peter
> Die Ticks-Funktion wird 100x pro Sekunde aufgerufen
Wieso das?
Ich gehe mal davon aus, dass der Attiny auch ein bis zwei 8- oder 16-Bit
Timer mitbringt.
Das DCF77-Signal legst du an einen Interrupt-Eingang. In der ISR fragst
du den Stand des Timers ab und setzt ihn wieder auf zurück.
Vorher definierst du, welche Timer-Werte 100 bzw. 200ms entsprechen.
Wenn du den Startwert geschickt definierst, kannst du den Timer dazu
bringen bei fehlendem Signal (oder der 59. Sekunde) überzulaufen.
In der zugehörigen ISR kannst du dann gleich die Daten auswerten oder
manuell die Zeit hochzählen.
Löwe schrieb:>> Die Ticks-Funktion wird 100x pro Sekunde aufgerufen>> Wieso das?
Weil sich das sehr bequem auswerten läßt, es reicht ein Byte als
Zählvariable aus.
Außerdem kann dieser Timerinterrupt gleich die interne Quarzuhr zählen,
da der DCF77 Empfang öfters mal gestört sein kann.
Peter
Johann L. schrieb:> Für ne DCF-Implementierung in C> würd ich so 300-350 Bytes veranschlagen. (Nur der reine DCF-Kram, also> bit-erkennung, Erkennung 59. Sekunde, BCD-Decodierung, Parity und> Fehlerbehandlung).
Wofür den ganzen Speicher? Ich brauche für DCF-Dekodierung, zweifache
Plausibilitätsprüfung und Echtzeituhr mit Datum ca. 50Bytes. Das ganze
funktioniert (eingeschränkt) sogar schon auf einem PIC 16F84. Natürlich
ist das in ASM programmiert. Das C so sehr Resourcen verschlampt, hätte
ich nicht für möglich gehalten.
spess53 schrieb:> Wer C kennt, nimmt Assembler,
@spess53: Ist das wirklich so schlimm? Ich programmiere bisher nur in
ASM, brauche jedoch für ein Projekt eine Hersteller-Lib, die nur in C
vorliegt und muss mich entsprechend in C einarbeiten. Wenn C jedoch
einem mehrfach höheren Variblen(RAM)bedarf hat, komme ich doch nie über
die Runden...
Hi
>@spess53: Ist das wirklich so schlimm? Ich programmiere bisher nur in>ASM,...
Ich auch. Vor einiger Zeit habe ich mal einen Test gemacht und ein
kleines Programm in C (fast stundenlang auf minimalen Code getrimmt), in
ASM ,sehr großzügig und korrekt, und in ASM auf minimale Codegröße
getrimmt, programmiert. Die erreichten Codegrößen waren 162:110:56 Byte.
>Wenn C jedoch einem mehrfach höheren Variblen(RAM)bedarf hat, komme ich>doch nie über die Runden...
Das ist meines achtens nur bedingt ein Problem von C, eher ein Problem
der Programmierer, die glauben, nur weil ein Programm funktioniert, das
Programm auch gut ist.
MfG Spess
Peter Dannegger schrieb:> Wenn man die Bits gleich dekodiert (Zeit+Datum), braucht man dafür etwa> 140 Bytes Code.>> Beitrag "DCF77 Uhr in C mit ATtiny26"
Irgendwas mach ich dann falsch, ich brauch da knapp 300 Bytes...
Wenn ich dein Projekt mit avr-gcc -Os übersetzte, ergeben sich für das
dcf77-Modul rund 320 Bytes, sowohl für avr-gcc 4.3 als auch für die
ältere 3.4, für die das Projekt wohl geschrieben wurde. Ein Byte rechne
ich mit 8 Bit.
Löwe schrieb:>> Die Ticks-Funktion wird 100x pro Sekunde aufgerufen>> Wieso das?
Viele meiner Projekte haben einen Grundtakt von 100 Hz, in der
Anwender-Aufgaben erlegigt werden. Alle 10ms werden in einer ISR
verschiedene Jobs erlegit:
o Taster abfragen: liefert automatisch die Entprellung, Interrupts oder
spezielle Ports werden so nicht benötigt. Das macht die Software
einfach auf neue Projekte mit anderen Layouts anpassbar, wo
man vielleicht keine IRQ-Ports mehr hat. Ausserdem sinkt so die
IRQ-Last des Systems.
o Dito für DCF. Es wird nur das Bit eingesammelt und in der main-Loop
ausgewertet die main-Loop ist natürlich nicht-blockierend. Wenn doch,
hat man ein Design-Problem
o Countdown-Zähler runterzählen, zB für LED-Blinken, Bildschirmschoner,
Sound-Ausgabe, ...
o weiß der Teufel...
Rainer Unsinn schrieb:> Johann L. schrieb:>> Für ne DCF-Implementierung in C>> würd ich so 300-350 Bytes veranschlagen. (Nur der reine DCF-Kram, also>> bit-erkennung, Erkennung 59. Sekunde, BCD-Decodierung, Parity und>> Fehlerbehandlung).>> Wofür den ganzen Speicher? Ich brauche für DCF-Dekodierung, zweifache> Plausibilitätsprüfung und Echtzeituhr mit Datum ca. 50Bytes.
Also mit höchstens 25 Assembler-Befehlen einen kompletten
DCF-Decoder...?
Ein paar Byte ist mir ein portierbarer Ansatz schon wert. Mein Modul hat
keinerlei Abhängigkeiten von der Hardware (Ports, Timer, IRQs, ...) und
ein einfaches Interface: Alle 10ms ein Bit rein, Zeit raus.
Die Abhänhigkeit von avr-gcc, die momentan noch drinne ist, kann einfach
so herausparametrisiert werden, was die Verständlichkeit aber nicht
unbedingt erhöht
Johann L. schrieb:> Also mit höchstens 25 Assembler-Befehlen einen kompletten> DCF-Decoder...?
Natürlich nicht. Ich bin vom RAM-Bedarf ausgegeangen. Man sollte den
Text eben richtig lesen.
Rainer Unsinn schrieb:> Johann L. schrieb:>> Also mit höchstens 25 Assembler-Befehlen einen kompletten>> DCF-Decoder...?>> Natürlich nicht. Ich bin vom RAM-Bedarf ausgegeangen. Man sollte den> Text eben richtig lesen.
Ah, ok, mein Fehler. Oben war nur die Rede von "50% µC ist voll" und
Größen, die für ein ATtiny2313-RAM nicht in Frage kommen... AFAIR hat er
128 Bytes
Meine Implementierung schluckt 31 Bytes an RAM incl. Stack-Bedarf und
Empfang von Sommer-/Winterzeit-Kennung. Wenn man letztere nicht will kan
man da noch sparen. Einige Stati könnte man in Bitfelder packen, aber
dann würde vermutlich der Flash-Bedarf weiter steigen.
Das Problem ist eindeutig das %59 udn, dass du es in jeder Indizierung
machst. Und das in der Menge. Da du sowieso nur innerhalb der erste
beiden Vielfachen bleibst kannst du da auch unter C einiges rausholen.
Immerhin bleiben von der Software-Division nur noch ein bissle natives
Zeug übrig.
Wie groß kann z werden für x = z*59 + R. Wie kann mit diesen beiden z
das R mit einfachen Operationen ausgerechnet werden? Und wie oft ist
dieser Schritt nötig innerhalb einer Schleife? Bei jeder Indizierung,
oder nur der Test jedes mal und die Korrektur einmal. Kann man den
Zeitpunkt der Korrektur auch noch vorhersagen?
Wenn man C nicht aufgeblähten allgemein zu geltenden Code aufbürgt, dann
kann der auch schmalen, dem Problem entsprechendes Kompilat erzeugen.
Eine Sache die bei dieser Diskusion nicht beleuchtet wurde ist die
Verwendung des GCC Compilers. Er ist gut, aber er ist auch eine
Eierlegendewollmilchsau. Ich meine damit, dass die Optimierung noch
besser geht.
Wer vielleicht mal etwas Zeit hat sollte sich den IAR Compiler angucken.
Es gibt sogar eine 4k-Version die für dieses DCF77 Problem durchaus
reichen sollte.
Johann L. schrieb:> Ah, ok, mein Fehler.
Nein, in dem Fall war es mein Fehler. Ich hatte den Beitrag irgendwie
nur halb gelesen und bin dadurch zu der Annahme gekommen, der TE meint
den RAM-Bedarf.