Forum: Mikrocontroller und Digitale Elektronik CRC16 Polynom 0xA001 auf AVR 8Bit und STM32


von EbbeSand (Gast)


Lesenswert?

Hat Jemand von euch eine Idee warum sich diese Funktion


Implementierung AVR 8Bit
1
unsigned short update_crc16( unsigned short crc, char a )
2
   {
3
           uint16_t i;
4
           crc ^= a;
5
           for (i = 0; i < 8; ++i)
6
              {
7
                if (crc & 1)  crc = (crc >> 1) ^ 0xA001;
8
                  else crc = (crc >> 1);
9
              }
10
           return crc;
11
         }


Implementierung STM32
1
uint16_t update_crc16(unit16_t crc, unit8_t a )
2
   {
3
           uint16_t i;
4
           crc ^= a;
5
           for (i = 0; i < 8; ++i)
6
              {
7
                if (crc & 1)  crc = (crc >> 1) ^ 0xA001;
8
                  else crc = (crc >> 1);
9
              }
10
           return crc;
11
         }

sich anderes verhält beide sind mit 0xFFFF initialisiert

auf einem STM32 erhalte ich aber das Ergebnis des Polynoms 0x8005 ?

Danke für die Hilfe

EbbeSand

von Dr. Sommer (Gast)


Lesenswert?

Warum benutzt du überhaupt zwei unterschiedliche Implementierungen? Eine 
die konsequent die uintXX_T Typen nutzt sollte auf beiden funktionieren.

Die Tatsache dass du Tippfehler im Code hast ("unit16_t") lässt vermuten 
dass das nicht der echte Code ist. Zeige diesen doch mal.

Der einzige wirkliche Unterschied ist dass "a" signed beim AVR, und 
unsigned beim STM32 ist. Definier doch mal "a" als uint8_t beim AVR, und 
am Besten "crc" auch als uint16_t. Dann ist der Code identisch zum 
anderen...

von EbbeSand (Gast)


Lesenswert?

Hallo Dr.Sommer

Danke für die Schnelle Antwort werde ich morgen mal versuchen und dann 
Berichten und zweitens Ja das ist nicht der Original Quelltext. 
(erwischt :-))

Danke

EbbeSand

von Peter D. (peda)


Lesenswert?

EbbeSand schrieb:
> Ja das ist nicht der Original Quelltext.

Damit ist jede Frage hinfällig und jede Antwort sinnlos.

von Sebastian V. (sebi_s)


Lesenswert?

Dr. Sommer schrieb:
> Der einzige wirkliche Unterschied ist dass "a" signed beim AVR, und
> unsigned beim STM32 ist.

Genau das ist auch das Problem (oder mindestens eins). Wenn das signed a 
negativ ist und du crc ^= a schreibst wird das char zu einem uint16_t 
konvertiert und dabei das Vorzeichen erweitert. Aus -1 (0xFF) wird dann 
ein 0xFFFF.

von EbbeSand (Gast)


Lesenswert?

So jetzt nochmals für alle die Originalen Quelltexte

Der AVR Quelltext ist schon etwas älter und ich habe diesen
mit AVRStudio4 und WINAVR-20090313 geschrieben besser gesagt dieser
kommt aus der lib und ist nur eingebunden.
1
/** \ingroup util_crc
2
    Optimized CRC-16 calculation.
3
4
    Polynomial: x^16 + x^15 + x^2 + 1 (0xa001)<br>
5
    Initial value: 0xffff
6
7
    This CRC is normally used in disk-drive controllers.
8
9
    The following is the equivalent functionality written in C.
10
11
    \code
12
    uint16_t
13
    crc16_update(uint16_t crc, uint8_t a)
14
    {
15
  int i;
16
17
  crc ^= a;
18
  for (i = 0; i < 8; ++i)
19
  {
20
      if (crc & 1)
21
    crc = (crc >> 1) ^ 0xA001;
22
      else
23
    crc = (crc >> 1);
24
  }
25
26
  return crc;
27
    }
28
29
    \endcode */
30
31
static __inline__ uint16_t
32
_crc16_update(uint16_t __crc, uint8_t __data)
33
{
34
  uint8_t __tmp;
35
  uint16_t __ret;
36
37
  __asm__ __volatile__ (
38
    "eor %A0,%2" "\n\t"
39
    "mov %1,%A0" "\n\t"
40
    "swap %1" "\n\t"
41
    "eor %1,%A0" "\n\t"
42
    "mov __tmp_reg__,%1" "\n\t"
43
    "lsr %1" "\n\t"
44
    "lsr %1" "\n\t"
45
    "eor %1,__tmp_reg__" "\n\t"
46
    "mov __tmp_reg__,%1" "\n\t"
47
    "lsr %1" "\n\t"
48
    "eor %1,__tmp_reg__" "\n\t"
49
    "andi %1,0x07" "\n\t"
50
    "mov __tmp_reg__,%A0" "\n\t"
51
    "mov %A0,%B0" "\n\t"
52
    "lsr %1" "\n\t"
53
    "ror __tmp_reg__" "\n\t"
54
    "ror %1" "\n\t"
55
    "mov %B0,__tmp_reg__" "\n\t"
56
    "eor %A0,%1" "\n\t"
57
    "lsr __tmp_reg__" "\n\t"
58
    "ror %1" "\n\t"
59
    "eor %B0,__tmp_reg__" "\n\t"
60
    "eor %A0,%1"
61
    : "=r" (__ret), "=d" (__tmp)
62
    : "r" (__data), "0" (__crc)
63
    : "r0"
64
  );
65
  return __ret;
66
}


Diesen code habe ich auf einem STM32 implementiert
1
/* This funtion is used Calculate the CRC
2
 *
3
 *       data --> data to be transmitted
4
 *       returns received value
5
 */
6
7
uint16_t crc16_update(uint16_t crc, uint8_t a)
8
       {
9
         uint16_t i;
10
         crc ^= a;
11
         for (i = 0; i < 8; ++i)
12
            {
13
              if (crc & 1)  crc = (crc >> 1) ^ 0xA001;
14
                else crc = (crc >> 1);
15
            }
16
         return crc;
17
       }


Und jetzt  nochmals die Frage warum rechnet der STM32 bei gleichem 
Startwert etwas anderes aus. Ich habe mit einem online CRC Calculator 
mal
geschaut und ich bekomme das Ergebnis des STM32 nur hin wenn ich

die folgenden Parameter verwende

Input reflected: yes
Result reflected: yes
Polynomial: 0x8005
Initial Value: 0xffff
Final Xor Value: 0x0

In meinen Augen steht dort nichts anderes Sorry für das Nebelwerfen am 
Anfang aber ich hab das von Unterwegs geschrieben.

Gruß

EbbeSand

von Michael R. (mr-action)


Lesenswert?

Dein Problem ist doch das gleiche wie vorher schon geschrieben - nur an 
einer anderen Stelle...

Nutz doch einfach auf beiden Prozessoren den gleichen Code! (int != 
uint16_t)

von Peter D. (peda)


Lesenswert?

EbbeSand schrieb:
> Polynomial: 0x8005

Das ist A001 reverse, d.h. Du hast wohl ne falsche Byteorder auf dem AVR 
angenommen.

von EbbeSand (Gast)


Lesenswert?

Hallo Nochmals!!!

Kommando zurück, wie öfter mal lag der Fehler einen halben Meter vor dem
Bildschirm. Wenn man in seiner alten Software den Datenstrom nicht 
Komplett im CRC berücksichtigt sondern bei n-1 abbricht zu rechnen. Aber 
auf der neuen Implementierung bis n rechnet dann kommen bzw. sollten 
auch zwei verschiedenen Ergebnisse für die CRC16 erscheinen.

Danke für eure Geduld und Hilfe

Gruß

EbbeSand

von Dr. Sommer (Gast)


Lesenswert?

EbbeSand schrieb:
> _crc16_update(uint16_t __crc, uint8_t __data)
> {
>   uint8_t __tmp;
>   uint16_t __ret;

In C und C++ ist es verboten, Bezeichner mit doppeltem Unterstrich , 
oder einzelner Unterstrich + Großbuchstabe zu nutzen. Das darf nur die 
Standard C(++) Library. Tut man es trotzdem, kann beliebig undefiniertes 
Verhalten folgen.

von Dr. Sommer (Gast)


Lesenswert?

EbbeSand schrieb:
> besser gesagt dieser
> kommt aus der lib und ist nur eingebunden.
Ok, es sei denn damit ist die Standard Library gemeint :-)

von EbbeSand (Gast)


Lesenswert?

Hallo Dr. Sommer,

ja es ist die Standard AVR Standard Library und zu deinem
zweiten Post --> ich hab die nur eingebunden aber nicht geschrieben.
der gepostete Code Auszug ist auf dem Header-File.

Gruß

EbbeSand

Beitrag #5134324 wurde vom Autor gelöscht.
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.