Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Le_Pont_V10015 by
Modbus.cpp
00001 /***********************************************************************************/ 00002 // 00003 // Gestion du Modbus 00004 // 00005 //************************************************************************************/ 00006 00007 #include <mbed.h> 00008 #include "Modbus.h" 00009 #include "Port_Serie.h" 00010 00011 00012 //volatile U8 Numero_Ordre_En_Cours_U8 ; 00013 volatile Ordre_Modbus_t Ordres[TAILLE_PILE_ORDRES] ; 00014 00015 00016 Serial PC7(USBTX, USBRX) ; 00017 00018 /************ Initialisation du Modbus ************************/ 00019 void vModbus_Init(int Baudrate) 00020 { 00021 U8 Numero_Ordre_U8 ; 00022 00023 vPort_Serie_Init( Baudrate ) ; 00024 00025 for ( Numero_Ordre_U8 = 0 ; Numero_Ordre_U8 < TAILLE_PILE_ORDRES ; Numero_Ordre_U8++ ) 00026 { 00027 // Effacement des ordres 00028 Ordres[Numero_Ordre_U8].Etat_U8 = ARRET ; 00029 Ordres[Numero_Ordre_U8].Nb_Caracteres_Recus_U8 = 0 ; 00030 Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = 0 ; 00031 Ordres[Numero_Ordre_U8].Code_Erreur = 0 ; 00032 } 00033 00034 00035 PC7.printf("\r\n Modbus : Init ") ; 00036 } 00037 00038 00039 /************* Demarrage du Modbus ****************************/ 00040 void vModbus_Start() 00041 { 00042 //Ordres[Numero_Ordre_En_Cours_U8].Etat_U8 = ATTENTE ; 00043 vPort_Serie_Ouvre() ; 00044 //vPort_Serie_Reception ( 0 ) ; 00045 PC7.printf("\r\n Modbus : Start ") ; 00046 } 00047 00048 static const U8 aucCRCHi[] = { 00049 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00050 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00051 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00052 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00053 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00054 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00055 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00056 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00057 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00058 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00059 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00060 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00061 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00062 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00063 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00064 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00065 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00066 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 00067 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00068 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 00069 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 00070 0x00, 0xC1, 0x81, 0x40 00071 }; 00072 00073 static const U8 aucCRCLo[] = { 00074 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 00075 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 00076 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 00077 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 00078 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 00079 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 00080 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 00081 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 00082 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 00083 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 00084 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 00085 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 00086 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 00087 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 00088 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 00089 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 00090 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 00091 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 00092 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 00093 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 00094 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 00095 0x41, 0x81, 0x80, 0x40 00096 }; 00097 00098 00099 U16 CRC16( U8 * pucFrame, U8 usLen ) 00100 { 00101 U8 ucCRCHi = 0xFF; 00102 U8 ucCRCLo = 0xFF; 00103 int iIndex; 00104 00105 while( usLen-- ) 00106 { 00107 //PC7.printf("/ %X /", *pucFrame) ; 00108 iIndex = ucCRCLo ^ *( pucFrame++ ); 00109 ucCRCLo = ( U8 )( ucCRCHi ^ aucCRCHi[iIndex] ); 00110 ucCRCHi = aucCRCLo[iIndex]; 00111 } 00112 //PC7.printf("\n\r CRC: %X",(ucCRCHi << 8 | ucCRCLo)) ; 00113 return ( U16 )( ucCRCHi << 8 | ucCRCLo ); 00114 } 00115 00116 /************* Traitement du Modbus ****************************/ 00117 void vModbus() 00118 { 00119 U8 Numero_Ordre_U8 ; 00120 U16 Valeur_U16 ; 00121 U8 Ordres_Arretes_U8 = 0 ; 00122 U8 Index_CRC_U8 ; 00123 U8 Index_Caractere_U8 ; 00124 U16 Index_Memoire_U16 ; 00125 00126 for ( Numero_Ordre_U8 = 0 ; Numero_Ordre_U8 < TAILLE_PILE_ORDRES ; Numero_Ordre_U8++ ) 00127 { 00128 00129 if ( Ordres[Numero_Ordre_U8].Etat_U8 == RECU ) 00130 {// Puisque la trame est complete, on peut la traiter 00131 //PC7.printf("\n\rOrdre : %i recu",Numero_Ordre_U8) ; 00132 if ( Numero_Ordre_U8 < ( TAILLE_PILE_ORDRES - 1 ) ) 00133 {// Enclenche l'ordre suivant 00134 vPort_Serie_Reception ( Numero_Ordre_U8 + 1 ) ; 00135 } 00136 else 00137 {// Enclenche l'ordre 0 00138 vPort_Serie_Reception ( 0 ) ; 00139 } 00140 // Adresse 00141 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0] = SLAVE_ID ; 00142 // Fonction 00143 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[1] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] ; 00144 00145 if (( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_READ_HOLDING_REGISTER ) 00146 || ( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_READ_INPUT_REGISTER )) 00147 {// Fonction 3 ou 4, Lecture de registres 00148 // Nombre d'octets 00149 //PC7.printf("\n\rOrdre Func: %i",Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1]) ; 00150 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] = 2 * Ordres[Numero_Ordre_U8].Trame_Recue_aU8[5] ; 00151 // Registre de départ = Hi * 256 + Lo + Base 00152 Index_Memoire_U16 = REG_INPUT_START + (U16)(Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2]) * 256 00153 + (U16)Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; 00154 //PC7.printf("\r\n %i :",Index_Memoire_U16) ; 00155 Index_Caractere_U8 = 0 ; 00156 while ( Index_Caractere_U8 < Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] ) 00157 { 00158 // Octet de poids fort du registre 00159 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 3] = (U8) (Memoire_S16 [ Index_Memoire_U16 ] >> 8 ) ; 00160 // Octet de poids faible 00161 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 4] = (U8) ( Memoire_S16 [ Index_Memoire_U16 ] & 0xFF ) ; 00162 //PC7.printf("/ %X / %X /",Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 3],Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 4]) ; 00163 Index_Caractere_U8 = Index_Caractere_U8 + 2 ; 00164 Index_Memoire_U16++ ; 00165 } 00166 00167 // Calcul de la position du CRC 00168 Index_CRC_U8 = 3 + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] ; 00169 // Calcul du CRC 00170 Valeur_U16 = CRC16 ( (U8 *) &(Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0]) , Index_CRC_U8 ) ; 00171 00172 // CRC Poids fort 00173 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 ] = (U8) ( Valeur_U16 & 0xFF ) ; 00174 // CRC Poids faible 00175 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 + 1 ] = (U8) ( Valeur_U16 >> 8 ) ; 00176 // Longueur de trame à emettre 00177 Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = Index_CRC_U8 + 2 ; 00178 } 00179 else if ( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_WRITE_MULTIPLE_REGISTERS ) 00180 {// Fonction 16 (0x10) écriture multiple 00181 //PC7.printf("\n\rOrdre Func: %i",Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1]) ; 00182 // Registre de départ poids fort 00183 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2] ; 00184 // Registre de départ poids faible 00185 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[3] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; 00186 // Nombre de registres poids fort 00187 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[4] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[4] ; 00188 // Nombre de registres poids faible 00189 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[5] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[5] ; 00190 00191 // Registre de départ = Hi * 256 + Lo + Base 00192 Index_Memoire_U16 = REG_INPUT_START + (U16)(Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2]) * 256 00193 + (U16)Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; 00194 Index_Caractere_U8 = 0 ; 00195 while ( Index_Caractere_U8 < Ordres[Numero_Ordre_U8].Trame_Recue_aU8[6] ) 00196 { 00197 // Ecriture des registres 00198 Memoire_S16 [ Index_Memoire_U16 ] = (S16) (Ordres[Numero_Ordre_U8].Trame_Recue_aU8[ 7 + Index_Caractere_U8 ]) * 256 00199 + (S16) Ordres[Numero_Ordre_U8].Trame_Recue_aU8[ 8 + Index_Caractere_U8 ]; 00200 Index_Caractere_U8 = Index_Caractere_U8 + 2 ; 00201 Index_Memoire_U16++ ; 00202 00203 } 00204 // Calcul du CRC 00205 Valeur_U16 = CRC16 ( (U8 *) &(Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0]) , 6 ) ; 00206 // Calcul de la position du CRC 00207 Index_CRC_U8 = 6 ; 00208 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8] = (U8) ( Valeur_U16 & 0xFF ) ; 00209 Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 + 1 ] = (U8) ( Valeur_U16 >> 8 ); 00210 // Longueur de trame à emettre 00211 Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = 8 ; 00212 } 00213 // La trame de réponse est terminée 00214 Ordres[Numero_Ordre_U8].Etat_U8 = TRAITE ; 00215 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,TRAITE) ; 00216 // Lancement de l'émission de la réponse 00217 vPort_Serie_Emission ( Numero_Ordre_U8 ) ; 00218 } 00219 00220 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == FIN ) 00221 {// La réponse est émise, cloture l'ordre 00222 Ordres[Numero_Ordre_U8].Etat_U8 = ARRET ; 00223 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,FIN) ; 00224 } 00225 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == EMISSION ) 00226 {// L'emission de la réponse n'est pas terminée, re-essaie 00227 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,EMISSION) ; 00228 vPort_Serie_Emission ( Numero_Ordre_U8 ); 00229 } 00230 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == ARRET ) 00231 {// Compte les ordres arretés 00232 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,ARRET) ; 00233 Ordres_Arretes_U8++ ; 00234 } 00235 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == RECEPTION ) 00236 {// Controle si les temps ne sont pas dépassés 00237 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,RECEPTION) ; 00238 //Ordres[Numero_Ordre_U8].Etat_U8 = cControle_Reception( Numero_Ordre_U8 ); 00239 } 00240 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == ATTENTE ) 00241 {// Controle si les temps ne sont pas dépassés 00242 //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,ATTENTE) ; 00243 } 00244 else if ( Ordres[Numero_Ordre_U8].Etat_U8 == TIMEOUT ) 00245 {// Les temps sont dépassés 00246 Ordres[Numero_Ordre_U8].Etat_U8 = ARRET; 00247 } 00248 //PC7.printf("\r\n Modbus : %i \t %i \r\n",Numero_Ordre_U8,Ordres[Numero_Ordre_U8].Etat_U8 ); 00249 } 00250 if (Ordres_Arretes_U8 >= TAILLE_PILE_ORDRES ) 00251 {// Si tous les ordres sont arretés, le prochain aura l'index 0 00252 vPort_Serie_Reception ( 0 ) ; 00253 } 00254 } 00255 00256 extern void vModbus_Stop() 00257 { 00258 } 00259 extern void vModbus_Reset() 00260 { 00261 } 00262 00263
Generated on Tue Jul 12 2022 13:32:39 by
