PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 2024 → Calcul CRC-16
Calcul CRC-16
Iniciado por Mouhi, 19,sep. 2019 22:52 - 16 respuestas
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 19,septiembre 2019 - 22:52
Bonjour,

Matheux wanted :D

Dans le cadre d'une communication avec une balise GPS, je cherche à calculer le CRC-16 d'une chaine Hexa :

sHexaMsg is string = 0C010500000009676574696E666F0D0A01 // CRC-16 = 00 00 DA 7E


On peut vérifier le résultat sur ce site : http://www.tahapaksu.com/crc/





Mais pas moyen d'obtenir le CRC-16 = 00 00 DA 7E (en Hexa).

J'ai essayé la fonction Windev sComputeCrc16 mais le résultat m'affiche d'autres chiffres :
sHexaMsg is string = "0C010500000009676574696E666F0D0A01"
sDecimal is string = "4084743592531350520179175524571022166529"
sBinary is string = "110000000001000001010000000000000000000000000000100101100111011001010111010001101001011011100110011001101111000011010000101000000001"

FOR i=1 _TO_ Length(sHexaMsg) STEP 2
sResult += Charact(Val(sHexaMsg[[i ON 2]],"x")) // Hexa => Decimal ("x" : base 16 = Hexa) => ASCII Char.
sResult += Asc(Val(sHexaMsg[[i ON 2]],"x")) // Hexa => Decimal ("x" : base 16 = Hexa) => ASCII Char.
END

Trace(sComputeCrc16(sResult)) // Normalement : 55934



J'ai trouvé ça sur le forum mais malheureusement je n'obtiens toujours pas mon résultat attendu (00 00 DA 7E) :
Procedure CRC16(sChaîne)
tabTableCRC est un tableau de 256 entiers sans signe sur 2
nCRC, nC sont des entiers sans signe sur 2
nPoly est un entier sans signe sur 2 = 0xA001

POUR i = 0 A 255
nCRC = 0
nC = i
POUR j = 0 A 7
SI ((nCRC || nC) & 0x0001) <> 0 ALORS
nCRC = (nCRC bitDécaleDroite 1) || nPoly
SINON
nCRC = nCRC bitDécaleDroite 1
FIN
nC = nC bitDécaleDroite 1
FIN
tabTableCRC[i + 1] = nCRC
FIN
nCRC = 0
POUR j = 1 _A_ Taille(sChaîne)
nC = Asc(sChaîne[[j]]) & 0xFF
nCRC = (nCRC bitDécaleDroite 8) || tabTableCRC[((nCRC || nC) & 0xFF) + 1]
FIN
RENVOYER nCRC


Quelqu'un peut me sauver ? ;(

Merci d'avance.
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 20,septiembre 2019 - 10:04
Bonjour,
j'ai parcouru rapidement ton code.
Qu'est ce que cela donne en remplaçant :
FOR i=1 _TO_ Length(sHexaMsg) STEP 2
sResult += Charact(Val(sHexaMsg[[i ON 2]],"x")) // Hexa => Decimal ("x" : base 16 = Hexa) => ASCII Char.
sResult += Asc(Val(sHexaMsg[[i ON 2]],"x")) // Hexa => Decimal ("x" : base 16 = Hexa) => ASCII Char.
END

Par
FOR i=1 _TO_ Length(sHexaMsg) STEP 2
sResult += Charact(Val(sHexaMsg[[i ON 2]],"x")) // Hexa => Decimal ("x" : base 16 = Hexa) => ASCII Char.
END


--
Il y a peut être plus simple, mais, ça tourne
Miembro registrado
324 mensajes
Popularité : +21 (51 votes)
Publicado el 20,septiembre 2019 - 13:18
Pourquoi vouloir réinventer la roue ?
sCalculeCrc16(Chaine)

Edit : Ok y'a bien 20 méthodes de calcule de CRC, bien entendu on ne le retrouve pas avec le CRC16 de windev

"CRC-16/ARC" < c'est ce type d'algo qui va vous donner le résultat attendu ^^

Après test je ne retrouve pas qu'elle algo utilise windev avec celà

gbufMEssageChaine est un Buffer = HexaVersBuffer("0C010500000009676574696E666F0D0A01")
gbufMEssageChaine = sCalculeCrc16(gbufMEssageChaine)
BufferVersHexa(gbufMEssageChaine)

"<12><1><5><0><0><0><TAB>getinfo<RC><1> " < le hexaVersBuffer me renvoie celà une fois converti ca me semble bon, par contre au retour du CRC 16 j'obtiens FF25 et non pas la donnée attendu alors soit on peut préciser l'algo de calcule du CRC à windev et c'est bon sinon ouais va falloir voir comment cet algo calcule le crc16 ^^

Désolé pour mon premier message !
Mensaje modificado, 20,septiembre 2019 - 13:39
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 20,septiembre 2019 - 13:29
L'instruction est dans son premier code, le problème, c'était la conversion Hexa->Chaine.
Le tout est de savoir si elle est nécessaire ou pas, en fonction de son traîtement.

--
Il y a peut être plus simple, mais, ça tourne
Mensaje modificado, 20,septiembre 2019 - 13:32
Miembro registrado
324 mensajes
Popularité : +21 (51 votes)
Publicado el 20,septiembre 2019 - 14:55
Ouais j'avais pas vu le sCompute c'est pour celà, et d'ou aussi mon excuse dans le message à la fin :D.
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 20,septiembre 2019 - 15:02
Un croisement de message je n'avais pas vu la modif, et mon post a mis du temps à être validé.
J'ai un rso rikiki aujourd'hui

--
Il y a peut être plus simple, mais, ça tourne
Mensaje modificado, 20,septiembre 2019 - 15:03
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 20,septiembre 2019 - 17:42
Bonjour,

Merci pour les réponses,

Bien sûr, j'ai essayé une ligne à la fois (et pas les deux) :

// Cette ligne
sResult += Charact(Val(sHexaMsg[[i ON 2]],"x"))
// Ou cette ligne (mais aucune ne donne le résultat attendu.
sResult += Asc(Val(sHexaMsg[[i ON 2]],"x"))


@Voroltinquo, tu dis il y a peut-être plus simple mais ça tourne, c'est-à-dire ? En effet ça tourne mais c'est pas le bon résultat.

Toujours en attente d'une solution miracle :p

Merci d'avance.
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 20,septiembre 2019 - 21:49
Poncherello a expliqué pourquoi.
En regardant ce site https://crccalc.com/ tu vas comprendre.
Selon le mode de calcul on obtient des résultats différents.

La partie principale de l’algorithme d'un calcul de CRC est la suivante
FONCTION crc(tableau de bits bitString[1..longueur], entier polynome)
{
shiftRegister := valeur_initiale // Généralement tous les bits à 0 ou 1
pour i de 1 à longueur
{
SI bit de poids fort de shiftRegister xor bitString[i] vaut 1
{
// décaler d'1 bit vers la gauche équivaut à multiplier par 2
shiftRegister := (shiftRegister décalé d'1 bit vers la Gauche) xor polynome
}
SINON
{
shiftRegister := (shiftRegister décalé d'1 bit vers la Gauche)
}
}
retourne shiftRegister
}

On vois que si l'on change la valeur initiale ou le polynôme le résultat va changer.

Dans ton deuxième code, en passant la valeur de nPoly à 0x8005 ça devrait fonctionner.



--
Il y a peut être plus simple, mais, ça tourne
Mensaje modificado, 20,septiembre 2019 - 22:10
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 21,septiembre 2019 - 00:47
Merci pour ton aide,

J'ai déjà vu le principe de ton algorithme (de Wikipedia), mais je n'ai pas réussi à l'implémenter,

Comme il y a plusieurs algo CRC-A, CRC-16/MODBUS CRC-16/ARC, c'est-ce dernier seulement qui affiche le résultat attendu.

J'ai suivi ton conseil, j'ai mis la valeur nPoly à 0x8005 (dans mon deuxième code), je m'approche mais ce n'est pas le bon résultat :o

nCRC, nC are 2-byte unsigned int
tabTableCRC is array of 256 2-byte unsigned int
nPoly is 2-byte unsigned int = 0x8005

sHexaMsg is string = "0C010500000009676574696E666F0D0A01" // CRC-16 = 00 00 DA 7E

FOR i = 0 TO 255
nCRC = 0
nC = i
FOR j = 0 TO 7
IF ((nCRC || nC) & 0x0001) <> 0 THEN
nCRC = (nCRC bitRightShift 1) || nPoly
ELSE
nCRC = nCRC bitRightShift 1
END
nC = nC bitRightShift 1
END
tabTableCRC[i + 1] = nCRC
END

FOR j = 1 _TO_ Length(sHexaMsg)
nC = Asc(sHexaMsg[[j]]) & 0xFF
nCRC = (nCRC bitRightShift 8) || tabTableCRC[((nCRC || nC) & 0xFF) + 1]
END

Trace(nCRC) // ça affiche : 55476 à la place de 55934 (00 00 DA 7E)


Un autre conseil ?

Merchiiii.
Mensaje modificado, 21,septiembre 2019 - 00:57
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 21,septiembre 2019 - 08:37
[A vue de nez]
Normalement, la fonction attend une chaîne de type buffer et non une valeur hexadécimale, un hexaversbuffer avant le traitement serait sans doute souhaitable.
bufMsg=HexaVersBuffer(sMsgHexa)
Le traitement se fera alors sur le buffer bufMsg
[/A vue de nez]
Je n'ai pas vérifié la validité du traitement

--
Il y a peut être plus simple, mais, ça tourne
Mensaje modificado, 21,septiembre 2019 - 08:44
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 21,septiembre 2019 - 12:35
Bonjour,

J'ai essayé avec un Buffer (plusieurs façons) mais toujours le résultat est différent,

nCRC, nC are 2-byte unsigned int
tabTableCRC is array of 256 2-byte unsigned int
nPoly is 2-byte unsigned int = 0x8005

// bufReplay is Buffer = HexaToBuffer("0C010500000009676574696E666F0D0A01") // J'ai essayé ça aussi.
bufReplay is Buffer = [0x0C,0x01,0x05,0x00,0x00,0x00,0x09,0x67,0x65,0x74,0x69,0x6E,0x66,0x6F,0x0D,0x0A,0x01]

FOR i = 0 TO 255
nCRC = 0
nC = i
FOR j = 0 TO 7
IF ((nCRC || nC) & 0x0001) <> 0 THEN
nCRC = (nCRC bitRightShift 1) || nPoly
ELSE
nCRC = nCRC bitRightShift 1
END
nC = nC bitRightShift 1
END
tabTableCRC[i + 1] = nCRC
END

FOR j = 1 _TO_ Length(bufReplay)
nC = Asc(bufReplay[[j]]) & 0xFF
nCRC = (nCRC bitRightShift 8) || tabTableCRC[((nCRC || nC) & 0xFF) + 1]
END

Trace(nCRC) // Maintenant le résultat est 41602 à la place de 55934


Dommage que la fonction Windev sCalculeCrc16(Chaine) ne reçoit pas un paramètre en plus (une constante) pour définir l'algo CRC.

@Voroltinquo, merci en tout cas :)
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 21,septiembre 2019 - 16:20
Il te manque l'initialisation du crc avant la boucle POUR j...

--
Il y a peut être plus simple, mais, ça tourne
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 21,septiembre 2019 - 17:55
Hello,

@Voroltinquo, je vois que tu ne lâche pas toi aussi :p

J'ai essayé avec et sans initialisation de nCRC, cette fois-ci j'obtiens 61673 à la place 55934 :D

nCRC, nC are 2-byte unsigned int
tabTableCRC is array of 256 2-byte unsigned int
nPoly is 2-byte unsigned int = 0x8005

bufReplay is Buffer = [0x0C,0x01,0x05,0x00,0x00,0x00,0x09,0x67,0x65,0x74,0x69,0x6E,0x66,0x6F,0x0D,0x0A,0x01]

FOR i = 0 TO 255
nCRC = 0
nC = i
FOR j = 0 TO 7
IF ((nCRC || nC) & 0x0001) <> 0 THEN
nCRC = (nCRC bitRightShift 1) || nPoly
ELSE
nCRC = nCRC bitRightShift 1
END
nC = nC bitRightShift 1
END
tabTableCRC[i + 1] = nCRC
END

nCRC = 0
FOR j = 1 _TO_ Length(bufReplay)
nC = Asc(bufReplay[[j]]) & 0xFF
nCRC = (nCRC bitRightShift 8) || tabTableCRC[((nCRC || nC) & 0xFF) + 1]
END

Trace(nCRC) // Maintenant le résultat est 61673 à la place de 55934
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 21,septiembre 2019 - 19:31
Essaye déjà de tester la validité de la procédure avec des chaines classiques, la transformation hexa->Chaine pourra être traitée ultérieurement.
Si la procédure ne fonctionne pas, il est inutile de s'entêter, il suffira de reprendre l'algo de base et de le convertir en Windev.
Je crois que cette solution aurait été plus rapide

--
Il y a peut être plus simple, mais, ça tourne
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 23,septiembre 2019 - 07:09
En relisant le code, j'ai constaté une erreur de taille. La division binaire se fait via un décalage à gauche or dans notre cas nous avons un décalage à droite
Par ailleurs,
Mouhi a écrit :
Dommage que la fonction Windev sCalculeCrc16(Chaine) ne reçoit pas un paramètre en plus (une constante) pour définir l'algo CRC.

Il est fort probable que Windev utilise la norme internationale, à savoir le polynôme=0xA001

--
Il y a peut être plus simple, mais, ça tourne
Mensaje modificado, 23,septiembre 2019 - 07:32
Miembro registrado
81 mensajes
Popularité : +7 (7 votes)
Publicado el 23,septiembre 2019 - 18:06
youpi :merci:

J'ai remis le polynôme 0xA001 et ça fonctionne.
J'ai gardé le même décalage mais, le dernier polynôme n'était pas correct.
Je suis en colère, au final c'est exactement le même code que j'ai posté dans le premier post.
ça n'a pas fonctionné au départ car j'ai passé mon code Hexa en String à la place d'un Buffer.

Le code final (ça peut être utile pour quelqu'un d'autre qui tombe sur ce topic) :

nCRC, nC are 2-byte unsigned int
tabTableCRC is array of 256 2-byte unsigned int
nPoly is 2-byte unsigned int = 0xA001

bufReplay is Buffer = [0x0C,0x01,0x05,0x00,0x00,0x00,0x09,0x67,0x65,0x74,0x69,0x6E,0x66,0x6F,0x0D,0x0A,0x01]

FOR i = 0 TO 255
nCRC = 0
nC = i
FOR j = 0 TO 7
IF ((nCRC || nC) & 0x0001) <> 0 THEN
nCRC = (nCRC bitRightShift 1) || nPoly
ELSE
nCRC = nCRC bitRightShift 1
END
nC = nC bitRightShift 1
END
tabTableCRC[i + 1] = nCRC
END

nCRC = 0
FOR j = 1 _TO_ Length(bufReplay)
nC = Asc(bufReplay[[j]]) & 0xFF
nCRC = (nCRC bitRightShift 8) || tabTableCRC[((nCRC || nC) & 0xFF) + 1]
END

Trace(nCRC) // 55934 (en Haxa : 0x0000DA7E).


Un grand merci @Voroltinquo :)
Miembro registrado
3.844 mensajes
Popularité : +227 (347 votes)
Publicado el 24,septiembre 2019 - 12:55
La valeur 0XA001 est l'inverse bit à bit de 0x8005, (ie 0xA001 = 1010 0000 0000 0001 et 0x8005 = 1000 0000 0000 0101) d'où le décalage à droite et non à gauche

--
Il y a peut être plus simple, mais, ça tourne