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

📄 ppia.h

📁 西门子PPI协议源码
💻 H
📖 第 1 页 / 共 3 页
字号:
//#define PPI_F_MASTER_SUCCESS  5

//上电的时候, step == PPI_F_MASTER_REQUIRED, 进入发送程序,发的实际上是DC me me ,step 变成 PPI_F_MASTER_SEND_DC,10ms后发
//10ms后发送请求,将OP表++,查发送指令后发送申请,step变成PPI_F_MASTER_REQUIRED从机若无反应(超时),则实际上回到上一步
//若接受到信息,则进入ppi_reqframe_anlys_master,
//应该是E5,发确认命令,step变成PPI_F_MASTER_ENTERED,若从机没反应(超时),发DC ME ME
//若不是E5,而是直接收到数据,则转入“收到数据:”
//若不是E5,什么也不发,step变成PPI_F_MASTER_ENTERED,从机定没反应(超时),发DC ME ME
//若收到数据:
//如果还是E5,step变成PPI_F_MASTER_E5AGAIN,则重新发10命令,若干次后重新发送DC ME ME,STEP变PPI_F_MASTER_ANSW_DC,并转换5C,7C
//若是数据,分析数据,step变成PPI_F_MASTER_SUCCESS,1MS后发DC ME ME

//*****************************************************************************************
//*****************************************************************************************
//**Purpose:当PPI为主时,分析接收帧,并根据接收帧作相应处理.
//**Entry: puc_rec_buf:---指向接收缓冲. uc_rec_len:---接收缓冲的长.uc_op_table_pos:指向发送命令表的下标。
//**当PPI为主时,接收帧有如下可能:
//** 1。返回E5,表示准备好命令,本机应该发送确认命令 10 ,PLC,ME,5C
//**    但返回2个E5,则忽略,发下个命令
//** 2。返回的是回复指令,如从PLC读数返回68,2x,2x,68,ME,PLC..... 向PLC写数返回68 12 12 68....
//** 3。异常:有两种,一个是E5反复发,一个是发 10,ME,PLC,02
//*****************************************************************************************

UCHAR ppi_reqframe_anlys_master(UCHAR uc_ch,UCHAR *puc_rec_buf,UCHAR *puc_send_buf,UCHAR uc_rec_len,UCHAR *uc_op_table_pos,
								uchar me_address,uchar uc_plc_address,uchar *next_send_ms_count)
{
	UCHAR uc_mid,uc_loop;
	UCHAR ucp_send_count = 0;
	UINT  u16;
	
	if(uc_ppi_master_step[uc_ch] == PPI_F_MASTER_REQUIRED)//刚才自己发的是请求命令,应该收到的是E5
	{
		//先写确认命令,只有PPI为MASTER时才调用,4.12后,收到连续两个E5,不再调用确认命令了
		if((*puc_rec_buf == 0xe5))// && (uc_rec_len == 1))
		{
			uc_ppi_is_connect[uc_ch] = 1;
			
			if(uc_ppi_acq_cmd_5c[uc_ch])//现在是确认指令,请求是5C,则确认是7C
			{
				uc_mid = 0x7c;
			}
			else
			{
				uc_mid = 0x5c;
			}
			
			uc_ppi_master_step[uc_ch] = PPI_F_MASTER_ENTERED;
			*next_send_ms_count = 250;  //本命令只发了5个字节,然后该收了,只要收到,则该变量会变255ms,如果没有反应了,则50ms后主发DC
			return(ppi_send_command_10(puc_send_buf,me_address,uc_plc_address,uc_mid));  
		}
		else if(*puc_rec_buf == 0x68)//发现是68,转到下面处理了
		{
			uc_ppi_master_step[uc_ch] = PPI_F_MASTER_ENTERED;
		}
		else//可能是10 me plc 02 不管他,直接发DC
		{
			//*puc_send_buf++ = 0xDC;
			//*puc_send_buf++ = me_address;
			//*puc_send_buf = me_address;
			
			uc_ppi_master_step[uc_ch] = PPI_F_MASTER_REQUIRED;
			*next_send_ms_count = 100;  //本命令只发了5个字节,应该什么也收不到,50ms后主发DC
			
			return(0xfe);
		}
	} 
	//不用else if 的原因是上面的程序要不就退出了或者跳转了,执行到这里,可能是上面发现了不发E5直接回复的现象
	if((uc_ppi_master_step[uc_ch] == PPI_F_MASTER_ENTERED) || (uc_ppi_master_step[uc_ch] == PPI_F_MASTER_E5AGAIN)) //已经发过了确认命令了,现在接受来的应该是68,12,12(写),68,2x,2x,(读)
	{
		if((*puc_rec_buf == 0xe5) && (uc_rec_len == 1))//还来E5,发10,PLC,ME,7C/5C
		{
			
			if(++uc_ppi_EnterCount[uc_ch] >10)
			{
				uc_ppi_EnterCount[uc_ch] = 0;  //计数器清除
				*puc_send_buf++ = 0xDC;
				*puc_send_buf++ = me_address;
				*puc_send_buf = me_address;
				
				uc_ppi_master_step[uc_ch] = PPI_F_MASTER_ANSW_DC;
				*next_send_ms_count = 250;  //本命令只发了3个字节,应该什么也收不到,50ms后主发确认,并把step = PPI_F_MASTER_E5AGAIN
				
				return(2);
			}
			else
			{
				if(uc_ppi_acq_cmd_5c[uc_ch])//现在是确认指令,请求是5C,则此次就发5C,反转呼叫申请和确认的5C和7C
				{
					uc_mid = 0x5c;
					uc_ppi_acq_cmd_5c[uc_ch] = 0;
				}
				else
				{
					uc_mid = 0x7c;
					uc_ppi_acq_cmd_5c[uc_ch] = 1;
				}
				
				
				uc_ppi_master_step[uc_ch] = PPI_F_MASTER_E5AGAIN;
				*next_send_ms_count = 250;   
				//应该收到68,或者E5
				//50MS什么数也没收到的话,转主发了,并且发的实际上是DC
				return(ppi_send_command_10(puc_send_buf,me_address,uc_plc_address,uc_mid));   
			}
		}
		//又来E5处理完毕了
		
		if(*puc_rec_buf == 0x68)
		{
			if(stMod_Master_OP[*uc_op_table_pos].uc_cmd == PPI_READ_BYTE_REG)//我读PLC的数,要填写到我的表中
			{
				if(*(puc_rec_buf + 4) != me_address){return(0xfe);}   //地址效验
				puc_rec_buf += 3;  //从第二个68开始
				uc_rec_len -= 3;   //长度跟着调整
				
				if(*puc_rec_buf != 0x68){return(0xfe);}  //是不是0x68
				if(uc_rec_len < 24){return(0xfe);}       //至少要有的长度
				if(*(puc_rec_buf-1) != *(puc_rec_buf-2)){return(0xfe);}//有错
				if(*(puc_rec_buf-1) <= 15){return(0xfe);}
				
				if(uc_ppi_addtest(puc_rec_buf+1,uc_rec_len-3) != *(puc_rec_buf + uc_rec_len - 2))  //和效验
				{
					return(0xfe);
				}
				
				//以下效验也对了
				//总的接受字节数量,注意以后是不是可能超过255
				uc_mid = *(puc_rec_buf+13) - 4;  
				u16 = stMod_Master_OP[*uc_op_table_pos].ui_mem_begin_addr;
				for(uc_loop = 0; uc_loop < uc_mid; uc_loop++)
				{
					PPI_write_singleReg(u16 + uc_loop, *(puc_rec_buf+ 22 + uc_loop));
				}	   
			}
			//else我写PLC的数,返回应该是68,12,12,不管是不是,都发DC了
		}
		//全当成功了
		*next_send_ms_count = 1;//50; 
		uc_ppi_master_step[uc_ch] = PPI_F_MASTER_SUCCESS;
		return(0xfe);
		//上两个分支的解释在上面
		//也就是说当PPI_F_MASTER_ENTERED时,收到E5则发7C的确认命令,收到68,并且大约对就都不发了
		//但若PPI_F_MASTER_E5AGAIN后再来E5,也不是68,则发DC,ME,ME
	}
	
	return(0xfe);//为了严谨		
}
///////////////////////////////////////////////////////////////////////////////
//以下是自己发出了写PLC内部命令组成发送数据串,返回串长度
///////////////////////////////////////////////////////////////////////////////
uchar ppi_master_send(uchar uc_ch,uchar *uc_op_table_pos,uchar uc_plc_address,uchar *puc_send_buf,uchar me_address,uchar *next_send_ms_count)

{
	uchar uc_mid,uc_loop,uc_count;
	UCHAR ucp_send_count = 0;
	unsigned long l16;
	uint u16;
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//进入本函数,有如下可能:	  		
	//									1:没响应 则由g_uc_commmain_send_count超时引起
	//											  分两种 (1)没PLC <- 我发了REQ命令
	//											  		 (2)我发了DC me me命令
	//										都在本函数中预设g_uc_commmain_send_count	 
	//									2: 接收程序发送了DC me me命令,导致无响应,也由g_uc_commmain_send_count导致
	//									   在本函数中判断uc_ppi_master_step,看是谁导致的无响应
	//
	//能进入本函数,则必须发信息,因为进入本函数有可能是接收函数发了DC指令导致的没有响应,
	//由接收函数g_uc_commmain_send_count设置的引起的超时,主程序中发送is_ppi_master_need_send
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	uc_mid = uc_ppi_master_step[uc_ch];
	
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//  主接收程序发DC ME ME 指令引发的没反应
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	if(uc_mid == PPI_F_MASTER_ANSW_DC)
	{
		if(uc_ppi_acq_cmd_5c[uc_ch])  //上次请求命令是5C,则这次改为7C
		{
			uc_ppi_acq_cmd_5c[uc_ch] = 0;
			uc_mid = 0x5c; //请求命令改为7C了,则确认命令发5C
		}
		else
		{
			uc_ppi_acq_cmd_5c[uc_ch] = 1;
			uc_mid =0x7c;
		}
		
		uc_ppi_master_step[uc_ch]   = PPI_F_MASTER_E5AGAIN;
		*next_send_ms_count = 250;      //无响应超时,PLC可能发E5,或者苏醒发68,XX,XX,68....都将在接受程序中处理了next_send_ms_count
		//所以再进入本函数的话,那是没反应了,所以应该发DC
		return( ppi_send_command_10(puc_send_buf,me_address,uc_plc_address,uc_mid)  );
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//  发申请指令
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//先把OP表的指针++
	if(uc_mid == PPI_F_MASTER_SEND_DC)
	{
		if(++(*uc_op_table_pos) >= OP_TABLE_LENTH){*uc_op_table_pos = 0;}
		
		uc_mid = stMod_Master_OP[*uc_op_table_pos].uc_cmd;
		
		if(uc_mid == PPI_READ_BYTE_REG)
		{uc_count = 0x1b;}
		else
		{uc_count = 0x1f + stMod_Master_OP[*uc_op_table_pos].uc_lenth;}
		
		*(puc_send_buf + ucp_send_count++) = 0x68;
		*(puc_send_buf + ucp_send_count++) = uc_count;
		*(puc_send_buf + ucp_send_count++) = uc_count;
		*(puc_send_buf + ucp_send_count++) = 0x68;
		*(puc_send_buf + ucp_send_count++) = uc_plc_address;  //address
		*(puc_send_buf + ucp_send_count++) = me_address;
		
		if(uc_ppi_is_connect[uc_ch] == 0)
		{ 
			*(puc_send_buf + ucp_send_count++) = 0x6c;
			uc_ppi_comm_count[uc_ch] = 2;
			uc_ppi_is_connect[uc_ch] = 1;
		}
		else
		{
			uc_ppi_is_connect[uc_ch]++;
			
			if(uc_ppi_is_connect[uc_ch] > 5)
			{
			 if(uc_ppi_acq_cmd_5c[uc_ch]){uc_ppi_acq_cmd_5c[uc_ch]=0;}else{uc_ppi_acq_cmd_5c[uc_ch]=-1;}
			 uc_ppi_is_connect[uc_ch] = 1;
			}
			
			if(uc_ppi_acq_cmd_5c[uc_ch])//如果申请是5C,则确认是7C,否则反之
			{
				*(puc_send_buf + ucp_send_count++) = 0x5c;
			}
			else
			{
				*(puc_send_buf + ucp_send_count++) = 0x7c;
			}
		}
		*(puc_send_buf + ucp_send_count++) = 0x32;
		*(puc_send_buf + ucp_send_count++) = 0x01;
		*(puc_send_buf + ucp_send_count++) = 0x00;
		*(puc_send_buf + ucp_send_count++) = 0x00;
		
		*(puc_send_buf + ucp_send_count++) = uc_ppi_comm_count[uc_ch];
		*(puc_send_buf + ucp_send_count++) = uc_ppi_comm_count[uc_ch];
		uc_ppi_comm_count[uc_ch] += 1;
		*(puc_send_buf + ucp_send_count++) = 0x00;
		*(puc_send_buf + ucp_send_count++) = 0x0e;		
		*(puc_send_buf + ucp_send_count++) = 0x00;
		
		l16 =stMod_Master_OP[*uc_op_table_pos].ui_plc_begin_addr;
		l16 *=8;
		if(uc_mid == PPI_READ_BYTE_REG)
		{
			*(puc_send_buf + ucp_send_count++) = 0x00;
			*(puc_send_buf + ucp_send_count++) = 0x04;
		}
		else
		{
			*(puc_send_buf + ucp_send_count++) =stMod_Master_OP[*uc_op_table_pos].uc_lenth + 4;
			*(puc_send_buf + ucp_send_count++) = 0x05;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -