modbus slaver

Files at this revision

API Documentation at this revision

Comitter:
yao6116601
Date:
Tue Sep 17 01:59:40 2019 +0000
Commit message:
modbus server

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
modbus/modbus.cpp Show annotated file Show diff for this revision Revisions of this file
modbus/modbus.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,2 @@
+# simple modbus communication on mbed OS
+for control 10 DigitalIn & 10 DigitalOut
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,173 @@
+#include "mbed.h"
+#include "modbus.h"
+DigitalOut led1(PC_6);
+
+DigitalIn DI0(PF_5);
+DigitalIn DI1(PF_3);
+DigitalIn DI2(PF_7);
+DigitalIn DI3(PF_6);
+DigitalIn DI4(PA_5);
+DigitalIn DI5(PB_8);
+DigitalIn DI6(PF_10);
+DigitalIn DI7(PF_4);
+DigitalIn DI8(PF_8);
+DigitalIn DI9(PF_9);
+
+DigitalOut DO0(PE_11);
+DigitalOut DO1(PE_7);
+DigitalOut DO2(PB_0);
+DigitalOut DO3(PA_4);
+DigitalOut DO4(PC_2);
+DigitalOut DO5(PF_2);
+DigitalOut DO6(PF_0);
+DigitalOut DO7(PF_1);
+DigitalOut DO8(PC_0);
+DigitalOut DO9(PC_3);
+//
+DigitalOut HF(PD_14);
+Modbus slave(PB_6,PB_7,PD_12,9600);
+uint8_t myAddress=0x01;
+uint16_t data[32];
+uint16_t readDI(uint16_t address)
+{ 
+   uint16_t terminal=address-100;
+   switch(terminal)
+   {
+       case 0:{
+           if (DI0) return 0xffff;
+           else return 0;
+           } 
+     case 1:{
+          if (DI1) return 0xffff;
+           else return 0;
+          } 
+     case 2:{
+        if (DI2) return 0xffff;
+           else return 0;
+            } 
+     case 3:{
+         if (DI3) return 0xffff;
+           else return 0;
+            } 
+     case 4:{
+            if (DI4) return 0xffff;
+           else return 0;
+             } 
+     case 5:{
+             if (DI5) return 0xffff;
+           else return 0;
+             } 
+     case 6:{
+             if (DI6) return 0xffff;
+           else return 0;
+            } 
+     case 7:{
+            if (DI7) return 0xffff;
+           else return 0;
+            } 
+     case 8:{
+           if (DI8) return 0xffff;
+           else return 0;
+           } 
+     case 9:{
+            if (DI9) return 0xffff;
+           else return 0;
+            } 
+     } 
+   return 0;  
+ }
+ uint16_t writeDO(uint16_t address,uint16_t value)
+{ 
+   uint16_t terminal=address-100;
+   switch(terminal)
+   {
+       case 0:{
+           DO0=value&0x0001;
+           if (DO0) return 0xffff;
+           else return 0;
+           } 
+     case 1:{
+          DO1=value&0x0001;
+          if (DO1) return 0xffff;
+           else return 0;
+          } 
+     case 2:{
+        DO2=value&0x0001;
+        if (DO2) return 0xffff;
+           else return 0;
+            } 
+     case 3:{
+         DO3=value&0x0001;
+         if (DO3) return 0xffff;
+           else return 0;
+            } 
+     case 4:{
+          DO4=value&0x0001;
+          if (DO4) return 0xffff;
+           else return 0;
+             } 
+     case 5:{
+            DO5=value&0x0001;
+            if (DO5) return 0xffff;
+           else return 0;
+             } 
+     case 6:{
+          DO6=value&0x0001;
+          if (DO6) return 0xffff;
+           else return 0;
+            } 
+     case 7:{
+           DO7=value&0x0001;
+           if (DO7) return 0xffff;
+           else return 0;
+            } 
+     case 8:{
+          DO8=value&0x0001;
+          if (DO8) return 0xffff;
+           else return 0;
+           } 
+     case 9:{
+           DO9=value&0x0001;
+           if (DO9) return 0xffff;
+           else return 0;
+            } 
+     } 
+  return 0; 
+ }
+void waitQuery()
+{   uint8_t address;
+    uint8_t function;
+    uint16_t startAddress;
+    uint16_t points;
+    int i;
+   if(slave.waitQuery(address,function,startAddress,points))
+     {
+        if ((address==myAddress)&&(function==0x03))  
+        { //read reigster
+          uint16_t p=startAddress;
+          for (i=0;i<points;i++)
+          {
+            data[i]= readDI(p++);
+            }
+          slave.sendResponse((uint8_t *)data,(uint8_t)(points*2));
+         } else
+         if ((address==myAddress)&&(function==0x06))
+         { //write register
+     
+            data[0]= writeDO(startAddress,points);     
+            slave.sendResponse((uint8_t *)data,2);
+             }
+      }
+    }
+int main() {
+    int i;
+    printf("modbus controller\n");
+    HF=1;
+    while (true) {
+        waitQuery();
+        led1 = !led1;
+      
+              
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#1bf6b20df9d3cd5f29f001ffc6f0d0fcbbb96118
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modbus/modbus.cpp	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,204 @@
+#include "modbus.h"
+#define   MODBUS_DEFAULT_BAUD_RATE   9600
+       const  char auchCRCHi[256]={
+    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
+};
+const  char auchCRCLo[256]={
+    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
+};
+Modbus::Modbus(PinName tx, PinName rx,PinName txEnable, int baud)
+: rs485(tx, rx,baud),
+dir(txEnable)
+{
+    rs485.format(8, Serial::None, 1);
+    }
+bool Modbus::sendQuery(uint8_t address,uint8_t function,uint16_t startAddress,uint16_t points)
+{  int index,i;
+     index=0;
+     _address=address;
+     _function=function;
+     _startAddress=startAddress;
+     _points=points;
+    sbuf[index++]=address;
+    sbuf[index++]=function;
+    sbuf[index++]=(startAddress>>8)&0xff;
+    sbuf[index++]=startAddress&0xff;
+    sbuf[index++]=(points>>8)&0xff;
+    sbuf[index++]=points&0xff;
+    unsigned short resultCRC =  calculateCRC16(sbuf,index); 
+     sbuf[index++]=(resultCRC>>8)&0xff;
+    sbuf[index++]=resultCRC&0xff;
+    dir=1;
+    wait_ms(2);
+    for (i=0;i<index;i++)
+      {
+      rs485.putc(sbuf[i]);
+  
+      }
+     wait_ms(2);
+    dir=0;
+    return true;
+    }
+int  Modbus::waitResponse(uint8_t *data)
+ {  unsigned short resultCRC ,recCRC;
+    
+    int state,index,len,cnt,i;
+    uint8_t ch;
+    bool flag;
+     flag=true;
+     state=0;
+     index=0;
+     while(flag)
+     {  ch=rs485.getc();
+        
+         switch(state)
+         {
+             case 0:{
+                 if (ch==_address)
+                   {state=1;
+                   rbuf[index++]=ch;}
+                 break;
+                 }
+            case 1:{
+               
+              if (ch==_function)
+                   {state=2;rbuf[index++]=ch;}
+                   else if(ch==(_function+0x80))
+                     state=10;
+                     else 
+                     return 0;
+                 break;
+                 }
+             case 2:{
+                    len=ch;cnt=ch;
+                    rbuf[index++]=ch;
+                    state=3;
+                    break;
+                    } 
+             case 3:{
+                    rbuf[index++]=ch;
+                    cnt--;
+                    if (cnt==0)
+                      { 
+                      state=4;
+                     
+                      }
+                    break;
+                    }
+              case 4:{
+                     recCRC=ch;
+                     state=5;
+                     break;
+                     } 
+              case 5:{
+                     recCRC=(recCRC<<8)|ch;
+                      resultCRC =  calculateCRC16(rbuf,index);  
+                   //  printf("CRC=%02x,%02x\n",recCRC,resultCRC);
+                     if (recCRC==resultCRC) {
+                         for (i=0;i<len;i++)
+                           data[i]=rbuf[3+i];
+                         return len;
+                         }
+                     else return 0;
+                     }
+               case 10:{
+                       len=0;
+                       flag=false;
+                       break;
+                       }                            
+             }
+         } 
+    
+        return len;
+     }
+bool  Modbus::waitQuery(uint8_t &address,uint8_t &function,uint16_t &startAddress,uint16_t &points)
+{ 
+unsigned short resultCRC ,recCRC;   
+    int i;
+    for (i=0;i<8;i++)
+     rbuf[i]=rs485.getc();
+     resultCRC =  calculateCRC16(rbuf,6);  
+     recCRC=(rbuf[6]<<8)|rbuf[7];
+     if ( resultCRC!=recCRC) return false;
+        address=rbuf[0];
+        _address=rbuf[0];
+        function=rbuf[1];
+        _function=rbuf[1]; 
+        _startAddress=(rbuf[2]<<8)|rbuf[3];
+        startAddress=_startAddress;
+        _points=(rbuf[4]<<8)|rbuf[5];
+        points=_points;
+        return true;
+    } 
+ bool Modbus::sendResponse(uint8_t *data,uint8_t length)
+ { 
+ unsigned short resultCRC;
+  int index,i;
+  index=0;
+     sbuf[index++]=_address;
+     sbuf[index++]=_function;
+     sbuf[index++]= length;
+    for (i=0;i<length;i++)
+     sbuf[index++]=data[i];
+     resultCRC =  calculateCRC16(rbuf,index);  
+     sbuf[index++]=(resultCRC>>8)&0xff;
+     sbuf[index++]=resultCRC &0xff;
+   for (i=0;i<index;i++)
+      rs485.putc(sbuf[i]) ;
+      return true;
+     }       
+unsigned int  Modbus::calculateCRC16( uint8_t *puchMsg,unsigned int  usDataLen)
+{
+    unsigned char uchCRCHi,uchCRCLo;
+    unsigned char uIndex=0 ;                             /* will index into CRC lookup table */
+    unsigned char tempp=0;
+    unsigned int CRCHL=0;
+    uchCRCHi=0xFF ;                             // high byte of CRC initialized 
+    uchCRCLo=0xFF ; 
+    tempp=0;                           // low byte of CRC initialized 
+    while(usDataLen--)                       // pass through message buffer 
+    {
+        uIndex=uchCRCHi^*puchMsg++ ; // calculate the CRC high byte         
+        tempp++;
+        uchCRCHi=uchCRCLo^auchCRCHi[uIndex] ;//01-auchCRCHi[254]:0x81;02-0x01;03-0x80;04-0xC0
+        uchCRCLo=auchCRCLo[uIndex] ;               
+    }
+    CRCHL=uchCRCHi;
+    CRCHL=CRCHL<<8;
+    CRCHL|=uchCRCLo;        
+    return CRCHL;//(uchCRCHi<<8|uchCRCLo) ;//uchCRCHi:0xa1;uchCRCLo:2B
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modbus/modbus.h	Tue Sep 17 01:59:40 2019 +0000
@@ -0,0 +1,35 @@
+/*
+  modbus  comuunication class
+   By modular-2 team 2018/8/3
+  modbus  mode=RTU master/salve
+  usage:
+  master mode:
+     sendQuery
+     waitResponse
+  salve mode:
+        waitQuery
+        sendResponse
+   */
+#ifndef MODBUS_H
+#define MODBUS_H
+#include "mbed.h"
+class Modbus
+{
+    public:
+      Modbus(PinName tx, PinName rx,PinName txEnable, int baud);
+      bool sendQuery(uint8_t address,uint8_t function,uint16_t startAddress,uint16_t points);
+      int  waitResponse(uint8_t *data);
+      bool  waitQuery(uint8_t &address,uint8_t &function,uint16_t &startAddress,uint16_t &points);
+      bool sendResponse(uint8_t *data,uint8_t length); 
+    private:
+        uint8_t sbuf[32];
+        uint8_t rbuf[32];
+        Serial rs485;
+        DigitalOut dir;
+        uint8_t _address;
+        uint8_t _function;
+        uint16_t _startAddress;
+        uint16_t _points;
+        unsigned int  calculateCRC16( uint8_t *puchMsg,unsigned int  usDataLen);
+    };
+#endif    
\ No newline at end of file