📄 ppia.h
字号:
//PPI通讯协议如下:
//主发写命令,从返回E5(准备就绪命令),主收到后发确认命令(10 SLAVER,MASTER,5C,ADD,16),从发(68 12 12 68 。。。)完毕
//主发读命令,从返回E5(准备就绪命令),主收到后发确认命令(10 SLAVER,MASTER,5C,ADD,16),从发(68 xx xx 68 。。。)完毕
//****************************************************************************
//**Purpose: 当PPI本机为从时,接受到了主的命令,命令有两种,申请和确认
//** uc_rec_len是长度,不是下标。先效验 返回为发送串长(下标),返回0xff为不发送
UCHAR ppi_reqframe_anlys_slaver(UCHAR uc_ch,UCHAR *puc_rec_buf,UCHAR uc_rec_len,UCHAR *puc_send_buf,uchar me_address)
{
static uchar st_uc_ppi_var_type[MCU_UART_NUM] = {2,2};//传输的数据类型
static uchar st_uc_ppi_var_num[MCU_UART_NUM];//传输的数据个数
static uint st_ui_ppi_me_var_add[MCU_UART_NUM];
static uchar st_uc_ppi_connect_type[MCU_UART_NUM]={0,0};
UCHAR ucp_send_count,uc_count;
UINT u16;
UCHAR uc_mid1,uc_mid2,uc_mid3;
if((*puc_rec_buf) == 0x10)//确认命令
{
if((uc_rec_len != 6) || (*(puc_rec_buf+5)!=0x16))//长度不对,或者结束符号不对
{
return(0xfe);
}
if(*(puc_rec_buf + 1) != me_address)
{
return(0xfe);
}
if(uc_ppi_addtest(puc_rec_buf+1, uc_rec_len-3) != *(puc_rec_buf + uc_rec_len - 2))//效验
{
return(0xfe);
}
//10 03 02 5c 61 16
//if(st_uc_ppi_connect_type[uc_ch] == 0)//还没连接
//{
// return(0xfe);
//}
//以上是2008.6.24修改,因为如果上电或其他因素
//首发DC命令,再发49命令,以上导致对49命令无响应(因为无连接),而PLC死循环
ucp_send_count = 0;
if(*(puc_rec_buf + 3) != 0x49) //最多出现的是5C,而7C也见过
{
uc_count = st_uc_ppi_var_num[uc_ch]; //此后的计算结果,uc_count将成为字节数
uc_mid1 = st_uc_ppi_var_type[uc_ch];
if(uc_mid1 == 4)//如果是字
{uc_count *=2;}
else if(uc_mid1 == 6)//如果是双字
{uc_count *=4;}
else if(uc_mid1 == 1)//位
{return(0xfe);}
if((uc_count+26) >= comm_array_max_xb)
{return(0xfe);}
if(st_uc_ppi_connect_type[uc_ch] == 1)//连接的性质,主PLC读本机
{
uc_mid1 = 0x15 + uc_count;
uc_mid2 = 4 + uc_count;
uc_mid3 = 0x04;
}
else
{
uc_mid1 = 0x12;
uc_mid2 = 0x01;
uc_mid3 = 0x05;
}
*(puc_send_buf + ucp_send_count++) = 0x68;
*(puc_send_buf + ucp_send_count++) = uc_mid1;
*(puc_send_buf + ucp_send_count++) = uc_mid1;
*(puc_send_buf + ucp_send_count++) = 0x68;
*(puc_send_buf + ucp_send_count++) = *(puc_rec_buf + 2);//对方地址
*(puc_send_buf + ucp_send_count++) = *(puc_rec_buf + 1);//本机地址
*(puc_send_buf + ucp_send_count++) = 0x08;
*(puc_send_buf + ucp_send_count++) = 0x32;
*(puc_send_buf + ucp_send_count++) = 0x03;
*(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]; //主机来是多少,返回就是多少
*(puc_send_buf + ucp_send_count++) = 0x00;
*(puc_send_buf + ucp_send_count++) = 0x02; //不管是字还是字节,固定为2
*(puc_send_buf + ucp_send_count++) = 0x00;
*(puc_send_buf + ucp_send_count++) = uc_mid2;
*(puc_send_buf + ucp_send_count++) = 0x00;
*(puc_send_buf + ucp_send_count++) = 0x00;
*(puc_send_buf + ucp_send_count++) = uc_mid3;
*(puc_send_buf + ucp_send_count++) = 0x01;
*(puc_send_buf + ucp_send_count++) = 0xff;
if(st_uc_ppi_connect_type[uc_ch] == 1)//连接的性质,主PLC读本机
{
*(puc_send_buf + ucp_send_count++) = 0x04;
u16 = uc_count;
u16 *= 8;
*(puc_send_buf + ucp_send_count++) = HI_UINT(u16);
*(puc_send_buf + ucp_send_count++) = LO_UINT(u16);
for(uc_mid1 = 0;uc_mid1<uc_count;uc_mid1++)
{
*(puc_send_buf + ucp_send_count++) = uc_PPI_ret_Word(st_ui_ppi_me_var_add[uc_ch] + uc_mid1);
}
}
//从4开始,就是从地址开始,-4是个数
uc_mid1 = uc_ppi_addtest(puc_send_buf + 4,ucp_send_count-4);
*(puc_send_buf + ucp_send_count++) = uc_mid1;
*(puc_send_buf + ucp_send_count) = 0x16;
return(ucp_send_count); //返回的是下标
}
else //if((*puc_rec_buf + 3) == 0x49) )似乎主机在问本机是不是也是主机,回答不是
{
*(puc_send_buf + ucp_send_count++) = 0x10;
*(puc_send_buf + ucp_send_count++) = *(puc_rec_buf + 2);//对方地址
*(puc_send_buf + ucp_send_count++) = *(puc_rec_buf + 1);//本机地址
*(puc_send_buf + ucp_send_count++) = 0; //告诉主机
*(puc_send_buf + ucp_send_count++) = uc_ppi_addtest(puc_send_buf+1,3);
*(puc_send_buf + ucp_send_count) = 0x16;
return(5); //返回的是下标
}//if((*puc_rec_buf + 3) == 0x5c))
}//确认命令至此完成了
/////////////////////////////////////////////////////////////////////////////////////////////////////
//热烈祝贺确认类型命令完成了,下面是申请命令,地址和效验都要重新做
/////////////////////////////////////////////////////////////////////////////////////////////////////
else if(((*puc_rec_buf) == 0xdc) || ((*puc_rec_buf) == 0x68)) //可能是呼叫申请,也可能是其他PPI的数据
{
if((uc_rec_len < 33) || (*(puc_rec_buf + uc_rec_len - 1) != 0x16))//长度不对,或者结束符号不对
{
return(0xfe);
}
if((*puc_rec_buf) == 0xdc)
{
puc_rec_buf += 3;
uc_rec_len -= 3;
if((*puc_rec_buf) != 0x68){return(0xfe);}
}
if(*(puc_rec_buf + 4) != me_address){return(0xfe);} //地址效验
puc_rec_buf += 3; //从第二个68开始
uc_rec_len -= 3; //长度跟着调整
if(uc_ppi_addtest(puc_rec_buf+1,uc_rec_len-3) != *(puc_rec_buf + uc_rec_len - 2)) //和效验
{
//st_uc_ppi_connect_type[uc_ch] = 0;//地址对了,但是效验错了,取消连接?
//2008.6.24 不取消连接
return(0xfe);
}
//以下效验也对了
st_uc_ppi_var_type[uc_ch] = *(puc_rec_buf + 19);
st_uc_ppi_var_num[uc_ch] = *(puc_rec_buf + 21);
uc_ppi_comm_count[uc_ch] = *(puc_rec_buf + 8);
st_ui_ppi_me_var_add[uc_ch] = MAKE_UINT(*(puc_rec_buf + 26),*(puc_rec_buf + 27)) / 8;
if(*(puc_rec_buf - 1) == 0x1b)//st_uc_ppi_connect_type[uc_ch]=1是读,2是写
{
st_uc_ppi_connect_type[uc_ch] = 1; //主PLC要从本机读数据
*(puc_send_buf) =0xe5;
return(0); //返回的是下标,却只发一个字节
}
//PLC写入功能不用包含在只读的采集模块仪表中
else if(*(puc_rec_buf - 1) >= 0x20)//是写入命令,主PLC写入信息
{
st_uc_ppi_connect_type[uc_ch] = 2;
uc_count = st_uc_ppi_var_num[uc_ch]; //此后的计算结果,uc_count将成为字节数
uc_mid1 = st_uc_ppi_var_type[uc_ch];
if(uc_mid1 == 4)//如果是字
{uc_count *=2;}
else if(uc_mid1 == 6)//如果是双字
{uc_count *=4;}
else if(uc_mid1 == 1)//位
{return(0xfe);}
for(uc_mid1 = 0;uc_mid1<uc_count;uc_mid1++)
{
PPI_write_singleReg(st_ui_ppi_me_var_add[uc_ch] + uc_mid1, *(puc_rec_buf + 32 + uc_mid1));
//开始地址+字节指针 从32(35从第一个68开始)
}
*(puc_send_buf) =0xe5;//发E5
return(0); //返回的是下标,却只发一个字节
}
else //不是读,也不是写,不认识
{
//st_uc_ppi_connect_type[uc_ch] = 0;
//2008.6.24不取消连接
return(0xfe);
}
}//else if(((*puc_rec_buf) == 0xdc) || ((*puc_rec_buf) == 0x68))
return(0xfe);
}
//*****************************************************************************************
//*****************************************************************************************
UCHAR ppi_send_command_10(UCHAR *puc_send_buf,UCHAR me_address,UCHAR uc_plc_address,UCHAR uc_command)
{
UCHAR uc_mid,uc_loop;
UCHAR ucp_send_count = 0;
*(puc_send_buf + ucp_send_count++) = 0x10;
*(puc_send_buf + ucp_send_count++) = uc_plc_address;
*(puc_send_buf + ucp_send_count++) = me_address;
*(puc_send_buf + ucp_send_count++) = uc_command;
uc_mid = 0;
for(uc_loop =1; uc_loop < ucp_send_count;uc_loop++)
{
uc_mid += *(puc_send_buf + uc_loop);
}
*(puc_send_buf + ucp_send_count++) = uc_mid;
*(puc_send_buf + ucp_send_count) = 0x16;
return(ucp_send_count);
}
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//*****************************************************************************************
//业务流程有必要写一下
//主发写命令,从返回E5(准备就绪命令),主收到后发确认命令(10 SLAVER,MASTER,5C,ADD,16),从发(68 12 12 68 。。。)完毕
//主发读命令,从返回E5(准备就绪命令),主收到后发确认命令(10 SLAVER,MASTER,5C,ADD,16),从发(68 xx xx 68 。。。)完毕
//接受部分和MODBUS基本相同:
//在接受中断中,重置了3.5字节的接受完毕,并且将发送的计数器g_uc_ppi_main_send_count=-1,就是最大值,这样,就会先进入接收程序,而不会由定时器导致发送
//而在主程序中,要对g_uc_ppi_main_send_count每ms--,到0后发出is_ppi_master_need_send消息
//而主接收函数ppi_reqframe_anlys_master 和主发送函数ppi_master_send都可能会组成发送串,并且会重写g_uc_ppi_main_send_count(函数内叫next_send_ms_count)
//当g_uc_ppi_main_send_count(next_send_ms_count)到时间后叫“超时”,将导致发送,用STEP同步
//
//#define PPI_F_MASTER_REQUIRED 0
//#define PPI_F_MASTER_ENTERED 1
//#define PPI_F_MASTER_SEND_DC 2
//#define PPI_F_MASTER_ANSW_DC 3 //这是接收函数发的DC ME ME 指令,发完后定时,再有主程序引发主发函数工作
//#define PPI_F_MASTER_E5AGAIN 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -