C-Programmierung/DCF77

Gast #4897899
Heyho,

ich bin gerade dabei, an einen uController ein DCF77 Empfänger-Modul 
anzuschließen. Das klappt auch alles wunderbar. Über UART(meine 
Debug-Schnittstelle) sehe ich auch, dass ich die Daten richtig empfangen 
habe. Nur der entsprechende C-Code dazu schaut "schrecklich" aus. Gibt 
es irgendwelche Tipps, wie man den vereinfach könnte?

DCF77 sendet in 1min 59Bits, die ich in ein Array(dcf77_rx[59)] 
speichere.
Um jetzt z.B. die Parity-Bits bzw. feste Bitwerte zu überprüfen, ob ich 
alles Richtig empfangen habe, schaut mein Code so aus:
1
if((dcf77_rx[0] == 0) && (((dcf77_rx[29]+dcf77_rx[30]+dcf77_rx[31]+dcf77_rx[32]+dcf77_rx[33]+dcf77_rx[34]+dcf77_rx[35]) % 2) == 0) && (((dcf77_rx[21]+dcf77_rx[22]+dcf77_rx[23]+dcf77_rx[24]+dcf77_rx[25]+dcf77_rx[26]+dcf77_rx[27]+dcf77_rx[28]) % 2) == 0) && (dcf77_rx[20] == 1))
2
    {

Oder um das Datum(BCD-Codiert) in Dezimalzahl umzuwandeln
1
date_day = dcf77_rx[36] + 2*dcf77_rx[37] + 4*dcf77_rx[38]+ 8*dcf77_rx[39] + 10*dcf77_rx[40] + 20*dcf77_rx[41];

Kann man das irgendwie vereinfacht/leserlicher schreiben/darstellen?
Gast #4897935
Als ersten Schritt: Berechnungen packt man jeweils in eine eigene 
Funktion, die man einmal erstellt und testet und danach (aus den Augen, 
aus dem Sinn) nur benutzt und die im Programmverlauf nicht stört, auch 
wenn sie intern etwas kompilzierter ist.
1
bool dcf_is_ok(const uint8_t[] buf)
2
{
3
    if ( (buf[0] != 0) || (buf[20] != 1) )
4
        return false;
5
    {
6
        uint8_t tmpsum_a = buf[21] + buf[22] + buf[23] + buf[24] + buf[25] + buf[26] + buf[27] + buf[28];
7
        if (tmpsum_a % 2 != 0)
8
            return false;
9
    }
10
    {
11
        uint8_t tmpsum_b = buf[29] + buf[30] + buf[31] + buf[32] + buf[33] + buf[34] + buf[35];
12
        if (tmpsum_b % 2 != 0)
13
            return false;
14
    }
15
    return true;
16
}
17

18

19
uint8_t calc_day(const uint8_t[] buf)
20
{
21
    uint8_t ones = buf[36] + 2 * buf[37] + 4 * buf[38]+ 8 * buf[39];
22
    uint8_t tens = buf[40] + 2 * buf[41];
23
    return ones + 10 * tens;
24
}
25

26

27
if(dcf_is_ok(dcf77_rx))
28
{
29
    date_day = calc_day(dcf77_rx);
30
}

Gleich werden die Optimierer kommen und wild Bytes sparen...
#4897943
programmieren schrieb:
> Kann man das irgendwie vereinfacht/leserlicher schreiben/darstellen?
Tom schrieb:
> Berechnungen packt man jeweils in eine eigene Funktion

Eine Funktion ist gut, WENN man sie mehrmals aufruft.
Deine Funktionen sind Unsinn weil zu hoch spezialisiert.
dcf77_rx (Arrayanfangspointer) als Parameter zu übergeben
ist Quatsch weil als globale Adresse immer gleich, es
gibt keine zweite.

Wenn man ein sinnvolles Programm haben will, erfindet man z.B. eine 
Funktion
1
uint8_t bitvalue(uint8_t firstbit,uint8_t n)
2
{
3
  uint8_t value=0;
4
  while(n--) value=(value<<1)|dcf77_rx[firstbit+n];
5
  return value;
6
}
die kann man dann überall aufrufen, wo man aus dem bitstram Daten 
entnehmen will.
1
day=bitvalue(36,4)+10*bitvalue(40,2);
oder für Parity
1
uint8_t bitparity(uint8_t firstbit,uint8_t n)
2
{
3
  uint8_t value=0;
4
  while(n--) value^=dcf77_rx[firstbit++];
5
  return value;
6
}
7

8
valid=!dcf77_rx[0]&&dcf77_rx[20]&&!bitparity(21,8)&&!bitparity(29,7);
#4897968
Michael B. schrieb:

> Eine Funktion ist gut, WENN man sie mehrmals aufruft.

Das kann man so alleine nicht stehenlassen. Aus Gründen der 
Übersichtlichkeit lagert man ja auch Programmteile in Funktionen aus, 
die nur einmal aufgerufen werden.

> Deine Funktionen sind Unsinn weil zu hoch spezialisiert.

Naja, Unsinn nicht, aber sie könnte weiter verbessert werden wenn sie 
die universelle Funktion von Dir aufrufen würde. Auch würde ich dennoch 
den Pointer zum Buffer übergeben, selbst wenn er in diesem Fall eine 
globale Variable ist. Vlt. schreibt er ja das Programm später um und der 
Buffer ist dann nur noch lokal (z.B. wenn er alles im Interrupt macht).
Gast #4898034
Tom schrieb:
> kommen und wild Bytes sparen...

Bytes sparen wäre hier Dummheit.
Zeilen sparen, wie im UP ebenso.
Das einzige, was hier zählt ist Lesbarkeit. Also sinnvolle Namen, 
Formatierung, verständliche Operationen. Für Anfänger ist massives 
"eigene Funktion draus machen" manchmal klarer zu strukturieren.. Je 
lesbarer der Code mit Erfahrung wird, umso weniger ist das sinnvoll.
Gast #4898108
Michael B. schrieb:
> Eine Funktion ist gut, WENN man sie mehrmals aufruft.

Die Vermeidung von Redundanz ist einer der Gründe, Funktionen zu 
schreiben (oft sicher auch der wichtigste und "einsichtigste"). Andere 
Gründe sind z.B. Lesbarkeit und Testbarkeit.
Gast #4899344
Architekt schrieb:
> Andere Gründe sind z.B. Lesbarkeit und Testbarkeit.

Genau hier entfacht sich ja der Streit, wohl unauflöslich, bei 
einmaligen Aufgaben:

Lesbarkeit: Der eine navigiert lieber über Listen von Anweisungen, der 
andere über Listen von Links.

Testbarkeit: Der eine favorisiert Unit-Test auf Einzeilern, dem anderen 
sind Test auf höheren Ebenen wichtig.

Das "gesunde Maß" hängt natürlich von Art und Umfang der Projekte ab. 
Für akademische Beispiele sind einzeiler-Funktionen immer positiv, bei 
größeren Projekten selbst in relativ kleiner Zahl tödlich.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.