Paritätsprüfung von einer Variable oder DCF77 Signalüberprüfung
Dienstag, 22. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  CCS Compiler  |  Timer (CCS)  |  Paritätsprüfung von einer Variable oder DCF77 Signalüberprüfung « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: Paritätsprüfung von einer Variable oder DCF77 Signalüberprüfung  (Gelesen 4970 mal)
 
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« am: Dezember 21, 2006, 22:04:23 »

Hallo Zusammen,

kennt jemand ein Code Beispiel, wie eine einfache Paritätsprüfung
aussehen könnte.
Ich möchte die gesendete Informationen des DCF77 Signals überprüfen.

Bernd
 :-?

Gespeichert

MFG
Bernd Fritz
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #1 am: Dezember 21, 2006, 23:25:02 »

Zitat
kennt jemand ein Code Beispiel, wie eine einfache Paritätsprüfung aussehen könnte.

Für die Paritätsberechnung (senden) einer 8-Bit Variablen verwende ich z.B. folgendes Makro:

Code:
#define EVEN  0
#define ODD   1

#define SET_PARITY(x,even_odd)                                       \
do                                                                   \
{                                                                    \
    unsigned char temp;                                              \
    temp = ((((((x)>>4) | ((x)<<4)) ^ (x)) + 0x41) & 0x82) + 0x7E;   \
    TX9D = even_odd;                                                 \
    if (temp & 0x80)                                                 \
        TX9D = even_odd ^ 1;                                         \
} while (0)

...

unsigned char data;

SET_PARITY (data,EVEN);

Für die Prüfung findet das selbe Prinzip Anwendung:

Code:
unsigned char data, parity;

parity = (((((data>>4) | (data<<4)) ^ data) + 0x41) & 0x82) + 0x7E;

Das MSB von parity ist "1", wenn data eine ungerade Anzahl von Einsen enthält.

In Assembler:

Code:
  swapf   data, W 
  xorwf   data, W
  addlw   0x41
  andlw   0x82
  addlw   0x7E       ; MSB von W ist Parity-Bit

Für die Parity-Bits von Minuten und Stunden kannst Du den angegebenen Code praktisch direkt verwenden. Datum und Wochentag würde ich der Einfachheit halber als vier 8-Bit Werte auffassen (die Parity-Bits dieser 8-Bit Werte geeignet verknüpfen) und dann mit dem empfangenen Parity-Bit vergleichen.


Viele Grüße

Bernd
Gespeichert

Ramazuki
Newbie
*
Offline Offline

Beiträge: 37


Profil anzeigen
« Antworten #2 am: Dezember 27, 2006, 19:56:38 »

Als unerfahrener Newbie hab ich da einen für
mich einfacheren Algo geschrieben :

Code:

int check_buffer()
{
int par_min = 0;
int i;

for(i=21;i<=27;i++)
 {
  par_min = par_min + incomming_buffer[i];
 }

 if ((!incomming_buffer[0])&(incomming_buffer[20])) // bit0=0 and bit20=1
  {
    if (    ( ((par_min % 2)) & (incomming_buffer[28]) ) ||   
            ( (!(par_min % 2)) & (!incomming_buffer[28]) )   )

      {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"OK !!");
        return 1;
      }
  }

 else
   {
        lcd_gotoxy(1,1);
        printf(lcd_putc,"Bad !!");

        return 0;
   }
}



Ich addiere einfach vom Buffer (60 Stellen, gefüllt mit den DCF-lows/highs) z.B
die Bits 21-27 (Minutenangabe), wenn das Resultat durch zwei ohne Rest
(%, in c++ mod) teilbar ist, muss das Paritätsbit auch 0 sein.. Ansonsten gibt's 1 als
Rest, so wie auch die Parität sein muss..

In meiner DCF-xls hab ichs dito gemacht..

Aber, ich glaube, dass dies oben eine weniger Speicherfressende Variante sein wird.. SchockiertSchockiert:
Gespeichert
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #3 am: Dezember 28, 2006, 23:41:04 »

Hallo Zusammen,

die Paritätsprüfung von Bernd habe ich probiert und bin noch zu kein brauchbaren Ergebniss gekommen.
Bei der Paritätsprüfung von Ramazuki steht ein Buffer mit Daten zur Verfügung. Eine Möglichkeit diese Prüfung durchzuführen.
Bei meinem Programm für eine DCF77 Uhr habe ich den Inhalt (BCD) in fünf Variablen für MIN, STD, WOCHENTAG, TAG, MONAT und Jahr zur Verfügung. Der Vorschlag von Bernd die Prüfung über 4 Byte ist in Arbeit.

Ich habe jetzt auch einen Code für die Paritätsprüfung erstellt, hierzu ein paar Anmerkungen:
Zur Prüfung werden an das Unterprogramm die Variable und das Paritätsbit gegeben, als Ergebniss soll mit return(1 oder 0) erfolgen.
Code: (c)
parity_check (unsigned char data, parity_bit)
{ unsigned char help, help_data, parity, x;

  help_data=dez_bcd(data);   // wandle in BCD und lade Prüfbyte
  parity=0;                  // parity Zähler auf Null
  x=8;               
  while(x)                   // Schleife für die Zählung
  { help=help_data;          // lade in help das byte bzw. geschobene
    help&=~0xFE;             // Codiere das letzte Bit aus
    if(help)                 // nur die Ergebnisse mit 1 zählen   
       parity++;   
    help_data>>=1;           // schiebe das zu Prüfende Byte um eine Stelle nach rechts
    x--;                     // setze auf das naechste  Bit
  }
   parity%=2;                 // Modulo also Rest in parity
  if ((parity)==(parity_bit)) // vergleiche parity von data mit parity_bit
     return(1);               // parity Rückgabe = ok
  else
     return(0);               // parity Rückgabe = Fehler
}

Der Code ist recht aufwendig geworden, weiß jemand eine Optimierung ?
Gespeichert

MFG
Bernd Fritz
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #4 am: Dezember 29, 2006, 14:35:13 »

Zitat
Der Code ist recht aufwendig geworden, weiß jemand eine Optimierung ?

Code:
unsigned char parity_check_1 (unsigned char data, unsigned char parity_bit)
{
   unsigned char parity;
   
   data = dez_bcd (data); // data ohne Parity-Bit

   data ^= parity_bit;    // Wert in data hat gleiche Parität wie
                          // der Ausgangswert von data inklusive Parity-Bit

   parity = (((((data>>4) | (data<<4)) ^ data) + 0x41) & 0x82) + 0x7E;

// parity = 0b1xxxxxxx, wenn data ungerade Anzahl an Einsen enthält
// parity = 0b0xxxxxxx, wenn data gerade Anzahl an Einsen enthält
// Parität muß "gerade" sein

   return (!(parity&0x80));  // liefert 1 bei "gerader" Parität
}

Für Datum und Wochentag kannst Du Dir eine nette Eigenschaft der xor-Verknüpfung zu Nutze machen:

Die Parität von "x"

Code:
unsigned char x;
 
x = Tag ^ Monat ^ Jahr ^ Wochentag;

ist identisch mit der Parität über alle vier Werte. Damit hast Du wieder einen 8-Bit Wert, dessen Parität Du mit dem oben gezeigten Code überprüfen kannst.

Wenn Du Die Parität mit der von Dir gezeigten Methode überprüfen willst, würde ich schreiben:

Code:
unsigned char parity_check_2 (unsigned char data, unsigned char parity_bit)
{
    unsigned char parity, x;

    data=dez_bcd(data);   // wandle in BCD und lade Prüfbyte 

    parity=0;                  // parity Zähler auf Null

    for (x=8; x>0; --x)
    {
        if (data & 0x01)
            parity++;
       
data >>= 1;  
    }

    return ((parity & 0x01) == parity_bit);
}

Von der Codegröße her gibt es keinen großen Unterschied zwischen beiden Varianten. Mein Compiler erzeugt für
parity_check_1() 14 Words Code und für parity_check_2() 18 Words (Funktionsaufruf von dez_bcd() jeweils auskommentiert).

Der wirkliche Vorteil der ersten Variante liegt in der Ausführungsgeschwindigkeit:

Code:
unsigned char ok;
   
ok = parity_check_x (0x87, 1);

parity_check_1() benötigt 23 Befehlszyklen (inklusive Parameterübergabe, Funktionsaufruf und Rücksprung), parity_check_2() hingegen 76 Befehlszyklen, also mehr als die dreifache Zeit.
 
Wenn Du die DCF77 Daten nur auf dem LCD anzeigen willst, könnte man auf die Umwandlung von BCD nach dezimal und wieder zurück verzichten. Für die Ausgabe auf dem LCD benötigt man letztendlich BCD Daten, die z.B. von printf erst wieder aus dem dezimalen Wert gewonnen werden müssen.

 
Viele Grüße

Bernd
Gespeichert

Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #5 am: Dezember 30, 2006, 09:17:48 »

Hallo Bernd

Zitat
... die Umwandlung von BCD nach dezimal und wieder zurück verzichten. Für die Ausgabe auf dem LCD benötigt man letztendlich BCD Daten.....

Beim Programmieren versuche ich immer soviel wie möglich in Header Dateien also Name.h reinzupacken, die dann im Hauptprogramm.c mit include eingebunden werden. So hat es sich ergeben das ich in der Header Datei den übergebenen Wert in BCD Umwandeln mußte. Über diese Falle des "Umwandeln von Byte's" bin ich schon öfters gestolpert.

Ich werde meine Paritätsprüfung nach dem  parity_check_1() optimieren. 
Hier ein Auszug aus der DCF77 Paritätsprüfung meiner DCF77 Uhr
Code: (css)
// unsigned char parity;            // hier zähle ich die Paritätsprüfungen

  if (sek_zahler==28)                      // Paritätsprüfung Minuten
         parity=parity_check_1(min,dcf_bit);
         
     if (sek_zahler==35)                      // Paritätsprüfung Stunden
         parity+=parity_check_1(std,dcf_bit);
   
     if (sek_zahler==58)         // Paritätsprüfung Tag,Wochent.,Monat,Jahr
        x = day ^ wochentag ^ month ^ year; // fasse die Variablen zusammen
        parity+=parity_check_1(x,dcf_bit); 

// dann werte ich die Variable "parity" aus 


Das ganze funktioniert Klasse, ein Dank an Bernd für die Hilfestellung
Gruß
Bernd Fritz    Schockiert:
« Letzte Änderung: Januar 01, 2007, 21:45:15 von Bernd_Fritz » Gespeichert

MFG
Bernd Fritz
wolfi_b
Jr. Member
**
Offline Offline

Beiträge: 84


Profil anzeigen
« Antworten #6 am: Januar 10, 2008, 11:56:26 »

Hallo!

Ich brüte gerade über dem selben Problem.

Code:
parity = (((((data>>4) | (data<<4)) ^ data) + 0x41) & 0x82) + 0x7E;

Sag mal Bernd, wie kommt man auf so einen Algorithmus? Ich kann das nicht im geringsten nachvollziehen. Prinzipiell gefällt mir das gut aber ich möchte nur ungerne Code verwenden den ich nicht verstehe.

Gruß Wolfi
Gespeichert
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #7 am: Januar 10, 2008, 18:10:24 »

Zitat
Ich kann das nicht im geringsten nachvollziehen.

Eine Erklärung findest Du hier. Ein sehr ähnlicher Algorithmus wird hier erklärt.


Viele Grüße

Bernd
Gespeichert

Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #8 am: Januar 10, 2008, 18:16:59 »

Hallo Wolfi,

ich habe die gute Formel hier im Forum bekommen. Natürlich habe ich schon Zeit gebraucht bist ich das verstanden und mal durchgespielt habe.
Meine Eigene Paritätsprüfung sah auf dem ersten Blick einfacher und übersichtlicher aus, aber es verbrauchte viel zu viel Speicher.
Hier mein Code: (ist aber nicht zu empfehlen)
Code: (css)
parity_check (unsigned char data, parity_bit)
{ unsigned char help, help_data, parity, x;

  help_data=dez_bcd(data);   // wandle in BCD und lade Prüfbyte
  parity=0;                  // parity Zähler auf Null
  x=8;              
  while(x)                   // Schleife für die Zählung
  { help=help_data;          // lade in help das byte bzw. geschobene
    help&=~0xFE;             // Codiere das letzte Bit aus
    if(help)                 // nur die Ergebnisse mit 1 zählen  
       parity++;    
    help_data>>=1;           // schiebe das zu Prüfende Byte um eine Stelle nach rechts
    x--;                     // setze auf das naechste  Bit
  }
   parity%=2;                 // Modulo also Rest in parity
  if ((parity)==(parity_bit)) // vergleiche parity von data mit parity_bit
     return(1);               // parity Rückgabe = ok
  else
     return(0);               // parity Rückgabe = Fehler
}
Gruß
Bernd
Gespeichert

MFG
Bernd Fritz
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.049 Sekunden mit 18 Zugriffen.
 
Top! Top!