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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von EbbeSand (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
EbbeSand schrieb:
> Polynomial: 0x8005

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

von EbbeSand (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.