#include #include #include #include "..\lib\module1.h" #include "..\lib\MBTCP.h" #include "..\lib\io_scan.h" int iModbusTCP_Process[8]={0,0,0,0,0,0,0,0}; int iScanCOMPort=1; // of Modbus Kernel //The I/O memory mapping unsigned char far iMemory_DI[1000]; unsigned char far iMemory_DO[1000]; int far iMemory_AI[800]; int far iMemory_AO[800]; void UserCount(void) { // user's timer trigger function // // In this function cannot use any function that will use the hardware signal "clock", // Such as: // 1. ClockHigh(),ClockLow(), ClockHighLow(), // 2. Any EEPROM functions. // 3. Any 5DigitLed functions. // 4. Any NVRAM function. // 5. Any RTC function.(GetTime(),SetTime(),GetDate(),SetDate()) } void UserInit(void) { /* In this function, user CAN: 1. initialize user's program. 2. set time interval for calling UserCount(). 3. set initial value of I/O or variables for UserLoopFun(). 4. set initial value of I/O or variables for another functions. 5. change the default TCP PORT 10000/9999/502 to others value. [after vcom3004.lib] Syntax: Port10000=newport_10000; for calling UserCmd (user.c) Port9999=newport_9999; for calling VcomCmd7000 (v7000.c) PortUser=newport_User; for calling VcomCmdUser (user.c) [after vcom3005.lib] Default port value: Port10000=10000; Port9999=9999; Port502=502; PortUser=0; If the port value is 0, Xserver will not listen that port. That means the port will be disable. Please refer to demo9 & demo11 for example code */ //InitLib(); // InitModbus() already includes InitLib();. //======= Begin Modbus Kernel ======= int iRet,i; for(i=0;i<1000;i++) iMemory_DO[i]=0; for(i=0;i<800;i++) iMemory_AO[i]=0; iRet=InitModbus(iMemory_DI,iMemory_DO,iMemory_AI,iMemory_AO); if(iRet!=0) { // Initial Modbus library error. } else { // Initial Modbus library ok. } Init_IO_Scan(iMemory_DI,iMemory_DO,iMemory_AI,iMemory_AO); //======= End Modbus Kernel ======= ModbusTCP_Init(0,"192.168.255.100",502,1500,8000); } void PortUserStart(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 10000, the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing } int iNet_Status=0,iOffset_Status=0; unsigned long lStart_TimeTick; //To record when the 7188E/8000E do //Ethernet communication. void UserLoopFun(void) { int i,iRet; //======= Begin of Modbus Kernel ======= UpdateIOModule(); 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==2) iScanCOMPort=3; if(iScanCOMPort>iTotalCOMPort) iScanCOMPort=1; if(iOffset_Status==0) iNet_Status=SMMI_Net_CheckIn(); if(iNet_Status==0) iOffset_Status=SMMI_Offset_CheckIn(); //======= End of Modbus Kernel ======= if((*TimeTicks-lStart_TimeTick)>100) //Do ethernet communication every 100 ms. { lStart_TimeTick=*TimeTicks; switch(iModbusTCP_Process[0]) { case 0: iRet=ModbusTCP_Master2Slave(0,1,2,iTotal_DINum,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 2 = Read DI //beginning index of register of I-8000 is iDINum //beginning index of register of Modub/TCP slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { printCom1("[192.168.255.100] Process[0]==> DI ok\n\r"); printCom1(" "); for(i=0;i<5;i++) { printCom1("DI[%02x]=%d ",iTotal_DINum+i,iMemory_DI[iTotal_DINum+i]); } printCom1("\n\r"); iModbusTCP_Process[0]=1; //Change to process 1. } else { printCom1("[192.168.255.100] Process[0]==> DI error code=%d\n\r",iRet); } break; case 1: iMemory_DO[iTotal_DONum+0]=1; iMemory_DO[iTotal_DONum+1]=0; iMemory_DO[iTotal_DONum+2]=1; iMemory_DO[iTotal_DONum+3]=0; iMemory_DO[iTotal_DONum+4]=1; iRet=ModbusTCP_Master2Slave(0,1,15,iTotal_DONum,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 15 = Write DO //beginning index of register of I-8000 is iDONum, //beginning index of register of Modub/RTU slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { printCom1("[192.168.255.100] Process[1]==> DO ok\n\r"); iModbusTCP_Process[0]=2; //Change to process 2. } else { printCom1("[192.168.255.100] Process[1]==> DO error code=%d\n\r",iRet); } break; case 2: iRet=ModbusTCP_Master2Slave(0,1,4,iTotal_AINum,0,2,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 4 = Read AI //beginning index of register of I-8000 is iAINum //beginning index of register of Modub/TCP slave device is 0 //I/O channel = 2 //Timeout=4000 ms if(iRet==0) { printCom1("[192.168.255.100] Process[2]==> AI ok\n\r"); printCom1(" "); for(i=0;i<2;i++) { printCom1("AI[%02X]=%04X ",iTotal_AINum+i,iMemory_AI[iTotal_AINum+i]); } printCom1("\n\r"); iModbusTCP_Process[0]=3; //Change to process 3. } else { printCom1("[192.168.255.100] Process[2]==> AI error code=%d\n\r",iRet); } break; case 3: iMemory_AO[iTotal_AONum+0]=0x0000; iMemory_AO[iTotal_AONum+1]=0x1111; iMemory_AO[iTotal_AONum+2]=0x2222; iMemory_AO[iTotal_AONum+3]=0x3333; iMemory_AO[iTotal_AONum+4]=0x4444; iRet=ModbusTCP_Master2Slave(0,1,16,iTotal_AONum,0,5,4000); //Modbus/TCP slave (0) (IP=192.168.255.100) //NetID=1 //Function Code = 16 = Write AO //beginning index of register of I-8000 is iAONum, //beginning index of register of Modub/RTU slave device is 0 //I/O channel = 5 //Timeout=4000 ms if(iRet==0) { printCom1("[192.168.255.100] Process[3]==> AO ok\n\r\n\r"); iModbusTCP_Process[0]=0; //Change to process 0. } else { printCom1("[192.168.255.100] Process[3]==> AO error code=%d\n\r",iRet); } break; default: iModbusTCP_Process[0]=0; //Change to process 0. break; } } } int UserCmd(unsigned char *Cmd,unsigned char *Response) { int iRet; //======= Begin Modbus Kernel ======= if(Cmd[0]=='!') { iRet=Configuration(Cmd,Response); if(iRet==0) return 1; /* return ok */ else return 0; /* return ERROR */ } //======= End Modbus ======= else return 1; /* return ok */ } int VcomUserBinaryCmd(TCPREADDATA *p) { /* VXCOMM.EXE 2.6.12(09/04/2001) or later will support this function. TCP PORT 10000, command 23 will call this function. user can get the following message: p->ReadUartChar : the buffer store the command data(include "23") p->Length : the command data length(include the two byte "23") p->Socket : the socket number that receive the command, that is when the user function want return message to the client, just use the socket to send data. use: VcomSendSocket(p->Socket,pdata,datalength); */ VcomSendSocket(p->Socket,"User-defined command(23)",24); // return 24 bytes. return 1; /* any value will be accept */ } int VcomCmdUser(TCPREADDATA *p) { /* VCOM3005 (Feb,22,2002) or later will call this function for PortUser. When packets received by TCP PORT PortUser(user defined) of 7188E/8000E, Xserver will call this function. user can get the following message: p->ReadUartChar : the buffer store the command data. Maximum length of p->ReadUartChar is 32767 bytes. p->Length : the command data length. p->Socket : the socket number that receive the command, that is when the user function wants return message to the client, just use the socket to send data. usage: VcomSendSocket(p->Socket,pdata,datalength); */ /* here just send back the command to the client. */ VcomSendSocket(p->Socket,p->ReadUartChar,p->Length); return 1; /* any value will be accept */ } void UserEnd(void) { } 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); } 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"); }