/* Compiler: BC++ 3.1, TC++ 3.0, TC++ 1.01 Compile mode: large Project: main.c ..\lib\upac5000.lib ..\lib\tcp_dm32.lib ..\lib\FW_09314.lib ..\lib\MBT7@174.lib Hardware: uPAC-5000 series Modbus demo for uPAC-5000 series The uPAC-5000 acts as a Modbus RTU and TCP master. [Feb 09, 2015] Beta Version */ #include #include #include #include #include "..\lib\upac5000.h" #include "..\lib\Tcpip32.h" #include "..\lib\MFW.h" #include "..\lib\MBTCP_XS.h" #define REG_SIZE 512 #define COMM_STATUS 32 void UPort502(int skt, int mode); /* MBTCP Server */ TCP_SERVER MBTCP={ 502, /* port */ -1, /* socket */ 0, /* state */ 0, /* connect */ UPort502 /* CallBackFun */ }; /* The I/O memory mapping */ unsigned char far iMemory_DI[REG_SIZE]; unsigned char far iMemory_DO[REG_SIZE]; int far iMemory_AI[REG_SIZE]; int far iMemory_AO[REG_SIZE]; #define COMPORT_NUMBER 2 int GetComportNumber(void) { return COMPORT_NUMBER; } void XS_UserInit(int argc, char *argv[]) { extern long MacTimeout; extern long MacRxTimeout; extern int bAcceptBroadcast; extern unsigned long ACKDELAY; extern long MAXTXTOUT; void UserLoop(void); int iRet; InitLib(); bAcceptBroadcast=0; ACKDELAY=200; /* ======= Begin of Modbus Kernel ======= */ ComData[1-1].baud=115200l; ComData[1-1].databit=8; ComData[1-1].parity=0; ComData[1-1].stopbit=1; VcomSaveComData(1-1); ComData[2-1].baud=9600l; ComData[2-1].databit=8; ComData[2-1].parity=0; ComData[2-1].stopbit=1; VcomSaveComData(2-1); Set_COMEnableMode(1, _Programming); Set_COMEnableMode(2, _Programming); Set_NetID(1); // set the Modbus ID to "01" iRet=InitModbus(iMemory_DI, iMemory_DO, iMemory_AI, iMemory_AO); if(iRet!=0) { /* Initial faild */ StopModbus(); } Modbus_Memory_Size(REG_SIZE, REG_SIZE, REG_SIZE, REG_SIZE); _fmemset(iMemory_DI, 0x0, REG_SIZE); _fmemset(iMemory_DO, 0x0, REG_SIZE); _fmemset(iMemory_AI, 0x0, sizeof(int) * REG_SIZE); _fmemset(iMemory_AO, 0x0, sizeof(int) * REG_SIZE); /* ======= End of Modbus Kernel======= */ XS_AddServer(&MBTCP); ModbusTCP_Init(0, "192.168.11.6", 502, 2000l, 3000l); XS_AddSystemLoopFun(UserLoop); MAXTXTOUT=6000UL; MacTimeout=30000L; MacRxTimeout=160000L; XS_AddSystemLoopFun(XS_SocketLoopFun); XS_StartSocket(); EnableWDT(); } void XS_UserEnd(void) { XS_StopSocket(); DisableWDT(); StopModbus(); RestoreCom(1); RestoreCom(2); } enum modbus_state { MODBUS_IDLE, MODBUS_WAITING, MODBUS_NORMAL_RESPONSE, MODBUS_EXCEPTION_RESPONSE, MODBUS_TIMEOUT, MODBUS_POLL_DELAY }; void UserLoop(void) { static unsigned long mytimeticks_RTU=0L; static unsigned long mytimeticks_TCP=0L; static int RTUprocess=MODBUS_POLL_DELAY; static int TCPprocess=MODBUS_POLL_DELAY; int iRet; RefreshWDT(); ModbusLoopFun(); if(RTUprocess==MODBUS_POLL_DELAY) { // RTU master polls the slave device at a regular interval if(GetTimeTicks()-mytimeticks_RTU>=200l) RTUprocess=MODBUS_IDLE; } if(RTUprocess==MODBUS_IDLE) { // RTU master sends a Modbus query to the slave device iRet=ModbusRTU_Master(2, 1, 2, 0, 4, 8, 300l, 0); // 2 -> defines the COM port to be used to connect between the slave device and the master // 1 -> defines the identification of the remote slave // 2 -> defines the request function code // 0 -> defines the Modbus address for the master // (them are used to hold data collected from the RTU slave devices) // 4 -> defines the starting address, i.e. the address of the first register specified // 8 -> define the quantity of registers to be read // 300 -> defines the period of time that the master will wait for a response from the RTU slave device RTUprocess=MODBUS_WAITING; } if(RTUprocess==MODBUS_WAITING) { iRet=ModbusRTU_Master(2, 1, 2, 0, 4, 8, 300l, 0); if(iRet<0) { RTUprocess=MODBUS_TIMEOUT; iMemory_AI[COMM_STATUS]=0xFF; } else if(iRet==0) { RTUprocess=MODBUS_NORMAL_RESPONSE; iMemory_AI[COMM_STATUS]=0; } else if(iRet<255) { RTUprocess=MODBUS_EXCEPTION_RESPONSE; iMemory_AI[COMM_STATUS]=iRet&0xFF; } } if(RTUprocess==MODBUS_NORMAL_RESPONSE || RTUprocess==MODBUS_EXCEPTION_RESPONSE || RTUprocess==MODBUS_TIMEOUT) { mytimeticks_RTU=GetTimeTicks(); RTUprocess=MODBUS_POLL_DELAY; } if(TCPprocess==MODBUS_POLL_DELAY) { // TCP master polls the slave device at a regular interval if(GetTimeTicks()-mytimeticks_TCP>=200l) TCPprocess=MODBUS_IDLE; } if(TCPprocess==MODBUS_IDLE) { // RTU master sends a Modbus query to the slave device iRet=ModbusTCP_Master2Slave(0, 1, 2, 16, 0, 16, 300l); // 0 -> index number // 1 -> defines the identification of the remote slave // 2 -> defines the request function code // 16 -> defines the Modbus address for the master // (them are used to hold data collected from the RTU slave devices) // 0 -> defines the starting address, i.e. the address of the first register specified // 16 -> define the quantity of registers to be read // 300 -> defines the period of time that the master will wait for a response from the RTU slave device TCPprocess=MODBUS_WAITING; } if(TCPprocess==MODBUS_WAITING) { iRet=ModbusTCP_Master2Slave(0, 1, 2, 16, 0, 16, 300l); if(iRet<0) { TCPprocess=MODBUS_TIMEOUT; iMemory_AI[COMM_STATUS+1]=0xFF; } else if(iRet==0) { TCPprocess=MODBUS_NORMAL_RESPONSE; iMemory_AI[COMM_STATUS+1]=0; } else if(iRet<255) { TCPprocess=MODBUS_EXCEPTION_RESPONSE; iMemory_AI[COMM_STATUS+1]=iRet&0xFF; } } if(TCPprocess==MODBUS_NORMAL_RESPONSE || TCPprocess==MODBUS_EXCEPTION_RESPONSE || TCPprocess==MODBUS_TIMEOUT) { mytimeticks_TCP=GetTimeTicks(); TCPprocess=MODBUS_POLL_DELAY; } } void UPort502(int skt, int mode) { TCPREADDATA pTCP_Data_Pointer; static char recBuf[512]; int iRet; if(!mode) { SOCKET_SET_TCP_KEEP_ALIVE_ON(skt); } else { if((iRet=XS_ReadSocket(skt, recBuf, sizeof(recBuf)))<=0) { SOCKET_SET_TCP_KEEP_ALIVE_OFF(skt); XS_CloseSocket(skt); return; } pTCP_Data_Pointer.Socket=skt; pTCP_Data_Pointer.ReadUartChar=recBuf; pTCP_Data_Pointer.Length=iRet; VcomCmdModbus(&pTCP_Data_Pointer); RefreshWDT(); } } void Modbus_Request_Event(char* CommandData, int* CommandLength) { CommandData=CommandData; CommandLength=CommandLength; } void Modbus_Response_Event(char* ResponseData, int* ResponseLength) { ResponseData=ResponseData; ResponseLength=ResponseLength; } void main(int argc, char *argv[]) { XS_main(argc,argv); /* call the XS library main function. */ }