Accueil > Forum > > > > Modbus RTU - Calcul du CRC 16
Modbus RTU - Calcul du CRC 16
lundi 11 mai 2009 à 13:56:53 |
Modbus RTU - Calcul du CRC 16

GingermaN
|
Bonjour a vous tous,
Je suis entrain de développer une petite appli Delphi qui permet d'aller écrire dans un registre d'un régulateur West 6100+ la valeur d'une alarme. J'utilise les composants de Tcomport pour la liaison série puis un convertisseur RS232/RS485 pour faire la liaison avec le regulateur.
Le regulateur utilise le protocole modbus soit RTU soit ASCII, j'ai donc choisi de communiquer en RTU. Mais le soucis vient du polynome imposé par le regulateur pour le calcul du CRC16, qui est le suivant: 216+215+22+1=98309
Voici ce que j'ai codé pour l'envoi de la trame: [code] procedure TForm1.ButEnvoiClick(Sender: TObject); var CRC:string; begin {ouverture du port COM} comport1.Connected:=true; ButEnvoi.Enabled:=false; {Conversion de la valeur de l'alarme en Hexa} ConcatenerValAlarme:=PanChiffre1.caption+PanChiffre2.caption+PanChiffre3.caption; ValeurAlarme:=StrToInt(ConcatenerValAlarme); Data:=inttohex(ValeurAlarme,4); Label1.Caption:=Data; {Construction de l'entete de la trame} Esclave:=IntToHex(StrToInt(CbxEsclave.Text),2); CodeFonction:=IntToHex(StrToInt(EditCdFct.Text),2); NumPara6100:=IntToHex(StrToInt(EditNumPara6100.Text),4); {Assemblage de la trame sans CRC16} TrameModbus:=Esclave+CodeFonction+NumPara6100+Data; Label2.Caption:=TrameModbus; {Calcul de CRC16} CRC:=CalcCRC16(TrameModbus); Label3.Caption:=CRC; TrameModbusCRC16:=TrameModbus+CRC; Label4.Caption:=TrameModbusCRC16; {écriture de la trame sur le port COM} comport1.WriteStr(TrameModbusCRC16); {{Reception trame reponse (Facultatif, si 1 seul esclave, envoie de la trame à l'adresse esclave 0 en broadcast car pas de reponse de l'esclave dans ce cas)} Comport1.ClearBuffer(True,False); // Supression de ce qui traine dans le buffer d'entrée long:=Comport1.ReadStr(TrameRecue,LongueurTrame);// Lecture bloquante de la longueur demandée} Label5.Caption:=TrameRecue; {fermeture de port COM} comport1.Connected:=false; ButEnvoi.Enabled:=true; end; [/code] et voici ma procedure de calcul du CRC [code] Function CalcCRC16(trame:string):string; var octet:char; ajout:boolean; CRC16:WORD; i,j:integer; begin CRC16:=$FFFF; for i:=0 to length(trame)-1 do begin octet:=trame[i]; CRC16:=(CRC16) xor ord(octet); for j:=1 to 8 do begin if odd(CRC16) then ajout:=true else begin ajout:=false; CRC16:=CRC16 div 2; end; if ajout=true then begin CRC16:=CRC16+98309; result:= IntToHex(CRC16,4); end; end; end; end; [/code] Est ce que mon code de calcul du CRC vous semble correct, car lorsque je test mon appli, je visualise mon CRC dans un label, mais si je change ma valeur de 3 ou 4 unité, ma trame change bien mais le CRC non. par exemple, je met ma valeur d'alarme a 185 ma trame sera: 01 06 000D 00B9 A8DA // A8DA etant mon CRC. Pour 189 ma trame sere 01 06 000D 00B9 A8DA // le CRC est toujours A8DA. Il faut que je monte a 192 pour voir mon CRC changer, pour cette valeur il est a : E9B0. cela me parait bizarre car la trame changeant, le CRC devrait aussi changer, non? En vous remerciant par avance. Cordialement, Jonathan PS: Au besoin je peux vous zipper et vous envoyer l'appli complete.
|
|
lundi 11 mai 2009 à 17:30:14 |
Re : Modbus RTU - Calcul du CRC 16

Kenavo
|
Salut,
begin CRC16 := $FFFF; for i := 1 to length(trame) do // caractères : trame[i] à trame[length(trame)] begin octet := trame[i]; CRC16 := (CRC16) xor ord(octet); for j := 1 to 8 do begin if odd(CRC16) then // ou : if Ajout := odd (CRC16) {plus élégant} ajout := true else begin ajout := false; CRC16 := CRC16 div 2; // quelque soit le résultat de Odd(CRC16) end; if ajout = true then // pas beau !!!! begin
CRC16 := CRC16 xor $A001; // il me semble .... result := IntToHex(CRC16, 4); // le résultat n'est pas mis à jour // à chaque boucle : à déplacer à la fin // de la fonction end; end; end; result := IntToHex(CRC16, 4); end;
Ken@vo
Code, Code, Codec !
|
|
lundi 11 mai 2009 à 17:47:11 |
Re : Modbus RTU - Calcul du CRC 16

GingermaN
|
Merci bien, J'essayerai dans la soirée. Apres pour la structure proprement dite, je l'ai reprise de mon cours de "bus de terrain que j'ai eu a l'IUT, commme quoi... En tout cas encore merci. Si, est tu sure pour le for i:=1 to length(Trame) car une chaine de caractere est un tableau a 1 dimension commencent a l'indice 0, non, enfin c'est ce que je croyais jusqu'a aujourd'hui 
|
|
lundi 11 mai 2009 à 17:58:40 |
Re : Modbus RTU - Calcul du CRC 16

GingermaN
|
Ah oui, désolé, pour le "flood" j'ai pas trouvé pour éditer mon post.  Pour la valeur $A001, d'apres mon cours, cela correspond au polynome x 15+x 13+x 0 et le polynome utilisé dans le regulateur pour calculer le crc est: 2 16+2 15+2 2+1. cordialement, Jonathan
|
|
lundi 11 mai 2009 à 19:18:07 |
Re : Modbus RTU - Calcul du CRC 16

jlen100
|
Les chaines sont des tableaux particuliers elle comment à l'indice 1 l'indice 0 est réservé à la longueur pour les chaines courtes <255 caractères pour les chaines longues ce sont les indices 0 à -3 qui contiennent la longueur c'est en C que les chaines commencent à l'indice 0 et se terminent par un 0
@+ jlen
|
|
lundi 11 mai 2009 à 19:36:27 |
Re : Modbus RTU - Calcul du CRC 16

Kenavo
|
Salut,
Merci à jlen100 pour cette précision !
Je ne sais pas d'où vient ce polynome que tu utilises, mais je confirme !
Voir ici, page 112 (http://www.modbus.org/docs/PI_MBUS_300.pdf)
Ken@vo Code, Code, Codec !
|
|
lundi 11 mai 2009 à 20:04:20 |
Re : Modbus RTU - Calcul du CRC 16

GingermaN
|
Merci jlen, pour la précision. Kenavo, mon polynome sort d'ici: [ Lien ] à la page 67. Je test ta solution au boulot demain avec le régulateur, et je te tiens au courant. Merci a vous deux!
|
|
mardi 12 mai 2009 à 09:14:19 |
Re : Modbus RTU - Calcul du CRC 16
|
mardi 12 mai 2009 à 09:19:49 |
Re : Modbus RTU - Calcul du CRC 16

GingermaN
|
Bonjour Kenavo, Je viens de tester ta version de ma fonction, et il y a un truc qui va pas, pour n'importe quelle valeur mon CRC=$C001  . Mais je pense savoir d'ou ca vient, il suffit que la variable ajout soit mise a true des la premeire boucle, et elle reste a true tout le long du calcul, ce qui par conséquent a chaque fois, on fait CRC16 xor $A001 qu'il y ai parité ou non. begin CRC16 := $FFFF; for i := 1 to length(trame) do // caractères : trame[i] à trame[length(trame)] begin octet := trame[i]; CRC16 := (CRC16) xor ord(octet); for j := 1 to 8 do begin if odd(CRC16) then // ou : if Ajout := odd(CRC16) {plus élégant} ajout := true else begin ajout := false; CRC16 := CRC16 div 2; // quelque soit le résultat de Odd(CRC16) end; if ajout = true then // pas beau !!!! begin
CRC16 := CRC16 xor $A001; // il me semble .... Ajout := false; end; end; end; result := IntToHex(CRC16, 4);end;Parcontre je n'ai pas encore pu tester sur le régulateur car nous en pleine production. Encore merci en tout cas!
|
|
mardi 12 mai 2009 à 15:16:00 |
Re : Modbus RTU - Calcul du CRC 16

Kenavo
|
Réponse acceptée !
Salut,
Et salut à toi JulioDelphi !
Exact pour ajout ... Ce qui donne au propre : begin CRC16 := $FFFF; for i := 1 to length(trame) do begin octet := trame[i]; CRC16 := (CRC16) xor ord(octet); for j := 1 to 8 do begin Ajout := odd (CRC16) ; CRC16 := CRC16 div 2; if ajout then CRC16 := CRC16 xor $A001; end; end; result := IntToHex(CRC16, 4); end; Pour le polynôme générateur :
Each message is followed by CRC (Cyclic Redundancy Check) with two byte. The CRC identify the incongruity situations of the message, in this case the receiver ignore the message. The CRC is calculated in accordance with a formula that imply a recursive division of the data by a polynomial. The polynomial divisor is: 216 + 215 + 22 + 1(Hex 18005) but is modified in two ways: . Since the bits order are reversed, then the binary pattern is also reversed, and the most significant bit (MSB) is the right-most bit. . Since interest only the remainder, the right-most bit could be discarded. Therefore, the polynomial divisor has value: Hex A001
Ken@vo
Code, Code, Codec !
|
|
Cette discussion est classée dans : caption, calcul, crc, trame, crc16
Répondre à ce message
Sujets en rapport avec ce message
Recherche type de CRC dans une trame de données [ par chimimic ]
Bonjour à tous,je cherche à établir une communication entre un PC et un équipement, via une liaison série standard RS232.J'ai déjà pu récupérer des tr
pb de calcul ... [ par etrix ]
salut !voila j'ai mon calcul:with Form1 doC2.Caption:= InttoStr(strToInt(E1.Caption) / strToInt(K2.Caption) - strToInt(k1.Caption) * strToInt(100);ne
pb de calcul ... [ par etrix ]
salut !voila j'ai mon calcul:with Form1 doC2.Caption:= InttoStr(strToInt(E1.Caption) / strToInt(K2.Caption) - strToInt(k1.Caption) * strToInt(100);ne
Calcul de date [ par seawolf ]
Je voudrais savoir pourquoi quand je soustrait 2 dates il me retourne une date au lieu de me retourner un entier qui correspond au nombre de jours ent
variable dans le nom d'un composant [ par thonyboy ]
Bonjour,Je cherche a faire un truc du genre :Supposons X composants Tlabels et 1 variable ICase of I 1: Tlabel1.caption := 'Label1' 2: Tlabel2.capti
CRC et compression [ par costello ]
re bonjour est ce que quelqu'un aurait un moyen de répondre à une question qui me pose un réel problème...- comment savoir le CRC d'un fichier contenu
calcul d'heures sous Access [ par luckylucky ]
comment peut-on additionner ou soustraire des heures sur access en concervant le format date, heure et obtenir un résultat sous ce format qui puisse i
Calcul dans TStrinGrid [ par goose84 ]
Bonjour,Voila, j'ai donc dans un TStringGrid des lignes de matières (1° colonne avec a la fin en constante (TOTAL et RESTE)) et une colonne indiquant
Label [ par UserXW ]
Slt:J'ai un souci avec un composant ... (Boite A propos sous forme de composant) voici donc :(parti du code source)private fCopyright: string; f
jm'étais trompé dans le code afficher audessu mais c'est pour la même kestion ! :D [ par Manouai ]
:D :) 8D[Code]if ( temp = 2) then begin shape2.brush.color := clmenu; shape2.enabled := true; player := player *-1; scorehorizon[1]:=scoreh
Livres en rapport
|
Derniers Blogs
[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE par orion
Comme de nombreux geek, je suis un grand amateur de série TV et je rate régulièrement des épisodes de mes séries préférés. Une solution s'offre à vous avec ce merveilleux site : Tv Gorge - www.tvgorge.com Moteur de recherche à l'appui, vous pouvez ...
Cliquez pour lire la suite de l'article par orion TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Arnault Nouvel et Antoine Dongois Le processus à prendre : Apprendre (découvrir la plateforme) Préparer (documenter l'historique et choisir la méthode de MAJ) Test (Test de MAJ) Implémenter (Effectuer la MAJ) Valid...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOURTECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOUR par ROMELARD Fabrice
Après un retour sur l'histoire des TechDays de Paris et le fait que ce soit le plus gros event MS au monde (du fait de sa gratuité), le président de MS France (Eric Boustoullier) a fait une présentation de la vision Microsoft pour les années à venir...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|