Newsgroup: it.comp.lang.visual-basic
Titolo: CRC16

Buona giornata a tutti,
ho un problema con il calcolo della CRC16 sia in VB6 che in un
microprocessore PIC 18F
Spiego il problema
ho a disposizione 4 modi per calcolare questa CRC16:
Un progetto scaricato con un modulo di codice (penso dal sito comune) che
utilizza per il calcolo due tabelle a 256 valori
La copia esatta per il PIC 18F di quel codice adattato al Basic per il micro
Un calcolatore di CRC16 anche questo scaricato da internet
Una routine di calcolo per il micro messa insieme da me sulla base di
un'idea vista su internet
Provando con la stessa stringa di dati ottengo 4 valori diversi :-( !!!
Cosa fare? Qualcuno mi può aiutare?
Di seguito spezzoni vari di codice
Le stringhe che utilizzo per il test  sono due   199,0,0,0,0,199   in
alternativa199,0,1,0,0,200
il bello è che già usando un solo byte (199) il risultato è totalmente
diverso
Codice per micro versione 1 (uguale al codice in VB6)
Sub CRC16(Nbyte As uByte)
Uses CRC_H,CRC_L
Dim uCRCHi As uByte
Dim uCRCLo As uByte
Dim uIndex As uByte
Dim i As uByte
Dim j1 As uByte
Dim k1 As uByte
uCRCHi = 255                               'Inizializza checksum Hi
uCRCLo = 255                               'Inizializza checksum Lo
i = 0                                       'Inizializza indice
crc_i=0
crc_o=0
  While (i < Nbyte)                      'Scorri tutti i caratteri del
messaggio
    uIndex = uCRCHi Xor rxBuf1(i)        'Trova l'indice per entrare nella
tabella CRCHi
    j1=Read(CRC_H,uindex)
    uCRCHi = uCRCLo Xor j1       'Ricava parte alta del CRC16
    k1=Read(CRC_L,uindex)
    uCRCLo = k1                 'Ricava parte bassa del CRC 16
    i = i + 1                               'Incrementa indice
  End While
  crc_i=uCRCHi
  crc_o=uCRCLo
End Sub
Table CRC_H As uByte
Data  &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41,
&H0, &HC1, &H81
Data  &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81,
&H40, &H1, &HC0
Data  &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1,
&H81, &H40, &H1
Data  &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1,
&HC0, &H80, &H41
Data  &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40,
&H0, &HC1, &H81
Data  &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80,
&H41, &H1, &HC0
Data  &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0,
&H80, &H41, &H1
Data  &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0,
&HC1, &H81, &H40
Data  &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41,
&H0, &HC1, &H81
Data  &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81,
&H40, &H1, &HC0
Data  &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1,
&H81, &H40, &H1
Data  &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1,
&HC0, &H80, &H41
Data  &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41,
&H0, &HC1, &H81
Data  &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81,
&H40, &H1, &HC0
Data  &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0,
&H80, &H41, &H1
Data  &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1,
&HC0, &H80, &H41
Data  &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41,
&H0, &HC1, &H81
Data  &H40
End Table
Table CRC_L As uByte
Data  &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5,
&HC5, &HC4
Data  &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB,
&HC9, &H9
Data  &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE,
&HDF, &H1F, &HDD
Data  &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6,
&HD2, &H12, &H13, &HD3
Data  &H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2,
&H32, &H36, &HF6, &HF7
Data  &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F,
&H3E, &HFE, &HFA, &H3A
Data  &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB,
&H2B, &H2A, &HEA, &HEE
Data  &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE4, &H24, &H25, &HE5,
&H27, &HE7, &HE6, &H26
Data  &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, &H61,
&HA1, &H63, &HA3, &HA2
Data  &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC,
&HAD, &H6D, &HAF, &H6F
Data  &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78,
&HB8, &HB9, &H79, &HBB
Data  &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H7C,
&HB4, &H74, &H75, &HB5
Data  &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70,
&HB0, &H50, &H90, &H91
Data  &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, &H95,
&H94, &H54, &H9C, &H5C
Data  &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99,
&H59, &H58, &H98, &H88
Data  &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F,
&H8D, &H4D, &H4C, &H8C
Data  &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43,
&H83, &H41, &H81, &H80
Data  &H40
End Table
Seconda versione sempre per il micro ma fatta come secondo me era più
semplice CRC contiene il valore di CRC e dato il byte da aggiungere.
'Sub CRC16
'Dim q As uByte
'Dim cy As uByte
'Dim by As uInteger
'Dim dy As uByte
'For q = 1 To 8 ' 8 bits in C to process
'    cy=0
'    by=CRC And 1
'    If by=1 Then
'    cy=1
'    End If
'     dy=DATO And 1
'    If dy=1 Then
'    cy=cy+1
'    End If
'
'    'cy = (a Mod 2) + (c Mod 2): ' If = 1 carry bits different
'    CRC = (CRC / 2) ' Shift Right 16 bits A
'    DATO = (DATO / 2) ' Shift Right 8 bits C
'    If cy = 1 Then CRC = CRC Xor 40961 ' Apply Algoritm
' Next q
'End Sub
versione per VB secondo me funzionalmente uguale al primo pezzo di codice
Sub Ini_Modbus()
'************************************************************
'* scopo: Inizializza gli array per il calcolo del CRC16 e tutte le
'*        variabili di temporizzazione necessarie per il protocollo
'************************************************************
'* input:
'* output: CRCHi, CRCLo, Time_silent35, Time_silent15, Time_out_answer
'* verify:
'************************************************************
Dim vntA As Variant
Dim i As Integer
  vntA = Array(&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0,
&H80, &H41, &H0, &HC1, &H81, _
               &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0,
&HC1, &H81, &H40, &H1, &HC0, _
               &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40,
&H0, &HC1, &H81, &H40, &H1, _
               &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80,
&H41, &H1, &HC0, &H80, &H41, _
               &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1,
&H81, &H40, &H0, &HC1, &H81, _
               &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1,
&HC0, &H80, &H41, &H1, &HC0, _
               &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40,
&H1, &HC0, &H80, &H41, &H1, _
               &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80,
&H41, &H0, &HC1, &H81, &H40, _
               &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0,
&H80, &H41, &H0, &HC1, &H81, _
               &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0,
&HC1, &H81, &H40, &H1, &HC0, _
               &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40,
&H0, &HC1, &H81, &H40, &H1, _
               &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81,
&H40, &H1, &HC0, &H80, &H41, _
               &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0,
&H80, &H41, &H0, &HC1, &H81, _
               &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0,
&HC1, &H81, &H40, &H1, &HC0, _
               &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40,
&H1, &HC0, &H80, &H41, &H1, _
               &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81,
&H40, &H1, &HC0, &H80, &H41, _
               &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0,
&H80, &H41, &H0, &HC1, &H81, _
               &H40)
  For i = 0 To 255
    CRCHi(i) = vntA(i)
  Next
  vntA = Array(&H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7,
&HC7, &H5, &HC5, &HC4, _
               &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, &HCA,
&HCB, &HB, &HC9, &H9, _
               &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A,
&H1E, &HDE, &HDF, &H1F, &HDD, _
               &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16,
&HD6, &HD2, &H12, &H13, &HD3, _
               &H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3,
&HF2, &H32, &H36, &HF6, &HF7, _
               &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF,
&H3F, &H3E, &HFE, &HFA, &H3A, _
               &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29,
&HEB, &H2B, &H2A, &HEA, &HEE, _
               &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE4, &H24, &H25,
&HE5, &H27, &HE7, &HE6, &H26, _
               &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60,
&H61, &HA1, &H63, &HA3, &HA2, _
               &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C,
&HAC, &HAD, &H6D, &HAF, &H6F, _
               &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68,
&H78, &HB8, &HB9, &H79, &HBB, _
               &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC,
&H7C, &HB4, &H74, &H75, &HB5, _
               &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71,
&H70, &HB0, &H50, &H90, &H91, _
               &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55,
&H95, &H94, &H54, &H9C, &H5C, _
               &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B,
&H99, &H59, &H58, &H98, &H88, _
               &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F,
&H4F, &H8D, &H4D, &H4C, &H8C, _
               &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42,
&H43, &H83, &H41, &H81, &H80, _
               &H40)
  For i = 0 To 255
    CRCLo(i) = vntA(i)
  Next

un'idea vista su internet
Il CRC si può fare con la somma senza riporto o con lo XOR di tutti i
bytes, ci sono scuole diverse.
Per esempio  ASCII-INTEL (il + usato) usa la somma
Ti copio incollo un pezzo del programma che uso per testare i file
ASCII-INTEL prima di inviarli alla seriale per un update flash di un
microprocessore.
           __________________________
'CALCOLO CHECKSUM= LE PRIME DUE CIFRE ESADECIMALI DELLA SOMMA
ALGEBRICA
      Tot = 0:     TotByts = TotByts + ((Len(StrInp$) - 11) \ 2)
     For i = 2 To Len(StrInp$) - 3 Step 2
         Tot = Tot + Val("&H" & Mid$(StrInp$, i, 2)) 
     Next
    Crc$ = Right$("0" + Hex$(0 - Val("&H" & Right$(Hex$(Tot), 2))), 2)
          _____________________________ 
Esempio di stringa ASCII-INTEL:
:10000000F33E80ED393FAFED39B63E30ED39B23ECB
i due punti sono il carattere di inizio stringa.
Il primo byte 10H dice che ci sono 16  bytes
il secondo e il terzo danno l'indirizzo 0000H
un altro byte è sempre a zero
poi i 16 bytes
F3 3E 80 ED 39 3F AF ED 39 B6 3E 30 ED 39 B2 3E
infine il checksum
0xCB
ciao
  Stefano