Quand on parle de communication entre une machine et un PC (ou un automate), c’est un dialogue en question/réponse. Mais si on peut envoyer n’importe quoi, il faut quand même que la machine comprenne en quelle langue on parle et comment décoder la trame. Pour ce faire, on utilise le CRC (Contrôle de redondance cyclique) et il en existe plusieurs en fonction du type de codage utilisé (8, 16 ou 32 bits) pour la communication.
Le plus souvent, on utilise un CRC16, c’est le système le plus courant, l’autre étant le 32 bits (CRC32).
Le calcul du CRC fait appel à des notions de programmation logique avec des OR, XOR, AND et XAND… autant dire que si on ne connait pas c’est le bordel, et même moi qui connait le principe je n’arrive pas à le traduire en code. Ci dessous vous trouverez deux fonctions, CRC16 et AddCRC16 :
- CRC16 : renvoie un tableau contenant le bit de poids fort et le bit de poids faible en fonction d’une trame sans CRC en Byte().
- AddCRC16 : corrige la trame envoyé sans CRC en Byte() en rajoutant le CRC à la fin.
Quand on souhaite envoyer une trame, on a souvent besoin d’ajouter le CRC après calcul quand le trame est variable, d’où la modification de la fonction CRC16 (qui n’est pas de moi) en AddCRC16 (que j’ai adapté) qui permet de restituer une trame exploitable immédiatement.
Function CRC16(ByVal data() As Byte) As Array Dim CRC16Lo As Byte, CRC16Hi As Byte 'CRC register Dim CL As Byte, CH As Byte 'Polynomial codes & HA001 Dim SaveHi As Byte, SaveLo As Byte Dim i As Integer Dim Flag As Integer Dim ReturnData(2) As Byte CRC16Lo = &HFF CRC16Hi = &HFF CL = &H1 CH = &HA0 For i = 0 To UBound(data) CRC16Lo = CRC16Lo Xor data(i) 'for each data and CRC register XOR For Flag = 0 To 7 SaveHi = CRC16Hi SaveLo = CRC16Lo CRC16Hi = CRC16Hi 2 'peak shift to the right one CRC16Lo = CRC16Lo 2 'shift to the right a low If ((SaveHi And &H1) = &H1) Then 'If the high byte last one for a CRC16Lo = CRC16Lo Or &H80 'then the low byte shifted to the right after the meeting in front of a End If 'Otherwise, auto-fill 0 If ((SaveLo And &H1) = &H1) Then 'If the LSB is 1, then XOR with the polynomial codes CRC16Hi = CRC16Hi Xor CH CRC16Lo = CRC16Lo Xor CL End If Next Flag Next i ReturnData(0) = CRC16Hi 'CRC high ReturnData(1) = CRC16Lo 'CRC low Return ReturnData End Function
Fonction suivante…
Function AddCRC16(ByVal data() As Byte) As Byte() Dim CRC16Lo As Byte, CRC16Hi As Byte 'CRC register Dim CL As Byte, CH As Byte 'Polynomial codes & HA001 Dim SaveHi As Byte, SaveLo As Byte Dim i As Integer Dim Flag As Integer 'Dim ReturnData(2) As Byte CRC16Lo = &HFF CRC16Hi = &HFF CL = &H1 CH = &HA0 For i = 0 To UBound(data) CRC16Lo = CRC16Lo Xor data(i) 'for each data and CRC register XOR For Flag = 0 To 7 SaveHi = CRC16Hi SaveLo = CRC16Lo CRC16Hi = CRC16Hi 2 'peak shift to the right one CRC16Lo = CRC16Lo 2 'shift to the right a low If ((SaveHi And &H1) = &H1) Then 'If the high byte last one for a CRC16Lo = CRC16Lo Or &H80 'then the low byte shifted to the right after the meeting in front of a End If 'Otherwise, auto-fill 0 If ((SaveLo And &H1) = &H1) Then 'If the LSB is 1, then XOR with the polynomial codes CRC16Hi = CRC16Hi Xor CH CRC16Lo = CRC16Lo Xor CL End If Next Flag Next i 'Agrandissement du data pour mettre 2 paramètres supplémentaires ReDim Preserve data(UBound(data) + 2) 'Stock le CRC data(UBound(data) - 1) = Convert.ToByte(CRC16Lo) data(UBound(data)) = Convert.ToByte(CRC16Hi) Return data End Function
Bien sur il faut quand même créer la trame pour lui ajouter le CRC. Dans le prochain chapitre, je donnerais deux fonctions pour créer des trames de lecture et d’écriture qui font justement appellent à la fonction AddCRC16.