SAGNES Christophe / Mbed 2 deprecated Le_Pont_V10015

Dependencies:   mbed

Fork of Le_Pont_V10015 by 3R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Modbus.cpp Source File

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