/* MBDemo02: Modbus/RTU controller + X board Compiler: BC++ 3.1 Compile mode: large Project: MBDemo01.c ..\Lib\7188XBL.Lib ..\Lib\MBR7Bnnn.Lib, with nnn being the version of Modbus/RTU library. Communication: Modbus Master <= Modbus/RTU => COM1 of 7188XB (You can change the Uplink port) <==> [Converter Kernel] <==> COM2 of 7188XB <==> Modbus/RTU slave device This program has 3 main functions 1. 1 to N port Modbus/RTU converter One COM port is used to receive Modbus/Request from Modbus/RTU master. Other COM ports are used to link to Modbus/RTU slave devices. When gets Modbus/RTU request, the kernel can decide to send request to which COM port and return the response to the Modbus/RTU master. 2. X board supports Modbus/RTU protocol Modbus/RTU master can send request to specific NetID(station number) to access the X board that mount on io expansion bus. 3. Supports user-defined registers The internal registers are open for X board and user-defined process. You can use the internal register to store some special information. Thus, the Modbus/RTU master can access the special internal registers. Hardware: 7188XB + X310 [10,May,2004] by Kevin Correct "missing function Init_X310();" [2006,Feb,17] by Kevin Use new I/O memory mapping method. */ #include #include "..\Lib\7188xb.h" #include "..\Lib\MBRTU.h" #include "..\Lib\Xboard\X310.h" int iScanUserProcess=0; int iScanXboardProcess=0; int ScanUserProcess(int iProcess); int ScanXboard(int iProcess); //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]; int main(void) { int iScanCOMPort=1; int iRet; int iPort2Device; int iUserProcess=0; InitLib(); //To use XB library version 2.0 (after 2004/Mar/08). // ***** 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. // Save COM1 setting to EEPROM ComData[1-1].baud=115200; ComData[1-1].databit=8; ComData[1-1].parity=0; ComData[1-1].stopbit=1; VcomSaveComData(1-1); // Save COM2 setting to EEPROM ComData[2-1].baud=115200; 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_StationCountPerCOMPort(10); Set_COMEnableMode(1,_ModbusRTU_Slave); //(COM1 be a Modbus/RTU slave port) Set_COMEnableMode(2,_ModbusRTU); //(COM2 be a Modbus/RTU converter port) // **** End Modbus configuration ***** iRet=InitModbus(iMemory_DI,iMemory_DO,iMemory_AI,iMemory_AO); if(iRet) return iRet; X310_Init(); for(;;) { // Begin of the 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 ? iScanCOMPort++; if(iScanCOMPort>iTotalCOMPort) iScanCOMPort=1; // End of the Modbus Kernel iUserProcess=ScanUserProcess(iUserProcess); // Scans user-define process, // stores results to memory(internal registers). iScanXboardProcess=ScanXboard(iScanXboardProcess); // Change this if you don't // plug a X board on expansion bus. } } /***************************/ /* [ScanUserProcess] */ /* for 7188E/7188XB */ /* version 1.0.1 */ /* date: 9,Aug,2002 */ /***************************/ int ScanUserProcess(int iProcess) { /* iProcess: executes which process? return: executes which process next time? This function scans the X board and stores the results to the memory. Thus, users can use Modbus protocol to read the memory to get the values of the Xboard. You should cut the hole scan process to many small processes. That can reduce execution time of this function and speed up the scan rate. The total internal registers spaces is limited by constant MAX_REGISTER_COUNT in MBTCP_7B.h. You can change the number to increase the total spaces. Xboard and user's process share the internal registers. To use the internal registers, you must notice don't overlap the registers. For X304 Memory mapping iMemory_DI[00]~[03] <====> X304 DI Ch0~Ch3 iMemory_DO[00]~[03] <====> X304 DO Ch0~Ch3 iMemory_AI[00]~[02] <====> X304 DI Ch0~Ch2 iMemory_AO[00]~[00] <====> X304 DO Ch0~Ch0 */ int iPort,iRet,i; int iNextProcess; switch(iProcess) { case 0: // Add user's process here. // For example, add CRC error number to AI register. iMemory_AI[0x10]=0x7188; //Address 0x10 is an example, //you can change it to suit your application. iNextProcess=1; break; case 1: // Add user's process here // For example, add Timeout error number to AI register. iMemory_DI[0x11]=1; //Address 0x11 is an example,=1 to set DI[0x11]=high. //you can change it to suit your application. iNextProcess=0; break; default: iNextProcess=0; break; } return iNextProcess; } /***************************/ /* [ScanXboard] */ /* for 7188E/7188XB */ /* version 1.0.1 */ /* date: 9,Aug,2002 */ /***************************/ int ScanXboard(int iProcess) { // iProcess: executes which process? // return: executes which process next time? // // This function scans the X board and stores the results // to the memory. Thus, users can use Modbus protocol to // read the memory to get the values of the Xboard. // You should cut the hole scan process to many small processes. // That can reduce execution time of this function and // speed up the scan rate. // // Xboard and user's process share the internal registers. // To use the internal registers, you must notice don't overlap // the registers. // X310 Memory mapping: // 00~02 : DI0 ~ DI2 // 00~03 : DO0 ~ DO2 // 00~01 : AI0 ~ AI1 // 00~01 : AO0 ~ AO1 int i,iNextProcess; float fValue; int iValue; switch(iProcess) { case 0: // Analog input ==> memory (Ch0) fValue=X310_AnalogIn(0); iMemory_AI[0]=(int)(fValue/20.0*32767.0); // 0~20 mA ==> 0~32767 iNextProcess=1; break; case 1: // Analog input ==> memory (Ch1) fValue=X310_AnalogIn(1); iMemory_AI[1]=(int)(fValue/10.0*32767.0); // 0~10 V ==> 0~32767 iNextProcess=2; break; case 2: // Memory ==> analog output (Ch0) fValue=(float)iMemory_AO[0]/32767.0*10.0; // 0~10 V ==> 0~32767 X310_AnalogOut(0,fValue); iNextProcess=3; break; case 3: // Memory ==> analog output (Ch1) fValue=(float)iMemory_AO[1]/32767.0*10.0; // 0~10 V ==> 0~32767 X310_AnalogOut(1,fValue); iNextProcess=4; break; case 4: // Digital input ==> memory iValue=X310_DigitalIn(); for(i=0;i<3;i++) // X310 has 3 DI channels { if((iValue&0x01)!=0) iMemory_DI[i]=1; else iMemory_DI[i]=0; iValue>>=1; } iNextProcess=5; break; case 5: //Memory ==> digital output iValue=0; for(i=0;i<3;i++) // X310 has 3 DO channels if(iMemory_DO[i]!=0) iValue+=(1<"); //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"); }