![](/media/cache/group/AET.jpg.50x50_q85.jpg)
Modbus Slave
Dependencies: mbed
Fork of HelloWorld by
Diff: modbus_slave.cpp
- 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); +*/ + } +}