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.