⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbusthread.cpp

📁 《WinCE.NET嵌入式工业用控制器及自动控制系统设计》的源代码
💻 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 + -