📄 modbusthread.cpp
字号:
/*****************************************************************************/
/* Subroutine: Demo8000 for ICPDAS WinCON 8000 */
/* Modbus/TCP Slave Thread */
/* Control Thread */
/* COPYRIGHT 2003 BY HUNG-TSAIR YEH */
/* Date : 2003 -10 - 01 designed V1.0 */
/* */
/* Desgined by Yeh Hung-Tsair */
/*****************************************************************************/
#include "com_sub.h"
/*...........................................................................*/
/* Modbus RTU Master Thread */
/*...........................................................................*/
UINT RTUMasterThreadProc( LPVOID lpParam )
{
// Get a THREAD_INFO pointer from the
// parameter that was passed in.
THREAD_INFO *lpThreadInfo =
(THREAD_INFO *) lpParam;
// AfxMessageBox(_T("RTU Master Thread Start...."), MB_OK);
int i, port, idx, rc, val;
int bytes, bitno, m, n;
int id, fun, req_addr, save_addr, words;
CString msg;
unsigned char coil[256], *cptr;
short reg[256];
short flag[MODBUS_MASTER_UNIT_MAX];
// just for testing program
memset((char *)&MB_PORT, 0, sizeof(MB_PORT));
memset((char *)MB_UNIT, 0, sizeof(MB_UNIT));
MB_PORT.portno= 2;
MB_PORT.baud= 19200;
MB_PORT.parity= iPARITY_NONE;
MB_PORT.data_bit= 8;
MB_PORT.stop_bit= 1;
MB_PORT.timeout= 1000;
MB_UNIT[0].active= 1;
MB_UNIT[0].fun= 1;
MB_UNIT[0].req_addr= 100;
MB_UNIT[0].save_addr= 0;
MB_UNIT[0].station= 1;
MB_UNIT[0].words= 10;
MB_UNIT[1].active= 1;
MB_UNIT[1].fun= 3;
MB_UNIT[1].req_addr= 200;
MB_UNIT[1].save_addr= 0;
MB_UNIT[1].station= 2;
MB_UNIT[1].words= 10;
MB_UNIT[3].active= 1;
MB_UNIT[3].fun= 5;
MB_UNIT[3].req_addr= 200;
MB_UNIT[3].save_addr= 1;
MB_UNIT[3].station= 2;
MB_UNIT[3].words= 1;
// search active unit no.
for(i=0; i<MODBUS_MASTER_UNIT_MAX; i++)
flag[i]= -1;
for(i=0, idx=0; i<MODBUS_MASTER_UNIT_MAX; i++)
{
if(MB_UNIT[i].active==1) flag[idx++]= i;
}
port= MB_PORT.portno;
rc= MBRTUInit(port, MB_PORT.baud, MB_PORT.parity, MB_PORT.data_bit,
MB_PORT.stop_bit, MB_PORT.timeout);
if(rc!= MB_RTC_OK)
{
msg.Format(_T("Open Modbus RTU Master COM Port error=%d"), rc);
AfxMessageBox(msg, MB_ICONEXCLAMATION);
return(0);
}
idx= 0;
while(1)
{
for(i=idx; i<MODBUS_MASTER_UNIT_MAX; i++)
{
if(flag[i] != -1)
{
idx=flag[i]; break;
}
}
if(idx >= MODBUS_MASTER_UNIT_MAX) // it is over last unit
{
// Sleep(10);
idx= 0; // return to first unit
continue;
}
fun= MB_UNIT[idx].fun;
id= MB_UNIT[idx].station;
req_addr= MB_UNIT[idx].req_addr;
words= MB_UNIT[idx].words;
save_addr= MB_UNIT[idx].save_addr;
switch(fun)
{
case 1: // read output coil
rc= MBRTU_R_Coils(port, id, req_addr, words, coil, fun);
if(rc==MB_RTC_OK)
{
cptr= Coil.DO_SOFT;
for(i=0; i<words; i++)
{
m= i/8;
n= i%8;
rc= Coil_Bit_Read(&coil[m], n);
bytes= (save_addr+i)/8;
bitno= (save_addr+i)%8;
if(rc==0)
Coil_Bit_Write((cptr+bytes), bitno, 0);
else
Coil_Bit_Write((cptr+bytes), bitno, 1);
}
}
break;
case 2: // read input coil
rc= MBRTU_R_Coils(port, id, req_addr, words, coil, fun);
if(rc==MB_RTC_OK)
{
cptr= Coil.DI_SOFT;
for(i=0; i<words; i++)
{
m= i/8;
n= i%8;
rc= Coil_Bit_Read(&coil[m], n);
bytes= (save_addr+i)/8;
bitno= (save_addr+i)%8;
if(rc==0)
Coil_Bit_Write((cptr+bytes), bitno, 0);
else
Coil_Bit_Write((cptr+bytes), bitno, 1);
}
}
break;
case 3: // read holding register
rc= MBRTU_R_Registers(port, id, req_addr, words, reg, fun);
if(rc==MB_RTC_OK)
{
for(i=0; i<words; i++)
{
Reg.AO_SOFT[save_addr+i]= reg[i];
}
}
break;
case 4: // read input register
rc= MBRTU_R_Registers(port, id, req_addr, words, reg, fun);
if(rc==MB_RTC_OK)
{
for(i=0; i<words; i++)
{
Reg.AI_SOFT[save_addr+i]= reg[i];
}
}
break;
case 5: // write output coil one TAG
m= save_addr/8;
n= save_addr%8;
rc= Coil_Bit_Read(&Coil.DO_SOFT[m], n);
val= rc;
rc= MBRTU_W_Coil(port, id, req_addr, val);
break;
case 6: // write holding register one TAG
reg[0]= (short)Reg.AO_SOFT[save_addr]; // just send integer value
rc= MBRTU_W_Register(port, id, req_addr, reg[0]);
break;
case 15: // write output coil multi-TAG
memset(coil, 0, sizeof(coil));
cptr= Coil.DO_SOFT;
for(i=0; i<words; i++)
{
m= (save_addr+i)/8;
n= (save_addr+i)%8;
rc= Coil_Bit_Read((cptr+m), n);
bytes= i/8;
bitno= i%8;
if(rc==0)
Coil_Bit_Write(&coil[bytes], bitno, 0);
else
Coil_Bit_Write(&coil[bytes], bitno, 1);
}
rc= MBRTU_W_Multi_Coils(port, id, req_addr, words, coil);
break;
case 16: // write holding register multi-TAG
memset(reg, 0, sizeof(reg));
for(i=0; i<words; i++)
{
reg[i]= (short)Reg.AO_SOFT[save_addr+i];
}
rc= MBRTU_W_Multi_Registers(port, id, req_addr, words, reg);
break;
}
idx++; // change to next unit index
if(idx>= MODBUS_MASTER_UNIT_MAX) idx=0;
if(flag[idx]== -1) idx=0;
Sleep(10); // wait 10 msec and then polling next unit
} // while(1)
MBRTUClose(port);
return 0;
}
/*...........................................................................*/
/* Modbus Slave TCP Thread */
/*...........................................................................*/
UINT TCPSlaveThreadProc( LPVOID lpParam )
{
// Get a THREAD_INFO pointer from the
// parameter that was passed in.
THREAD_INFO *lpThreadInfo =
(THREAD_INFO *) lpParam;
// AfxMessageBox(_T("TCP Thread Start...."), MB_OK);
int i, rc, rc1, fun, id, addr, count, max, addr_1;
int bytes, bitno, m, n;
unsigned char coil[256], *cptr, *cptr_1;
short reg[256], *iptr;
unsigned short val;
CString s;
float fvalue;
rc= SLTCPInit(503); // Modbus default IP port no. is 502, but I use 503 in this demo program
while(1)
{
rc=SLTCP_Wait_Query(&id, &addr, &count, &fun);
if(rc==MB_RTC_OK)
{
while(1) // it has more then one Query which is send from multi-Matser client Request
{
rc1= SLTCP_Has_Query(&id, &addr, &count, &fun);
if(rc1 != MB_TCP_HAS_DATA) break;
// s.Format(_T("%d %d %d %d\n"), id, addr, count, fun);
// TRACE(s);
switch(fun)
{
case 1: // Read Output Coil
// set I/O data, send back to Modbus Master
max= DO_INIT_PTR + DD_MAX_BIT*3;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(coil, 0, sizeof(coil));
cptr= Coil.DO_BARE;
for(i=0; i<count; i++)
{
bytes= (addr+i)/8;
bitno= (addr+i)%8;
rc= Coil_Bit_Read((cptr+bytes), bitno);
m= i/8;
n= i%8;
Coil_Bit_Write(&coil[m], n, rc);
}
SLTCP_Set_Coils(coil);
break;
case 2: // Read Input Status
// set I/O data, send back to Modbus Master
max= DI_INIT_PTR + DD_MAX_BIT*3;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(coil, 0, sizeof(coil));
cptr= Coil.DI_BARE;
for(i=0; i<count; i++)
{
bytes= (addr+i)/8;
bitno= (addr+i)%8;
rc= Coil_Bit_Read((cptr+bytes), bitno);
m= i/8;
n= i%8;
Coil_Bit_Write(&coil[m], n, rc);
}
SLTCP_Set_Coils(coil);
break;
case 3: // Read Holding Register
// set I/O data, send back to Modbus Master
max= CN_CURR_PTR + CT_MAX_CASE;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((addr%2)!=0 && addr<TM_PSET_PTR) // it must even addr.
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((count%2)!=0 && addr<TM_PSET_PTR) // it must two words per TAG
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(reg, 0, sizeof(reg));
cptr= (unsigned char *)Reg.AO_BARE;
cptr_1= (unsigned char *)&val;
for(i=0; i<count; i++)
{
m= addr*2+i*2;
memcpy(cptr_1, (cptr+m), 2);
reg[i]= val;
}
SLTCP_Set_Registers((unsigned short *)reg);
break;
case 4: // Read Input Register
// set I/O data, send back to Modbus Master
max= AI_INIT_PTR*2 + ED_MAX*5*2;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((addr%2) !=0) // it must even addr.
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((count%2) != 0) // it must two words per TAG
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(reg, 0, sizeof(reg));
cptr= (unsigned char *)Reg.AI_BARE;
cptr_1= (unsigned char *)&val;
for(i=0; i<count; i++)
{
m= addr*2+i*2;
memcpy(cptr_1, (cptr+m), 2);
reg[i]= val;
}
SLTCP_Set_Registers((unsigned short *)reg);
break;
case 5: // Write Output Coil one bit
max= DO_INIT_PTR + DD_MAX_BIT*3;
if(addr>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(coil, 0, sizeof(coil));
SLTCP_Get_Coils(coil);
bytes= addr/8;
bitno= addr%8;
cptr= Coil.DO_BARE;
if(coil[0]==0)
Coil_Bit_Write((cptr+bytes), bitno, 0);
else
Coil_Bit_Write((cptr+bytes), bitno, 1);
if( addr>=DO_BARE_PTR && addr<DO_SOFT_PTR) // it is H/W DO
{
if(coil[0] == 1) fvalue= 1;
else fvalue= 0;
set_AODO_output(DO_TYPE, addr, fvalue);
}
break;
case 6: // Write Holding Register one words
max= CN_CURR_PTR + CT_MAX_CASE;
if(addr>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if(addr<TM_PSET_PTR) // it must Timer or Counter addr.
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(reg, 0, sizeof(reg));
SLTCP_Get_Registers((unsigned short *)reg);
iptr= Reg.TM_PSET;
m= addr - TM_PSET_PTR;
*(iptr+m)= reg[0];
s.Format(_T("Fun-6 Register=%d\n"), reg[0]);
TRACE(s);
if((addr%2)==0) // even address
{
if(addr>=(AO_BARE_PTR*2) && addr<(AO_ENG_PTR*2))
{
addr_1= addr/2;
fvalue= reg[0];
set_AODO_output(AO_TYPE, addr_1, fvalue);
}
else if(addr>=(AO_ENG_PTR*2) && addr<(AO_SOFT_PTR*2))
{
addr_1= (addr - AO_ENG_PTR*2)/2;
fvalue= reg[0];
set_AODO_output(AO_TYPE_ENG, addr_1, fvalue);
}
}
break;
case 15: // Write Output Coil multi-bit
max= DO_INIT_PTR + DD_MAX_BIT*3;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(coil, 0, sizeof(coil));
SLTCP_Get_Coils(coil);
cptr= Coil.DO_BARE;
for(i=0; i<count; i++)
{
m= i/8;
n= i%8;
rc= Coil_Bit_Read(&coil[m], n);
bytes= (addr+i)/8;
bitno= (addr+i)%8;
if(rc==0)
Coil_Bit_Write((cptr+bytes), bitno, 0);
else
Coil_Bit_Write((cptr+bytes), bitno, 1);
if( (addr+i)>=DO_BARE_PTR && (addr+i)<DO_SOFT_PTR) // it is H/W DO
{
if(rc == 1) fvalue= 1;
else fvalue= 0;
set_AODO_output(DO_TYPE, addr+i, fvalue);
}
}
s.Format(_T("Fun-15 Coil=%d\n"), coil[0]);
TRACE(s);
break;
case 16: // Write Holding Register multi-words
max= CN_CURR_PTR + CT_MAX_CASE;
if(addr>max || (addr+count)>max)
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((addr%2)!=0 && addr<TM_PSET_PTR) // it must even addr.
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
if((count%2)!=0 && addr<TM_PSET_PTR) // it must two words per TAG
{
SLTCP_Send_Exception(0x02); // illegal addr.
break;
}
memset(reg, 0, sizeof(reg));
SLTCP_Get_Registers((unsigned short *)reg);
if(addr<TM_PSET_PTR) // it is float
{
iptr= (short *)Reg.AO_BARE;
for(i=0; i<count; i++)
{
m= (addr+i);
*(iptr+m)= reg[i];
}
for(i=0; i<count; i=i+2)
{
addr_1= addr+i;
if(addr_1>=(AO_BARE_PTR*2) && addr_1<(AO_ENG_PTR*2))
{
m= addr_1/2;
fvalue= Reg.AO_BARE[m];
set_AODO_output(AO_TYPE, m, fvalue);
}
else if(addr>=(AO_ENG_PTR*2) && addr<(AO_SOFT_PTR*2))
{
m= (addr_1 - AO_ENG_PTR*2)/2;
fvalue= Reg.AO_ENG[m];
set_AODO_output(AO_TYPE_ENG, m, fvalue);
// s.Format(_T("Modbus Set Eng: %f addr: %d %d"), fvalue, addr, m);
// AfxMessageBox(s, MB_OK);
}
}
}
else // it is timer or counter
{
iptr= Reg.TM_PSET;
for(i=0; i<count; i++)
{
m= (addr+i) - TM_PSET_PTR;
*(iptr+m)= reg[i];
}
}
s.Format(_T("Fun-16 Register=%d\n"), reg[0]);
TRACE(s);
break;
default:
SLTCP_Send_Exception(0x01); // illegal fun.
break;
}
} // while(has_data)
}
} // while(1)
SLTCPClose();
return 0;
}
/*...........................................................................*/
/* Control Thread */
/*...........................................................................*/
// include special control file
#include "sample_1.cpp" // sample-1 special control case
//#include "sample_2.cpp" // sample-2 special control case
//#include "sample_3.cpp" // sample-3 special control case
UINT ControlThreadProc( LPVOID lpParam )
{
// Get a THREAD_INFO pointer from the
// parameter that was passed in.
THREAD_INFO *lpThreadInfo =
(THREAD_INFO *) lpParam;
// initial Parallel I/O Module
if( initial_local()!=0) return(1); // I/O Module is not consistent
while(1)
{
ICP_local_main(); // read/write I/O Module signal
control_calc();
special_control();
Sleep(10);
}
return(0);
}
//------------------ end of Add ----------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -