Modbus Slave

Dependencies:   mbed

Fork of HelloWorld by Simon Ford

Revision:
2:d6e9fff32b77
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modbus_slave.cpp	Fri Nov 04 08:48:54 2016 +0000
@@ -0,0 +1,220 @@
+#include "mbed.h"
+
+//globalne varijable//
+Serial pc(USBTX, USBRX); 
+Serial b(p28, p27);
+DigitalIn In1(p5);
+DigitalIn In2(p6);
+DigitalIn In3(p7);
+DigitalIn In4(p8);
+DigitalIn In5(p9);
+DigitalIn In6(p10);
+DigitalIn In7(p11);
+DigitalIn In8(p12);
+DigitalIn In9(p13);
+DigitalIn In10(p14);
+AnalogIn AIn1(p16);
+DigitalOut cmd(p21);
+PwmOut cmd2(p22);
+DigitalOut txen(p26);
+DigitalOut led1 (LED1);
+DigitalOut led2 (LED2);
+DigitalOut led3 (LED3);
+unsigned short nAddress;
+unsigned short DI=0;
+unsigned short AI=0;
+char cInputBuffer[128];
+char cResponse[128]; 
+char cSlaveAddress, cFunction,cStartAddress_HI,cStartAddress_LO,cNoOfReg_HI,cNoOfReg_LO,cCRC_HI,cCRC_LO;
+unsigned short nAI;
+float fAI;
+float fPeriod=0;
+unsigned short MBMemoryMap[2]; 
+int nMyAddress=2;
+
+void crc( int start, int cnt)
+{
+// funkcija izračunava crc prema algoritmu opisanom u standardu
+   int      i,j;
+   unsigned int temp,temp2,flag;
+   temp=0xFFFF;
+   for (i=start; i<cnt; i++){
+      temp=temp ^ cResponse[i];
+
+      for (j=1; j<=8; j++){
+         flag=temp & 0x0001;
+         temp=temp >> 1;
+         if (flag) temp=temp ^ 0xA001;
+      }
+   }
+
+   /*
+   ** Zamjeni bajtove
+   */
+   temp2=temp >> 8;
+   temp=(temp << 8) | temp2;
+    cResponse[cnt]=temp/256;
+    cResponse[cnt+1]=temp % 256;
+}
+
+void FillData(){
+    // puni vrijednosti u MB telegramu (XX XX XX YY....YY XX XX)
+    int n=1;
+     if(nAddress==100){
+        for(int k =1; k<=cResponse[2];k=k+2){
+            cResponse[2+k]=MBMemoryMap[k-n]/256;
+            cResponse[3+k]=MBMemoryMap[k-n] % 256;
+            n++;   
+        }
+    }
+    if(nAddress==101){
+        cResponse[3]=MBMemoryMap[1]/256;
+        cResponse[4]=MBMemoryMap[1] % 256;
+        }
+}
+
+void ParseRequest(){
+    cSlaveAddress=cInputBuffer[0];
+    cFunction=cInputBuffer[1];
+    cStartAddress_HI=cInputBuffer[2];
+    cStartAddress_LO=cInputBuffer[3];
+    cNoOfReg_HI=cInputBuffer[4];
+    cNoOfReg_LO=cInputBuffer[5];
+    cCRC_HI=cInputBuffer[6];
+    cCRC_LO=cInputBuffer[7];
+}
+void PrepareReply() {
+     /*(odgovor u formatu :
+     1. byte : adresa slave jedinice
+     2. byte : modbus funkcija
+     3. i 4. byte : broj byte koje šaljemo
+     5. - X. byte : vrijednosti koje šlajemo
+     X+1. i X+2. byte : CRC (cyclic rednundyncy check) - provjera ispravnosti telegrama prema algoritmu opisanom u standardu */
+     bool bRespond = false;
+     bool bDiagnostic = false;
+     int nLength=0;
+     ParseRequest();
+     nAddress=cStartAddress_HI*256+cStartAddress_LO;
+     
+     if (cSlaveAddress==nMyAddress ){
+         cResponse[0]=nMyAddress;
+         bRespond=true;
+        }
+     // cResponse[0]=cSlaveAddress;
+      //bRespond=true;
+     switch(cFunction){
+         case 4:
+            pc.printf("Read Input register");
+            cResponse[1]=0x04;
+            break;
+        case 6:
+            pc.printf("Preset single register");
+            cResponse[1]=0x06;
+            cResponse[2]=cStartAddress_HI;
+            cResponse[3]=cStartAddress_LO;
+            cResponse[4]=cNoOfReg_HI;
+            cResponse[5]=cNoOfReg_LO;
+            cResponse[6]=cCRC_HI;
+            cResponse[7]=cCRC_LO;
+            led3=!led3;
+            if (cStartAddress_LO==102){
+                if (cNoOfReg_LO==1){
+                    pc.printf("jedan");
+                    cmd.write(1);
+                    }
+                if (cNoOfReg_LO==0){
+                    pc.printf("nula");
+                    cmd.write(0);
+                    } 
+             } 
+            if (cStartAddress_LO==0x67){
+                    fPeriod=(cNoOfReg_HI*256.0 + cNoOfReg_LO)/32768.0;
+                  //  pc.printf("PWM %X %X %.2f",cNoOfReg_HI,cNoOfReg_LO,fPeriod );
+                    cmd2.write(fPeriod);
+                   
+              } 
+            nLength=6;
+            bDiagnostic=true;
+            break;
+        case 8:
+            bRespond=true;
+            bDiagnostic=true;
+            cResponse[1]=0x08;          
+            cResponse[2]=cStartAddress_HI;
+            cResponse[3]=cStartAddress_LO;
+            cResponse[4]=cNoOfReg_HI;
+            cResponse[5]=cNoOfReg_LO;
+            cResponse[6]=cCRC_HI;
+            cResponse[7]=cCRC_LO;
+            nLength=6;
+
+            break;
+        }
+
+    if(!bDiagnostic){
+       
+            cResponse[2]=cNoOfReg_LO*2;
+            if((nAddress==100 and cResponse[2]<5) or (nAddress==101 and cResponse[2]==2)){
+                nLength=3+cResponse[2];
+                FillData();
+                }
+            else{
+                pc.printf("unsupported address"); 
+                cResponse[1]=cFunction|0x80;
+                }
+            crc(0,nLength);
+                   
+    }
+
+    if (bRespond){
+        if (b.writeable()){
+            pc.printf("\r\n tx_b "); 
+            for (int m =0; m<nLength+2; m++){
+                led2=!led2;
+                b.putc(cResponse[m]); 
+                pc.printf(" %.2X ", cResponse[m]); 
+               }
+            printf("\r\n"); 
+        }
+    }
+}
+void b_rx() { 
+
+    led1=!led1;
+    int i=0;
+    pc.printf("\r\n rx_b "); 
+    //čitamo što nam je došlo na serijski port i spremqamo u polje charactera cInputBuffer
+    while(b.readable()){
+       cInputBuffer[i]=b.getc(); 
+      // wait_us(500);
+       pc.printf(" %.2X ", cInputBuffer[i]); 
+      i++;
+    }
+    pc.printf("\r\n"); 
+    wait_ms(5);
+    txen=1; // postavljamo vanjski rs485 tranceiver u mod za slanje
+    wait_ms(5);
+    PrepareReply(); 
+    txen=0; // postavljamo vanjski rs485 tranceiver u mod za slušanje
+    
+}
+  
+int main() {
+
+    pc.printf("program pokrenut!!!!");
+    In1.mode(PullDown);
+    b.format(8,Serial::Even,1);
+    b.attach(&b_rx); //kada nas master pozove odi na b_rx
+    while (1){
+        //čitanje stanja digitalnih i analognih ulaza i spremanje u 16 bitne modbus registre
+        DI=In1.read() | In2.read()<<1 | In3.read()<<2 | In4.read()<<3 | In5.read()<<4 | In6.read()<<5 | In7.read()<<6 | In8.read()<<7 | In9.read()<<8 | In10.read()<<9; 
+        nAI = AIn1.read_u16();
+        MBMemoryMap[0]=DI;
+        MBMemoryMap[1]=nAI;
+ /*       fAI= AIn1.read();
+        wait(0.2);
+        pc.printf(" %.2f \r\n", fAI); 
+        pc.printf(" %d \r\n", nAI); 
+*/
+    }
+}