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
Diff: Modbus.cpp
- Revision:
- 0:a53b6ec3fbb3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modbus.cpp Mon May 30 07:04:49 2016 +0000 @@ -0,0 +1,263 @@ +/***********************************************************************************/ +// +// Gestion du Modbus +// +//************************************************************************************/ + +#include <mbed.h> +#include "Modbus.h" +#include "Port_Serie.h" + + +//volatile U8 Numero_Ordre_En_Cours_U8 ; +volatile Ordre_Modbus_t Ordres[TAILLE_PILE_ORDRES] ; + + +Serial PC7(USBTX, USBRX) ; + +/************ Initialisation du Modbus ************************/ +void vModbus_Init(int Baudrate) + { + U8 Numero_Ordre_U8 ; + + vPort_Serie_Init( Baudrate ) ; + + for ( Numero_Ordre_U8 = 0 ; Numero_Ordre_U8 < TAILLE_PILE_ORDRES ; Numero_Ordre_U8++ ) + { + // Effacement des ordres + Ordres[Numero_Ordre_U8].Etat_U8 = ARRET ; + Ordres[Numero_Ordre_U8].Nb_Caracteres_Recus_U8 = 0 ; + Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = 0 ; + Ordres[Numero_Ordre_U8].Code_Erreur = 0 ; + } + + + PC7.printf("\r\n Modbus : Init ") ; + } + + +/************* Demarrage du Modbus ****************************/ +void vModbus_Start() + { + //Ordres[Numero_Ordre_En_Cours_U8].Etat_U8 = ATTENTE ; + vPort_Serie_Ouvre() ; + //vPort_Serie_Reception ( 0 ) ; + PC7.printf("\r\n Modbus : Start ") ; + } + +static const U8 aucCRCHi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40 +}; + +static const U8 aucCRCLo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, + 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, + 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, + 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, + 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, + 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, + 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, + 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40 +}; + + +U16 CRC16( U8 * pucFrame, U8 usLen ) +{ + U8 ucCRCHi = 0xFF; + U8 ucCRCLo = 0xFF; + int iIndex; + + while( usLen-- ) + { + //PC7.printf("/ %X /", *pucFrame) ; + iIndex = ucCRCLo ^ *( pucFrame++ ); + ucCRCLo = ( U8 )( ucCRCHi ^ aucCRCHi[iIndex] ); + ucCRCHi = aucCRCLo[iIndex]; + } + //PC7.printf("\n\r CRC: %X",(ucCRCHi << 8 | ucCRCLo)) ; + return ( U16 )( ucCRCHi << 8 | ucCRCLo ); +} + +/************* Traitement du Modbus ****************************/ +void vModbus() + { + U8 Numero_Ordre_U8 ; + U16 Valeur_U16 ; + U8 Ordres_Arretes_U8 = 0 ; + U8 Index_CRC_U8 ; + U8 Index_Caractere_U8 ; + U16 Index_Memoire_U16 ; + + for ( Numero_Ordre_U8 = 0 ; Numero_Ordre_U8 < TAILLE_PILE_ORDRES ; Numero_Ordre_U8++ ) + { + + if ( Ordres[Numero_Ordre_U8].Etat_U8 == RECU ) + {// Puisque la trame est complete, on peut la traiter + //PC7.printf("\n\rOrdre : %i recu",Numero_Ordre_U8) ; + if ( Numero_Ordre_U8 < ( TAILLE_PILE_ORDRES - 1 ) ) + {// Enclenche l'ordre suivant + vPort_Serie_Reception ( Numero_Ordre_U8 + 1 ) ; + } + else + {// Enclenche l'ordre 0 + vPort_Serie_Reception ( 0 ) ; + } + // Adresse + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0] = SLAVE_ID ; + // Fonction + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[1] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] ; + + if (( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_READ_HOLDING_REGISTER ) + || ( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_READ_INPUT_REGISTER )) + {// Fonction 3 ou 4, Lecture de registres + // Nombre d'octets + //PC7.printf("\n\rOrdre Func: %i",Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1]) ; + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] = 2 * Ordres[Numero_Ordre_U8].Trame_Recue_aU8[5] ; + // Registre de départ = Hi * 256 + Lo + Base + Index_Memoire_U16 = REG_INPUT_START + (U16)(Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2]) * 256 + + (U16)Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; + //PC7.printf("\r\n %i :",Index_Memoire_U16) ; + Index_Caractere_U8 = 0 ; + while ( Index_Caractere_U8 < Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] ) + { + // Octet de poids fort du registre + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 3] = (U8) (Memoire_S16 [ Index_Memoire_U16 ] >> 8 ) ; + // Octet de poids faible + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_Caractere_U8 + 4] = (U8) ( Memoire_S16 [ Index_Memoire_U16 ] & 0xFF ) ; + //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]) ; + Index_Caractere_U8 = Index_Caractere_U8 + 2 ; + Index_Memoire_U16++ ; + } + + // Calcul de la position du CRC + Index_CRC_U8 = 3 + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] ; + // Calcul du CRC + Valeur_U16 = CRC16 ( (U8 *) &(Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0]) , Index_CRC_U8 ) ; + + // CRC Poids fort + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 ] = (U8) ( Valeur_U16 & 0xFF ) ; + // CRC Poids faible + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 + 1 ] = (U8) ( Valeur_U16 >> 8 ) ; + // Longueur de trame à emettre + Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = Index_CRC_U8 + 2 ; + } + else if ( Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1] == MB_FUNC_WRITE_MULTIPLE_REGISTERS ) + {// Fonction 16 (0x10) écriture multiple + //PC7.printf("\n\rOrdre Func: %i",Ordres[Numero_Ordre_U8].Trame_Recue_aU8[1]) ; + // Registre de départ poids fort + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[2] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2] ; + // Registre de départ poids faible + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[3] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; + // Nombre de registres poids fort + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[4] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[4] ; + // Nombre de registres poids faible + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[5] = Ordres[Numero_Ordre_U8].Trame_Recue_aU8[5] ; + + // Registre de départ = Hi * 256 + Lo + Base + Index_Memoire_U16 = REG_INPUT_START + (U16)(Ordres[Numero_Ordre_U8].Trame_Recue_aU8[2]) * 256 + + (U16)Ordres[Numero_Ordre_U8].Trame_Recue_aU8[3] ; + Index_Caractere_U8 = 0 ; + while ( Index_Caractere_U8 < Ordres[Numero_Ordre_U8].Trame_Recue_aU8[6] ) + { + // Ecriture des registres + Memoire_S16 [ Index_Memoire_U16 ] = (S16) (Ordres[Numero_Ordre_U8].Trame_Recue_aU8[ 7 + Index_Caractere_U8 ]) * 256 + + (S16) Ordres[Numero_Ordre_U8].Trame_Recue_aU8[ 8 + Index_Caractere_U8 ]; + Index_Caractere_U8 = Index_Caractere_U8 + 2 ; + Index_Memoire_U16++ ; + + } + // Calcul du CRC + Valeur_U16 = CRC16 ( (U8 *) &(Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[0]) , 6 ) ; + // Calcul de la position du CRC + Index_CRC_U8 = 6 ; + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8] = (U8) ( Valeur_U16 & 0xFF ) ; + Ordres[Numero_Ordre_U8].Trame_Reponse_aU8[ Index_CRC_U8 + 1 ] = (U8) ( Valeur_U16 >> 8 ); + // Longueur de trame à emettre + Ordres[Numero_Ordre_U8].Nb_Caracteres_A_Emettre_U8 = 8 ; + } + // La trame de réponse est terminée + Ordres[Numero_Ordre_U8].Etat_U8 = TRAITE ; + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,TRAITE) ; + // Lancement de l'émission de la réponse + vPort_Serie_Emission ( Numero_Ordre_U8 ) ; + } + + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == FIN ) + {// La réponse est émise, cloture l'ordre + Ordres[Numero_Ordre_U8].Etat_U8 = ARRET ; + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,FIN) ; + } + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == EMISSION ) + {// L'emission de la réponse n'est pas terminée, re-essaie + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,EMISSION) ; + vPort_Serie_Emission ( Numero_Ordre_U8 ); + } + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == ARRET ) + {// Compte les ordres arretés + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,ARRET) ; + Ordres_Arretes_U8++ ; + } + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == RECEPTION ) + {// Controle si les temps ne sont pas dépassés + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,RECEPTION) ; + //Ordres[Numero_Ordre_U8].Etat_U8 = cControle_Reception( Numero_Ordre_U8 ); + } + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == ATTENTE ) + {// Controle si les temps ne sont pas dépassés + //PC7.printf("\n\rOrdre %i Etat: %i",Numero_Ordre_U8,ATTENTE) ; + } + else if ( Ordres[Numero_Ordre_U8].Etat_U8 == TIMEOUT ) + {// Les temps sont dépassés + Ordres[Numero_Ordre_U8].Etat_U8 = ARRET; + } + //PC7.printf("\r\n Modbus : %i \t %i \r\n",Numero_Ordre_U8,Ordres[Numero_Ordre_U8].Etat_U8 ); + } + if (Ordres_Arretes_U8 >= TAILLE_PILE_ORDRES ) + {// Si tous les ordres sont arretés, le prochain aura l'index 0 + vPort_Serie_Reception ( 0 ) ; + } + } + + extern void vModbus_Stop() + { + } + extern void vModbus_Reset() + { + } + +