Forum: Mikrocontroller und Digitale Elektronik Parity check von 32-Bit Wert


von Jens K. (mister232)


Lesenswert?

Hallo Leute,

ich verwende in meiner Schaltung einen LTC2418 ADC, welcher über SPI mit 
meinem Mikrocontroller kommuniziert. Das funktioniert soweit auch alles 
sehr gut. Nun bietet das Protokoll des LTC2418 die Möglichkeit die 
Parität der Nachricht zu prüfen, diese muss immer "even" sein. Dazu habe 
ich folgende Funktion geschrieben, welche die Parität eines 32-Bit 
Wertes prüfen soll:
1
// Function, which checks the parity of a received message from the ADC
2
uint8_t check_parity(uint32_t adc_message)
3
{
4
  unsigned int count = 0, pos, check_bit = 1;
5
6
7
  // Calculate parity sum
8
  for(pos = 0; pos < 32; pos++)
9
  {
10
    // Check if the bit at the actual position is 1
11
    if(adc_message & (check_bit << pos))
12
    {
13
      count++;
14
    }
15
  }
16
17
  
18
  // If parity is odd return 0
19
  if(count % 2)
20
  {
21
    return 0;
22
  }
23
24
  return 1;
25
}

Leider ergibt jede Nachricht "odd". Liegt es an meinem Code oder scheint 
es da noch Probleme beim Empfang der Nachricht zu geben?

von Peter II (Gast)


Lesenswert?

(check_bit << pos)

geht auf einer 16bit CPU auch nur bis 16bit.

von H.Joachim S. (crazyhorse)


Lesenswert?

Check_bit dürfe etwas knapp bemessen sein.

von Falk B. (falk)


Lesenswert?

@Jens K. (mister232)

>sehr gut. Nun bietet das Protokoll des LTC2418 die Möglichkeit die
>Parität der Nachricht zu prüfen, diese muss immer "even" sein.

>// Function, which checks the parity of a received message from the ADC
>uint8_t check_parity(uint32_t adc_message)
{
>  unsigned int count = 0, pos, check_bit = 1;

check_bit muss auch uint32 sein, es sei denn, du hast einen 32 Bit uC, 
dann ist dort int auch 32 Bit breit.
Dann sollte deine Funktion laufen.

Allerdings ist sie reichlich lahm, vor allem auf einem kleinen uC. So 
geht es besser.
1
uint8_t check_parity(uint32_t adc_message)
2
{
3
  int parity, i;
4
5
  // Calculate parity sum
6
  for(i=0, parity=0; i < 32; i++, adc_message>>=1)
7
  {
8
    // Check if bit #0 is 1
9
    if(adc_message & 1)
10
    {
11
      parity++;
12
    }
13
  }
14
15
  if(parity & 1)
16
  {
17
    return 0;  // parity is odd, return 0 (error)
18
  }
19
20
  return 1;
21
}


Noch schneller und besser ist es so, zumindest auf einer 32 Bit CPU.
1
uint8_t check_parity(uint32_t adc_message)
2
{
3
4
  adc_message = adc_message ^ (adc_message>>16);
5
  adc_message = adc_message ^ (adc_message>>8);
6
  adc_message = adc_message ^ (adc_message>>4);
7
  adc_message = adc_message ^ (adc_message>>2);
8
  adc_message = adc_message ^ (adc_message>>1);
9
10
  if (adc_message & 1) {
11
  return 0;    // odd parity, error
12
  };
13
14
  return 1;    // even parity, OK
15
}

Auf einer kleinen CPU könnte eine 16/8 Bit Hilfsvariable die 
Geschwindigkeit erhöhen, falls der Compiler das nicht clever allein 
erkennt.
1
uint8_t check_parity(uint32_t adc_message)
2
{
3
4
  uint16_t tmp16;
5
  uint8_t tmp8;
6
7
  tmp16 = adc_message ^ (adc_message>>16);
8
  tmp8  = tmp16 ^ (tmp16>>8);
9
  tmp8  = tmp8  ^ (tmp8>>4);
10
  tmp8  = tmp8  ^ (tmp8>>2);
11
  tmp8  = tmp8  ^ (tmp8>>1);
12
13
  if (tmp8 & 1) {
14
  return 0;    // odd parity, error
15
  };
16
17
  return 1;    // even parity, OK
18
}

von Jens K. (mister232)


Lesenswert?

Danke für eure antworten, werde es nachher mal ausprobieren und mich 
wieder melden

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mit GCC:
1
#include <stdint.h>
2
3
uint8_t get_parity (uint32_t x)
4
{
5
#if defined(__GNUC__) && (__SIZEOF_INT__ == 4)
6
    return __builtin_parity (x);
7
#elif defined(__GNUC__) && (__SIZEOF_LONG__ == 4)
8
    return __builtin_parityl (x);
9
#else
10
#error
11
#endif
12
}

von Falk B. (falk)


Lesenswert?

Schön, aber da lernt der OP noch weniger.

von Eric B. (beric)


Lesenswert?

Oder so:
1
uint8_t check_parity(uint32_t adc_message)
2
{
3
  int i;
4
  uint8_t parity = 1;
5
6
  // Calculate parity sum
7
  for(i=0; i < 32; i++, adc_message>>=1)
8
  {
9
    parity ^= (uint8_t)(adc_message & 1);
10
  }
11
12
  return parity;
13
}

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.