/* FW_MT01.c: Be a Modbus/TCP master to connect to one Modbus/TCP slave device. Compiler: BC++ 3.1 Compile mode: large Project: FW_MT01.c 7188EL.Lib tcpip32.Lib MBT7@NNN.Lib, with NNN being the lib file's version. Using function ModbusTCP_Init, ModbusTCP_Master2Slave, ModbusTCP_Close 7188E can controll Modbus/TCP slave devices through the ethernet. Please refer to MBTCP_7E.h for more information. Hardware: 7188EX + Modbus/TCP slave device [Feb 03, 2010] by Liam [Aug,02,2011] by Nicholas */ #include #include #include "..\lib\7188e.h" #include "..\lib\Tcpip32.h" #include "..\lib\MFW.h" #include "..\lib\MBTCP_XS.h" int VcomCmdModbus(TCPREADDATA *p); // declared in the MBT7@NNN.Lib void Port502(int SocketNumber, int Connected); int iScanCOMPort=1; // for Modbus Kernel int iSendflag,iModbusTCP_Process; //The I/O memory mapping unsigned char far iMemory_DI[100]; unsigned char far iMemory_DO[100]; int far iMemory_AI[100]; int far iMemory_AO[100]; TCP_SERVER MBServer={ 502, -1, 0, 0, Port502 }; /************************************************************************/ char *GetModuleName(void) /* User's program must support this function for UDP search */ { return "I-7188EX" ; } /************************************************************************/ char *GetAliasName(void) /* User's program must support this function for UDP search */ { return "test1" ; } /************************************************************************/ void XS_UserInit(int argc, char *argv[]) { extern int bAcceptBroadcast; extern unsigned long ACKDELAY; /* variable in tcp.c */ extern long MAXTXTOUT; void UserLoop(void); int iRet; InitLib(); bAcceptBroadcast=1; ACKDELAY=200; XS_AddSystemLoopFun(UserLoop); // add a Modbus server to your program XS_AddServer(&MBServer); // ======= Begin changing COM port setting ======= // Call following codes once when you change the COM port setting // After saving the setting to the EEPROM, you should remove the codes // COM1 setting ComData[1-1].baud=115200L; ComData[1-1].databit=8; ComData[1-1].parity=0; ComData[1-1].stopbit=1; VcomSaveComData(1-1); // COM2 setting ComData[2-1].baud=9600; ComData[2-1].databit=8; ComData[2-1].parity=0; ComData[2-1].stopbit=1; VcomSaveComData(2-1); // ======= End changing COM port setting ======= // ***** Begin Modbus configuration ***** // Before the Modbus Utility can support the 7188XB -MRTU, // You can add following functions to configure the Modbus settings. Set_NetID(1); Set_COMEnableMode(1, _Programming); //(COM1 be a Modbus/RTU slave port) Set_COMEnableMode(2, _Programming); //(COM2 be a Modbus/ASCII slave port) // **** End Modbus configuration ***** //======= Begin of Modbus Kernel ======= iRet=InitModbus(iMemory_DI, iMemory_DO, iMemory_AI, iMemory_AO); if(iRet==0) { // Initial Modbus configuration success. } else { // Initial Modbus configuration failure. } Modbus_Memory_Size(100, 100, 100, 100); //======= End of Modbus Kernel======= ModbusTCP_Init(0, "192.168.255.100", 502, 1500, 8000); // uses the TCP/IP functions XS_AddSystemLoopFun(XS_SocketLoopFun); XS_StartSocket(); MAXTXTOUT=6000UL; EnableWDT(); iModbusTCP_Process=0; } void XS_UserEnd(void) { XS_StopSocket(); DisableWDT(); RestoreCom(1); RestoreCom(2); } unsigned long lStart_TimeTick; void UserLoop(void) { int i, iRet; RefreshWDT(); //======= Begin of Modbus Kernel ======= if(mtModbusPort[iScanCOMPort].EnableMode==_ModbusRTU_Slave) CheckModbusRTURequest(iScanCOMPort); // Is any request from Modbus/RTU Master ? if(mtModbusPort[iScanCOMPort].EnableMode==_ModbusASCII_Slave) CheckModbusASCIIRequest(iScanCOMPort); // Is any request from Modbus/ASCII Master ? if(mtModbusPort[iScanCOMPort].EnableMode==_ModbusRTU_Gateway) { SendModbusRequest(iScanCOMPort); // Passes request to modbus slave device. CheckResponseTimeout(iScanCOMPort); // If response timeout, sets iModbusAction // to IDLE status. CheckModbusResponse(iScanCOMPort); // Is any response from modbus slave device? SendModbusResponse(iScanCOMPort); // Passes response to Modbus/RTU Master. } iScanCOMPort++; if(iScanCOMPort>iTotalCOMPort) iScanCOMPort=1; //======= End of Modbus Kernel ======= if((GetTimeTicks()-lStart_TimeTick)>500 || (iSendflag==1)) //Do ethernet communication every 500 ms. { lStart_TimeTick=GetTimeTicks(); switch(iModbusTCP_Process) { case 0: iRet=ModbusTCP_Master2Slave(0,1,2,0,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 2 = Read DI //beginning index of register of 7186E is 0 //beginning index of register of Modub/TCP slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { iSendflag=0; printCom1("Modbus TCP read DI success "); for(i=0;i<5;i++) { printCom1("DI[%02X]=%X ",i,iMemory_DI[i]); } printCom1("\n\r"); iModbusTCP_Process=1; //Change to process 1. } else if(iRet<0) { iSendflag=0; printCom1("Modbus TCP DI transaction error code = %d\n\r",iRet); iModbusTCP_Process=1; //Change to process 1. } else { iSendflag=1; printCom1("Wait for DI transaction response \n\r"); } break; case 1: iMemory_DO[0]=1; iMemory_DO[1]=0; iMemory_DO[2]=1; iMemory_DO[3]=0; iMemory_DO[4]=1; iRet=ModbusTCP_Master2Slave(0,1,15,0,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 15 = Write DO //beginning index of register of 7186E is 0, //beginning index of register of Modub/RTU slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { iSendflag=0; printCom1("Modbus TCP write DO success \n\r"); iModbusTCP_Process=2; //Change to process 2. } else if(iRet<0) { iSendflag=0; printCom1("Modbus TCP DO transaction error code = %d\n\r",iRet); iModbusTCP_Process=2; //Change to process 2. } else { iSendflag=1; printCom1("Wait for DO transaction response \n\r"); } break; case 2: iRet=ModbusTCP_Master2Slave(0,1,4,0,0,2,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 4 = Read AI //beginning index of register of 7186E is 0 //beginning index of register of Modub/TCP slave device is 0 //I/O channel = 2 //Timeout=4000 ms if(iRet==0) { iSendflag=0; printCom1("Modbus TCP read AI success "); for(i=0;i<2;i++) { printCom1("AI[%02X]=%04X ",i,iMemory_AI[i]); } printCom1("\n\r"); iModbusTCP_Process=3; //Change to process 3. } else if(iRet<0) { iSendflag=0; printCom1("Modbus TCP AI transaction error code = %d\n\r",iRet); iModbusTCP_Process=3; //Change to process 3. } else { iSendflag=1; printCom1("Wait for AI transaction response \n\r"); } break; case 3: iMemory_AO[0]=0x0000; iMemory_AO[1]=0x1111; iMemory_AO[2]=0x2222; iMemory_AO[3]=0x3333; iMemory_AO[4]=0x4444; iRet=ModbusTCP_Master2Slave(0,1,16,0,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 16 = Write AO //beginning index of register of 7186E is 0, //beginning index of register of Modub/RTU slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { iSendflag=0; printCom1("Modbus TCP write AO success \n\r"); iModbusTCP_Process=0; //Change to process 0. } else if(iRet<0) { iSendflag=0; printCom1("Modbus TCP AO transaction error code = %d\n\r",iRet); iModbusTCP_Process=0; //Change to process 0. } else { iSendflag=1; printCom1("Wait for AO transaction response \n\r"); } break; default: iModbusTCP_Process=0; //Change to process 0. break; } } if(IsCom1()) QuitMain=1; } char far sInputBuffer_P502[512]; void Port502(int SocketNumber, int Connected) { int iByte; TCPREADDATA pTCP_Data_Pointer; if(Connected==0) //First time connected from remote clients. { ; } else { iByte=readsocket(SocketNumber, sInputBuffer_P502, sizeof(sInputBuffer_P502)-1); if(iByte>0) { pTCP_Data_Pointer.Socket=SocketNumber; pTCP_Data_Pointer.ReadUartChar=sInputBuffer_P502; pTCP_Data_Pointer.Length=iByte; VcomCmdModbus(&pTCP_Data_Pointer); } else XS_CloseSocket(SocketNumber); } } void Modbus_Request_Event(char* CommandData, int* CommandLength) { /* Modbus_Request_Event is supported since version 1.6.8 [2007,03,13]. char* CommandData: For Modbus/TCP, it includes 6 leading bytes. (needful) For Modbus/RTU, it includes 6 leading bytes. (needless) int* CommandLength: For Modbus/TCP, it includes 6 leading bytes. For Modbus/RTU, it includes 6 leading bytes. */ /* Example code */ //int i; //printCom1("FC:%2d StartAddress:%3d IOCount:%4d\n\r",iModbusRequest_Fun, iModbusRequest_Addr,iModbusRequest_IOCount); //printCom1("Modbus Request\n\r In==>"); //for(i=0;i<*CommandLength;i++) // printCom1("[%02X] ",CommandData[i]&0xFF); // do nothing CommandData=CommandData; CommandLength=CommandLength; } void Modbus_Response_Event(char* ResponseData, int* ResponseLength) { /* char* ResponseData: For Modbus/TCP, it includes 6 leading bytes. For Modbus/RTU, it doesn't include 6 leading bytes int* CommandLength: For Modbus/TCP, it includes 6 leading bytes. For Modbus/RTU, it doesn't include 6 leading bytes */ //If you want to change the content of the ResponseData, //you have to do 2 steps for Modbus/TCP or Modbus/RTU. //Step1: Change content (Note:you must know the modbus protocol well) //ResponseData[6]=0x19; //ResponseData[7]=0x75; //ResponseData[8]=0x04; //ResponseData[9]=0x01; //Step2: Update data length //*ResponseLength=10; //int i; //printCom1("\n\r Out==>"); //for(i=0;i<*ResponseLength;i++) // printCom1("[%02X] ",ResponseData[i]&0xFF); //printCom1("\n\r"); // do nothing ResponseData=ResponseData; ResponseLength=ResponseLength; } void main(int argc,char *argv[]) { XS_main(argc, argv); // call the XS library main function }