|
|
@@ -109,465 +109,459 @@ struct di_db g_di_db[MAX_DPI_NUMBER];
|
|
|
*/
|
|
|
void plc_db_soe(EVENT_STRUCT *ev);
|
|
|
|
|
|
-
|
|
|
/*------------------------------ 外部函数 -------------------------------------
|
|
|
外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
|
|
|
*/
|
|
|
int plc_yx2index(u8 sw, u8 type)
|
|
|
{
|
|
|
- if(sw>SWITCH_NUM_MAX)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if(type == 0)
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- type--;
|
|
|
-
|
|
|
- if(sw == 0)
|
|
|
- {
|
|
|
- return type;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- sw--;
|
|
|
- return PUB_DI_NUM_ALL+(SW_DI_NUM_ALL*sw) + type;
|
|
|
- }
|
|
|
-
|
|
|
- return -2;
|
|
|
+ if (sw > SWITCH_NUM_MAX)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (type == 0)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ type--;
|
|
|
+
|
|
|
+ if (sw == 0)
|
|
|
+ {
|
|
|
+ return type;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sw--;
|
|
|
+ return PUB_DI_NUM_ALL + (SW_DI_NUM_ALL * sw) + type;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -2;
|
|
|
}
|
|
|
|
|
|
SOE_DEF *plc_yx2soe(u8 sw, u8 type)
|
|
|
{
|
|
|
- if(sw>SWITCH_NUM_MAX)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- if(type == 0)
|
|
|
- {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- type--;
|
|
|
-
|
|
|
- if(sw == 0)
|
|
|
- {
|
|
|
- if(type >= PUB_DI_NUM && type < PUB_DI_NUM_ALL)
|
|
|
- {
|
|
|
- return (SOE_DEF *)&tAllSOE[type - PUB_DI_NUM + EV_SW_NUM];
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if(type >= SW_DI_NUM && type < SW_DI_NUM_ALL)
|
|
|
- {
|
|
|
- return (SOE_DEF *)&tAllSOE[type - SW_DI_NUM];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
+ if (sw > SWITCH_NUM_MAX)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ if (type == 0)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ type--;
|
|
|
+
|
|
|
+ if (sw == 0)
|
|
|
+ {
|
|
|
+ if (type >= PUB_DI_NUM && type < PUB_DI_NUM_ALL)
|
|
|
+ {
|
|
|
+ return (SOE_DEF *)&tAllSOE[type - PUB_DI_NUM + EV_SW_NUM];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (type >= SW_DI_NUM && type < SW_DI_NUM_ALL)
|
|
|
+ {
|
|
|
+ return (SOE_DEF *)&tAllSOE[type - SW_DI_NUM];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
s32 plc_get_input(u16 ld)
|
|
|
{
|
|
|
- u16 type,sw,no;
|
|
|
- s32 r;
|
|
|
-
|
|
|
- type = (ld & LP_TYPE);
|
|
|
- sw = (ld & LP_SW)>>8 ;
|
|
|
- no = (ld & LP_INDEX);
|
|
|
-
|
|
|
- r = 0;
|
|
|
- switch(type)
|
|
|
- {
|
|
|
- case LP_TYPE_YX:
|
|
|
- r = GetRmtYxVal(sw,no);
|
|
|
- r = (r == SW_DI_TYPE_ON);
|
|
|
- break;
|
|
|
-
|
|
|
- case LP_TYPE_YC:
|
|
|
- r = GetRmtMeaVal(sw,no,NULL);
|
|
|
- break;
|
|
|
-
|
|
|
- case LP_TYPE_PLC:
|
|
|
- r = g_plc[no].result;
|
|
|
- break;
|
|
|
-
|
|
|
- case LP_TYPE_PLC_CST:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return r;
|
|
|
+ u16 type, sw, no;
|
|
|
+ s32 r;
|
|
|
+
|
|
|
+ type = (ld & LP_TYPE);
|
|
|
+ sw = (ld & LP_SW) >> 8;
|
|
|
+ no = (ld & LP_INDEX);
|
|
|
+
|
|
|
+ r = 0;
|
|
|
+ switch (type)
|
|
|
+ {
|
|
|
+ case LP_TYPE_YX:
|
|
|
+ r = GetRmtYxVal(sw, no);
|
|
|
+ r = (r == SW_DI_TYPE_ON);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case LP_TYPE_YC:
|
|
|
+ r = GetRmtMeaVal(sw, no, NULL);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case LP_TYPE_PLC:
|
|
|
+ r = g_plc[no].result;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case LP_TYPE_PLC_CST:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
int plc_init_iec_table(void)
|
|
|
{
|
|
|
- u16 i,j,ep;
|
|
|
- u16 v;
|
|
|
- int index;
|
|
|
- SOE_DEF * soe;
|
|
|
-
|
|
|
- // 处理单点,如果一个逻辑点对应多个通讯点,将除第一个通讯点外的其它通讯点放入PLC逻辑中
|
|
|
- for(i=0; i<g_table_head->di_num; i++)
|
|
|
- {
|
|
|
- index = plc_yx2index(g_di_table[i].owner,g_di_table[i].indexno);
|
|
|
- if(index < 0)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 将第一个通讯点滤除
|
|
|
- if(g_lp[index].cp == g_di_table[i].cp)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 没有通讯点,不需要
|
|
|
- if(g_di_table[i].cp == 0)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 除第一个通讯点外的其它通讯点,放入PLC逻辑中
|
|
|
- // 检查空间
|
|
|
- if(g_plc_num >= PLC_EXP_NUM)
|
|
|
- {
|
|
|
- rt_printf("g_plc_num单点越限(g_plc_num=%d,i=%d).\r\n",g_plc_num,i);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- // 通讯点
|
|
|
- g_plc[g_plc_num].cp = g_di_table[i].cp;
|
|
|
-
|
|
|
- // 标志,目前只有故障记录标志
|
|
|
- soe = plc_yx2soe(g_di_table[i].owner,g_di_table[i].indexno);
|
|
|
- if(soe)
|
|
|
- {
|
|
|
- if(soe->soe_def&0x80)
|
|
|
- {
|
|
|
- g_plc[g_plc_num].flag = (PLC_FLAG_FAULT|(g_di_table[i].owner<<16));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 插入操作数
|
|
|
- ep = 0;
|
|
|
- v = LP_TYPE_YX;
|
|
|
- v |= (g_di_table[i].owner<<8) | g_di_table[i].indexno;
|
|
|
- g_plc[g_plc_num].exp[ep++] = v;
|
|
|
-
|
|
|
- //单点取反
|
|
|
- if(g_di_table[i].is_inverse)
|
|
|
- {
|
|
|
- g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
- }
|
|
|
-
|
|
|
- // 结束符
|
|
|
- g_plc[g_plc_num].exp[ep++] = 0;
|
|
|
-
|
|
|
- g_plc_num++;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // 处理合并点
|
|
|
- g_plc_merge_index = g_plc_num;
|
|
|
- for(i=0;i<g_table_head->dimerge_num;i++)
|
|
|
- {
|
|
|
- if(g_plc_num >= PLC_EXP_NUM)
|
|
|
- {
|
|
|
- rt_printf("g_plc_num合并点越限(g_plc_num=%d,i=%d).\r\n",g_plc_num,i);
|
|
|
- return -2;
|
|
|
- }
|
|
|
-
|
|
|
- g_plc[g_plc_num].cp = g_di_merge_table[i].cp;
|
|
|
- ep = 0;
|
|
|
- for(j=0;j<MIX_YX_NUMBER;j++)
|
|
|
- {
|
|
|
- u8 no=g_di_merge_table[i].no[j]&0xff;
|
|
|
- u8 owner=(g_di_merge_table[i].no[j]>>8)&0xff;
|
|
|
-
|
|
|
- // 组合点号为空代表结束,退出。
|
|
|
- if(g_di_merge_table[i].no[j] == 0)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // 标志,目前只有故障记录标志
|
|
|
- soe = plc_yx2soe(owner,no);
|
|
|
- if(soe)
|
|
|
- {
|
|
|
- if(soe->soe_def&0x80)
|
|
|
- {
|
|
|
- g_plc[g_plc_num].flag = (PLC_FLAG_FAULT|(owner<<16));
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 插入操作数
|
|
|
- v = LP_TYPE_YX | (owner<<8) | no;
|
|
|
- g_plc[g_plc_num].exp[ep++] = v;
|
|
|
-
|
|
|
- //单点取反
|
|
|
- if(g_di_merge_table[i].is_inv[j])
|
|
|
- {
|
|
|
- g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
- }
|
|
|
-
|
|
|
- // 插入或运算符
|
|
|
- if(j)
|
|
|
- {
|
|
|
- g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_OR;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 合并点取反
|
|
|
- if(g_di_merge_table[i].is_inv_all)
|
|
|
- {
|
|
|
- g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
- }
|
|
|
-
|
|
|
- // 结束符
|
|
|
- g_plc[g_plc_num].exp[ep++] = 0;
|
|
|
-
|
|
|
- // 检查长度是否越界
|
|
|
- if(ep > PLC_EXP_LEN)
|
|
|
- {
|
|
|
- rt_printf("plc_iec_table: 表达式太长(i=%d,j=%d,ep=%d).\r\n",i,j,ep);
|
|
|
- return -3;
|
|
|
- }
|
|
|
-
|
|
|
- g_plc_num++;
|
|
|
- }
|
|
|
-
|
|
|
- //g_plc[2].do_owner = 0;
|
|
|
- //g_plc[2].do_index = 1;
|
|
|
-
|
|
|
- return 0;
|
|
|
+ u16 i, j, ep;
|
|
|
+ u16 v;
|
|
|
+ int index;
|
|
|
+ SOE_DEF *soe;
|
|
|
+
|
|
|
+ // 处理单点,如果一个逻辑点对应多个通讯点,将除第一个通讯点外的其它通讯点放入PLC逻辑中
|
|
|
+ for (i = 0; i < g_table_head->di_num; i++)
|
|
|
+ {
|
|
|
+ index = plc_yx2index(g_di_table[i].owner, g_di_table[i].indexno);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将第一个通讯点滤除
|
|
|
+ if (g_lp[index].cp == g_di_table[i].cp)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 没有通讯点,不需要
|
|
|
+ if (g_di_table[i].cp == 0)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 除第一个通讯点外的其它通讯点,放入PLC逻辑中
|
|
|
+ // 检查空间
|
|
|
+ if (g_plc_num >= PLC_EXP_NUM)
|
|
|
+ {
|
|
|
+ rt_printf("g_plc_num单点越限(g_plc_num=%d,i=%d).\r\n", g_plc_num, i);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通讯点
|
|
|
+ g_plc[g_plc_num].cp = g_di_table[i].cp;
|
|
|
+
|
|
|
+ // 标志,目前只有故障记录标志
|
|
|
+ soe = plc_yx2soe(g_di_table[i].owner, g_di_table[i].indexno);
|
|
|
+ if (soe)
|
|
|
+ {
|
|
|
+ if (soe->soe_def & SOE_TYPE_FAULT)
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].flag = (PLC_FLAG_FAULT | (g_di_table[i].owner << 16));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入操作数
|
|
|
+ ep = 0;
|
|
|
+ v = LP_TYPE_YX;
|
|
|
+ v |= (g_di_table[i].owner << 8) | g_di_table[i].indexno;
|
|
|
+ g_plc[g_plc_num].exp[ep++] = v;
|
|
|
+
|
|
|
+ // 单点取反
|
|
|
+ if (g_di_table[i].is_inverse)
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 结束符
|
|
|
+ g_plc[g_plc_num].exp[ep++] = 0;
|
|
|
+
|
|
|
+ g_plc_num++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理合并点
|
|
|
+ g_plc_merge_index = g_plc_num;
|
|
|
+ for (i = 0; i < g_table_head->dimerge_num; i++)
|
|
|
+ {
|
|
|
+ if (g_plc_num >= PLC_EXP_NUM)
|
|
|
+ {
|
|
|
+ rt_printf("g_plc_num合并点越限(g_plc_num=%d,i=%d).\r\n", g_plc_num, i);
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_plc[g_plc_num].cp = g_di_merge_table[i].cp;
|
|
|
+ ep = 0;
|
|
|
+ for (j = 0; j < MIX_YX_NUMBER; j++)
|
|
|
+ {
|
|
|
+ u8 no = g_di_merge_table[i].no[j] & 0xff;
|
|
|
+ u8 owner = (g_di_merge_table[i].no[j] >> 8) & 0xff;
|
|
|
+
|
|
|
+ // 组合点号为空代表结束,退出。
|
|
|
+ if (g_di_merge_table[i].no[j] == 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 标志,目前只有故障记录标志
|
|
|
+ soe = plc_yx2soe(owner, no);
|
|
|
+ if (soe)
|
|
|
+ {
|
|
|
+ if (soe->soe_def & SOE_TYPE_FAULT)
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].flag = (PLC_FLAG_FAULT | (owner << 16));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入操作数
|
|
|
+ v = LP_TYPE_YX | (owner << 8) | no;
|
|
|
+ g_plc[g_plc_num].exp[ep++] = v;
|
|
|
+
|
|
|
+ // 单点取反
|
|
|
+ if (g_di_merge_table[i].is_inv[j])
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入或运算符
|
|
|
+ if (j)
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_OR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并点取反
|
|
|
+ if (g_di_merge_table[i].is_inv_all)
|
|
|
+ {
|
|
|
+ g_plc[g_plc_num].exp[ep++] = PLC_LOGIC_NOT;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 结束符
|
|
|
+ g_plc[g_plc_num].exp[ep++] = 0;
|
|
|
+
|
|
|
+ // 检查长度是否越界
|
|
|
+ if (ep > PLC_EXP_LEN)
|
|
|
+ {
|
|
|
+ rt_printf("plc_iec_table: 表达式太长(i=%d,j=%d,ep=%d).\r\n", i, j, ep);
|
|
|
+ return -3;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_plc_num++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // g_plc[2].do_owner = 0;
|
|
|
+ // g_plc[2].do_index = 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int plc_init(void)
|
|
|
{
|
|
|
- int i, j, k,index,ret;
|
|
|
- u8 sw, no;
|
|
|
- u32 timeout[2] = {0};
|
|
|
- u32 timeout_add;
|
|
|
-
|
|
|
- // 初值
|
|
|
- for(i=0; i< LP_NUM; i++)
|
|
|
- {
|
|
|
- g_lp[i].cp =0;
|
|
|
- g_lp[i].db_index = -1;
|
|
|
- }
|
|
|
- if(equ_config_null())
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- // 单点
|
|
|
- // 保存第一个单点通讯点号
|
|
|
- for(i=0; i<g_table_head->di_num; i++)
|
|
|
- {
|
|
|
- index = plc_yx2index(g_di_table[i].owner,g_di_table[i].indexno);
|
|
|
- if(index < 0)
|
|
|
- {
|
|
|
- // 跳过备用点
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if(g_lp[index].cp == 0)
|
|
|
- {
|
|
|
- g_lp[index].cp = g_di_table[i].cp;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 双点
|
|
|
- if(g_table_head->di_db_num >MAX_DPI_NUMBER)
|
|
|
- {
|
|
|
- return -2;
|
|
|
- }
|
|
|
- for(i=0; i<g_table_head->di_db_num; i++)
|
|
|
- {
|
|
|
- for (k=0; k<2; k++)
|
|
|
- {
|
|
|
- sw = (u8)(g_di_db_table[i].no[k]>>8);
|
|
|
- no = (u8)(g_di_db_table[i].no[k]);
|
|
|
-
|
|
|
- // 得到检查索引
|
|
|
- index = plc_yx2index(sw,no);
|
|
|
- if(index< 0)
|
|
|
- {
|
|
|
- return -3;
|
|
|
- }
|
|
|
-
|
|
|
- // 一个逻辑点只能对应一个双点
|
|
|
- if(g_lp[index].db_index >= 0)
|
|
|
- {
|
|
|
- return -4;
|
|
|
- }
|
|
|
- g_lp[index].db_index = i;
|
|
|
-
|
|
|
- // 得到滤波时间
|
|
|
- for (j=0; j<g_equ_config->di_num; j++)
|
|
|
- {
|
|
|
- if ((g_equ_config_di[j].owner == sw)
|
|
|
- && (g_equ_config_di[j].type == no))
|
|
|
- {
|
|
|
- g_di_db[i].ev_code[k] = (g_equ_config_di[j].slot<<8)|g_equ_config_di[j].index;
|
|
|
- timeout[k] = g_equ_config_di[j].filter_time*USTIMER_MS;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化双点值
|
|
|
- if(j != g_equ_config->di_num)
|
|
|
- {
|
|
|
- // 双点标准定义中,分位在bit0,合位在bit1.在转发点表中合位在前,分位在后
|
|
|
- // 所以移位必须取反一下。
|
|
|
- int sft = !k;
|
|
|
- if(dido_di_is_on(g_equ_config_di[j].slot,g_equ_config_di[j].index))
|
|
|
- {
|
|
|
- g_di_db[i].value0 |= 1<<sft;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- g_di_db[i].value0 &= ~(1<<sft);
|
|
|
- }
|
|
|
-
|
|
|
- g_di_db[i].value1 = g_di_db[i].value0;
|
|
|
- if(g_di_db_table[i].is_inv[k])
|
|
|
- {
|
|
|
- g_di_db[i].value1 ^= 1<<sft;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rt_printf("双点需要实际通道对应(i=%d)\r\n",i);
|
|
|
- return -5;
|
|
|
- }
|
|
|
- }
|
|
|
- // 双点确认延时(两点滤波时间差),转化为us,再增加20ms,以确保双点变位成功
|
|
|
- // 2017-09-05:在电科院测试,遥信10ms滤波,双点没有变位信号。针对此情况修改如下:
|
|
|
- // 1、附加延时由固定的20ms改为最小滤波时间的1/4,这样10ms的遥信滤波,将有2.5ms的附加延时。
|
|
|
- // 初步评估2.5ms的延时相对于5ms的中断间隔是个合适的值,
|
|
|
- // 2、如果附加延时大于20ms则限制为20ms,防止延时过长。
|
|
|
- if(timeout[0] >= timeout[1])
|
|
|
- {
|
|
|
-
|
|
|
- g_di_db[i].timeout = (timeout[0] - timeout[1]);
|
|
|
- timeout_add = timeout[1]/4;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- g_di_db[i].timeout = (timeout[1] - timeout[0]);
|
|
|
- timeout_add = timeout[0]/4;
|
|
|
- }
|
|
|
-
|
|
|
- if(timeout_add >20*USTIMER_MS)
|
|
|
- {
|
|
|
- timeout_add = 20*USTIMER_MS;
|
|
|
- }
|
|
|
-
|
|
|
- g_di_db[i].timeout += timeout_add;
|
|
|
- }
|
|
|
-
|
|
|
- // 解析PLC文件
|
|
|
-
|
|
|
- // 将转发点表中的多余单点和合并点转入PLC模块
|
|
|
- ret = plc_init_iec_table();
|
|
|
- if(ret < 0)
|
|
|
- {
|
|
|
- ret -= 10;
|
|
|
- }
|
|
|
-
|
|
|
- plc_scan(0);
|
|
|
-
|
|
|
- return ret;
|
|
|
+ int i, j, k, index, ret;
|
|
|
+ u8 sw, no;
|
|
|
+ u32 timeout[2] = {0};
|
|
|
+ u32 timeout_add;
|
|
|
+
|
|
|
+ // 初值
|
|
|
+ for (i = 0; i < LP_NUM; i++)
|
|
|
+ {
|
|
|
+ g_lp[i].cp = 0;
|
|
|
+ g_lp[i].db_index = -1;
|
|
|
+ }
|
|
|
+ if (equ_config_null())
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ // 单点
|
|
|
+ // 保存第一个单点通讯点号
|
|
|
+ for (i = 0; i < g_table_head->di_num; i++)
|
|
|
+ {
|
|
|
+ index = plc_yx2index(g_di_table[i].owner, g_di_table[i].indexno);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ // 跳过备用点
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (g_lp[index].cp == 0)
|
|
|
+ {
|
|
|
+ g_lp[index].cp = g_di_table[i].cp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 双点
|
|
|
+ if (g_table_head->di_db_num > MAX_DPI_NUMBER)
|
|
|
+ {
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+ for (i = 0; i < g_table_head->di_db_num; i++)
|
|
|
+ {
|
|
|
+ for (k = 0; k < 2; k++)
|
|
|
+ {
|
|
|
+ sw = (u8)(g_di_db_table[i].no[k] >> 8);
|
|
|
+ no = (u8)(g_di_db_table[i].no[k]);
|
|
|
+
|
|
|
+ // 得到检查索引
|
|
|
+ index = plc_yx2index(sw, no);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ return -3;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 一个逻辑点只能对应一个双点
|
|
|
+ if (g_lp[index].db_index >= 0)
|
|
|
+ {
|
|
|
+ return -4;
|
|
|
+ }
|
|
|
+ g_lp[index].db_index = i;
|
|
|
+
|
|
|
+ // 得到滤波时间
|
|
|
+ for (j = 0; j < g_equ_config->di_num; j++)
|
|
|
+ {
|
|
|
+ if ((g_equ_config_di[j].owner == sw) && (g_equ_config_di[j].type == no))
|
|
|
+ {
|
|
|
+ g_di_db[i].ev_code[k] = (g_equ_config_di[j].slot << 8) | g_equ_config_di[j].index;
|
|
|
+ timeout[k] = g_equ_config_di[j].filter_time * USTIMER_MS;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化双点值
|
|
|
+ if (j != g_equ_config->di_num)
|
|
|
+ {
|
|
|
+ // 双点标准定义中,分位在bit0,合位在bit1.在转发点表中合位在前,分位在后
|
|
|
+ // 所以移位必须取反一下。
|
|
|
+ int sft = !k;
|
|
|
+ if (dido_di_is_on(g_equ_config_di[j].slot, g_equ_config_di[j].index))
|
|
|
+ {
|
|
|
+ g_di_db[i].value0 |= 1 << sft;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_di_db[i].value0 &= ~(1 << sft);
|
|
|
+ }
|
|
|
+
|
|
|
+ g_di_db[i].value1 = g_di_db[i].value0;
|
|
|
+ if (g_di_db_table[i].is_inv[k])
|
|
|
+ {
|
|
|
+ g_di_db[i].value1 ^= 1 << sft;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rt_printf("双点需要实际通道对应(i=%d)\r\n", i);
|
|
|
+ return -5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 双点确认延时(两点滤波时间差),转化为us,再增加20ms,以确保双点变位成功
|
|
|
+ // 2017-09-05:在电科院测试,遥信10ms滤波,双点没有变位信号。针对此情况修改如下:
|
|
|
+ // 1、附加延时由固定的20ms改为最小滤波时间的1/4,这样10ms的遥信滤波,将有2.5ms的附加延时。
|
|
|
+ // 初步评估2.5ms的延时相对于5ms的中断间隔是个合适的值,
|
|
|
+ // 2、如果附加延时大于20ms则限制为20ms,防止延时过长。
|
|
|
+ if (timeout[0] >= timeout[1])
|
|
|
+ {
|
|
|
+
|
|
|
+ g_di_db[i].timeout = (timeout[0] - timeout[1]);
|
|
|
+ timeout_add = timeout[1] / 4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_di_db[i].timeout = (timeout[1] - timeout[0]);
|
|
|
+ timeout_add = timeout[0] / 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timeout_add > 20 * USTIMER_MS)
|
|
|
+ {
|
|
|
+ timeout_add = 20 * USTIMER_MS;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_di_db[i].timeout += timeout_add;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析PLC文件
|
|
|
+
|
|
|
+ // 将转发点表中的多余单点和合并点转入PLC模块
|
|
|
+ ret = plc_init_iec_table();
|
|
|
+ if (ret < 0)
|
|
|
+ {
|
|
|
+ ret -= 10;
|
|
|
+ }
|
|
|
+
|
|
|
+ plc_scan(0);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
int plc_exit(void)
|
|
|
{
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
u8 plc_db_value(int index)
|
|
|
{
|
|
|
- return g_di_db[index].value1;
|
|
|
+ return g_di_db[index].value1;
|
|
|
}
|
|
|
|
|
|
-void plc_db_init_value(u8 slot,u8 no,u8 v)
|
|
|
+void plc_db_init_value(u8 slot, u8 no, u8 v)
|
|
|
{
|
|
|
- int index,db_index;
|
|
|
- u16 ev_code;
|
|
|
-
|
|
|
- ev_code = (slot<<8) | no;
|
|
|
-
|
|
|
- // 得到检查逻辑点索引
|
|
|
- index = plc_yx2index(g_di_st[slot][no].owner,g_di_st[slot][no].type);
|
|
|
- if(index < 0)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
+ int index, db_index;
|
|
|
+ u16 ev_code;
|
|
|
|
|
|
- // 检查双点索引
|
|
|
- db_index = g_lp[index].db_index;
|
|
|
- if(db_index < 0)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
+ ev_code = (slot << 8) | no;
|
|
|
+
|
|
|
+ // 得到检查逻辑点索引
|
|
|
+ index = plc_yx2index(g_di_st[slot][no].owner, g_di_st[slot][no].type);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查双点索引
|
|
|
+ db_index = g_lp[index].db_index;
|
|
|
+ if (db_index < 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
#if 1
|
|
|
- // 取消正在进行的双点处理过程
|
|
|
- g_di_db[db_index].bChange = 0;
|
|
|
+ // 取消正在进行的双点处理过程
|
|
|
+ g_di_db[db_index].bChange = 0;
|
|
|
#else
|
|
|
- // 双点第一次变位,记录时标
|
|
|
- if (g_di_db[db_index].bChange == 0)
|
|
|
- {
|
|
|
- g_di_db[db_index].ts = ev->ts;
|
|
|
- g_di_db[db_index].bChange = 1;
|
|
|
- }
|
|
|
+ // 双点第一次变位,记录时标
|
|
|
+ if (g_di_db[db_index].bChange == 0)
|
|
|
+ {
|
|
|
+ g_di_db[db_index].ts = ev->ts;
|
|
|
+ g_di_db[db_index].bChange = 1;
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
- // 每次变位都重新获取超时起点和双点的值
|
|
|
- g_di_db[db_index].us0 = ustimer_get_origin();
|
|
|
- if(ev_code == g_di_db[db_index].ev_code[0])
|
|
|
- {
|
|
|
- index = 1;
|
|
|
- }
|
|
|
- else if(ev_code == g_di_db[db_index].ev_code[1])
|
|
|
- {
|
|
|
- index = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rt_printf("plc_db_soe:ev_code err!\r\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 滤波前的值
|
|
|
- if(v)
|
|
|
- {
|
|
|
- g_di_db[db_index].value0 |= 1<<index;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- g_di_db[db_index].value0 &= ~(1<<index);
|
|
|
- }
|
|
|
-
|
|
|
- // 滤波后的值
|
|
|
- // 双点标准定义中,分位在bit0,合位在bit1.在转发点表中合位在前,分位在后
|
|
|
- // 所以移位必须取反一下。
|
|
|
- if(g_di_db_table[db_index].is_inv[!index])
|
|
|
- {
|
|
|
- v = !v;
|
|
|
- }
|
|
|
- if(v)
|
|
|
- {
|
|
|
- g_di_db[db_index].value1 |= (1<<index);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- g_di_db[db_index].value1 &= ~(1<<index);
|
|
|
- }
|
|
|
+ // 每次变位都重新获取超时起点和双点的值
|
|
|
+ g_di_db[db_index].us0 = ustimer_get_origin();
|
|
|
+ if (ev_code == g_di_db[db_index].ev_code[0])
|
|
|
+ {
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ else if (ev_code == g_di_db[db_index].ev_code[1])
|
|
|
+ {
|
|
|
+ index = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rt_printf("plc_db_soe:ev_code err!\r\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 滤波前的值
|
|
|
+ if (v)
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value0 |= 1 << index;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value0 &= ~(1 << index);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 滤波后的值
|
|
|
+ // 双点标准定义中,分位在bit0,合位在bit1.在转发点表中合位在前,分位在后
|
|
|
+ // 所以移位必须取反一下。
|
|
|
+ if (g_di_db_table[db_index].is_inv[!index])
|
|
|
+ {
|
|
|
+ v = !v;
|
|
|
+ }
|
|
|
+ if (v)
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value1 |= (1 << index);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value1 &= ~(1 << index);
|
|
|
+ }
|
|
|
|
|
|
#if 0
|
|
|
rt_printf("db_init:db=%d,index=%d,is_inv=%d,v0=%d,v1=%d\r\n",
|
|
|
@@ -577,216 +571,211 @@ void plc_db_init_value(u8 slot,u8 no,u8 v)
|
|
|
g_di_db[db_index].value1);
|
|
|
#endif
|
|
|
|
|
|
- return;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
void plc_db_soe(EVENT_STRUCT *ev)
|
|
|
{
|
|
|
- int index,db_index;
|
|
|
- u8 slot,no;
|
|
|
-
|
|
|
- slot = (ev->ev_code>>8);
|
|
|
- no = ev->ev_code&0xff;
|
|
|
-
|
|
|
- // 得到检查逻辑点索引
|
|
|
- index = plc_yx2index(g_di_st[slot][no].owner,g_di_st[slot][no].type);
|
|
|
- if(index < 0)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 检查双点索引
|
|
|
- db_index = g_lp[index].db_index;
|
|
|
- if(db_index < 0)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 双点第一次变位,记录时标
|
|
|
- if (g_di_db[db_index].bChange == 0)
|
|
|
- {
|
|
|
- g_di_db[db_index].ts = ev->ts;
|
|
|
- g_di_db[db_index].bChange = 1;
|
|
|
- }
|
|
|
-
|
|
|
- // 每次变位都重新获取超时起点和双点的值
|
|
|
- g_di_db[db_index].us0 = ustimer_get_origin();
|
|
|
- if(ev->ev_code == g_di_db[db_index].ev_code[0])
|
|
|
- {
|
|
|
- index = 1;
|
|
|
- }
|
|
|
- else if(ev->ev_code == g_di_db[db_index].ev_code[1])
|
|
|
- {
|
|
|
- index = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rt_printf("plc_db_soe:ev_code err!\r\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if(ev->ev_value)
|
|
|
- {
|
|
|
- g_di_db[db_index].value0 |= 1<<index;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- g_di_db[db_index].value0 &= ~(1<<index);
|
|
|
- }
|
|
|
-
|
|
|
- return;
|
|
|
+ int index, db_index;
|
|
|
+ u8 slot, no;
|
|
|
+
|
|
|
+ slot = (ev->ev_code >> 8);
|
|
|
+ no = ev->ev_code & 0xff;
|
|
|
+
|
|
|
+ // 得到检查逻辑点索引
|
|
|
+ index = plc_yx2index(g_di_st[slot][no].owner, g_di_st[slot][no].type);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查双点索引
|
|
|
+ db_index = g_lp[index].db_index;
|
|
|
+ if (db_index < 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 双点第一次变位,记录时标
|
|
|
+ if (g_di_db[db_index].bChange == 0)
|
|
|
+ {
|
|
|
+ g_di_db[db_index].ts = ev->ts;
|
|
|
+ g_di_db[db_index].bChange = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 每次变位都重新获取超时起点和双点的值
|
|
|
+ g_di_db[db_index].us0 = ustimer_get_origin();
|
|
|
+ if (ev->ev_code == g_di_db[db_index].ev_code[0])
|
|
|
+ {
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ else if (ev->ev_code == g_di_db[db_index].ev_code[1])
|
|
|
+ {
|
|
|
+ index = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rt_printf("plc_db_soe:ev_code err!\r\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ev->ev_value)
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value0 |= 1 << index;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_di_db[db_index].value0 &= ~(1 << index);
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 双点滤波处理,得到滤波后的值
|
|
|
static void plc_db_scan(void)
|
|
|
{
|
|
|
- int i,value;
|
|
|
- uint32_t flags;
|
|
|
-
|
|
|
- for(i=0; i<g_table_head->di_db_num; i++)
|
|
|
- {
|
|
|
- if (g_di_db[i].bChange)
|
|
|
- {
|
|
|
- // 屏蔽中断的情况下检查超时,防止超时和value不对应。
|
|
|
- value = -1;
|
|
|
- rt_irq_save(flags);
|
|
|
- if(ustimer_get_duration(g_di_db[i].us0) >= g_di_db[i].timeout)
|
|
|
- {
|
|
|
-
|
|
|
- value = g_di_db[i].value0;
|
|
|
- }
|
|
|
- rt_irq_restore(flags);
|
|
|
-
|
|
|
- if(value!= -1)
|
|
|
- {
|
|
|
- g_di_db[i].bChange = 0;
|
|
|
-
|
|
|
- if(g_di_db_table[i].is_inv[0])
|
|
|
- {
|
|
|
- value ^= 2;
|
|
|
- }
|
|
|
- if(g_di_db_table[i].is_inv[1])
|
|
|
- {
|
|
|
- value ^= 1;
|
|
|
- }
|
|
|
-
|
|
|
- // 如果和旧值相等,说明信号已返回,不应送SOE。
|
|
|
- if(value != g_di_db[i].value1)
|
|
|
- {
|
|
|
- soe_record_dpi(i,value,&g_di_db[i].ts);
|
|
|
- g_di_db[i].value1 = value;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return;
|
|
|
+ int i, value;
|
|
|
+ uint32_t flags;
|
|
|
+
|
|
|
+ for (i = 0; i < g_table_head->di_db_num; i++)
|
|
|
+ {
|
|
|
+ if (g_di_db[i].bChange)
|
|
|
+ {
|
|
|
+ // 屏蔽中断的情况下检查超时,防止超时和value不对应。
|
|
|
+ value = -1;
|
|
|
+ rt_irq_save(flags);
|
|
|
+ if (ustimer_get_duration(g_di_db[i].us0) >= g_di_db[i].timeout)
|
|
|
+ {
|
|
|
+ value = g_di_db[i].value0;
|
|
|
+ }
|
|
|
+ rt_irq_restore(flags);
|
|
|
+
|
|
|
+ if (value != -1)
|
|
|
+ {
|
|
|
+ g_di_db[i].bChange = 0;
|
|
|
+
|
|
|
+ if (g_di_db_table[i].is_inv[0])
|
|
|
+ {
|
|
|
+ value ^= 2;
|
|
|
+ }
|
|
|
+ if (g_di_db_table[i].is_inv[1])
|
|
|
+ {
|
|
|
+ value ^= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果和旧值相等,说明信号已返回,不应送SOE。
|
|
|
+ if (value != g_di_db[i].value1)
|
|
|
+ {
|
|
|
+ soe_record_dpi(i, value, &g_di_db[i].ts);
|
|
|
+ g_di_db[i].value1 = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- int plc_scan(int is_rec)
|
|
|
+int plc_scan(int is_rec)
|
|
|
{
|
|
|
- static s32 r[64];
|
|
|
- u16 *p,i,rp;
|
|
|
-
|
|
|
- // 双点扫描
|
|
|
- plc_db_scan();
|
|
|
-
|
|
|
- // PLC扫描
|
|
|
- for(i=0;i<g_plc_num;i++)
|
|
|
- {
|
|
|
- p = g_plc[i].exp;
|
|
|
- rp = 0;
|
|
|
- while(*p)
|
|
|
- {
|
|
|
- // 操作数,直接压栈
|
|
|
- if(((*p)&LP_TYPE) != LP_TYPE_PLC_OPT)
|
|
|
- {
|
|
|
- r[rp++] = plc_get_input(*p);
|
|
|
- }
|
|
|
- // 运算符,出栈计算,结果压栈
|
|
|
- else
|
|
|
- {
|
|
|
- switch(*p)
|
|
|
- {
|
|
|
- case PLC_LOGIC_NOT:
|
|
|
- r[rp-1] = (~r[rp-1]) & 0x01;
|
|
|
- break;
|
|
|
-
|
|
|
- case PLC_LOGIC_AND:
|
|
|
- r[rp-2] = r[rp-1] & r[rp-2];
|
|
|
- rp--;
|
|
|
- break;
|
|
|
-
|
|
|
- case PLC_LOGIC_OR:
|
|
|
- r[rp-2] = r[rp-1] | r[rp-2];
|
|
|
- rp--;
|
|
|
- break;
|
|
|
-
|
|
|
- case PLC_LOGIC_XOR:
|
|
|
- r[rp-2] = r[rp-1] ^ r[rp-2];
|
|
|
- rp--;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- p++;
|
|
|
- }
|
|
|
-
|
|
|
- // 全部计算完毕,rp应该等1.
|
|
|
- if(rp != 1)
|
|
|
- {
|
|
|
- rt_err_set(ERR_CODE_PLC,0);
|
|
|
- rt_printf("plc_scan:i=%d,rp=%d\r\n",i,rp);
|
|
|
- }
|
|
|
-
|
|
|
- if(g_plc[i].result != r[rp -1])
|
|
|
- {
|
|
|
- g_plc[i].result = r[rp -1];
|
|
|
-
|
|
|
- // 开出
|
|
|
- if(g_plc[i].do_index)
|
|
|
- {
|
|
|
- int type;
|
|
|
- if(g_plc[i].result)
|
|
|
- {
|
|
|
- type = SW_DO_TYPE_ON;
|
|
|
- soe_record_opt(EV_PLC_HZ,((g_plc[i].do_owner<<8)|g_plc[i].do_index));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- type = SW_DO_TYPE_OFF;
|
|
|
- soe_record_opt(EV_PLC_TZ,((g_plc[i].do_owner<<8)|g_plc[i].do_index));
|
|
|
- }
|
|
|
-
|
|
|
- if(g_plc[i].do_owner == 0)
|
|
|
- {
|
|
|
- sw_do_pub(g_plc[i].do_index-1,type);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- sw_do(g_plc[i].do_owner-1,g_plc[i].do_index-1,type);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 需要送主站
|
|
|
- if(g_plc[i].cp && is_rec)
|
|
|
- {
|
|
|
- u8 value = g_plc[i].result ? 1:0;
|
|
|
- soe_record_plc(i,value,g_plc[i].flag);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
+ static s32 r[64];
|
|
|
+ u16 *p, i, rp;
|
|
|
+
|
|
|
+ // 双点扫描
|
|
|
+ plc_db_scan();
|
|
|
+
|
|
|
+ // PLC扫描
|
|
|
+ for (i = 0; i < g_plc_num; i++)
|
|
|
+ {
|
|
|
+ p = g_plc[i].exp;
|
|
|
+ rp = 0;
|
|
|
+ while (*p)
|
|
|
+ {
|
|
|
+ // 操作数,直接压栈
|
|
|
+ if (((*p) & LP_TYPE) != LP_TYPE_PLC_OPT)
|
|
|
+ {
|
|
|
+ r[rp++] = plc_get_input(*p);
|
|
|
+ }
|
|
|
+ // 运算符,出栈计算,结果压栈
|
|
|
+ else
|
|
|
+ {
|
|
|
+ switch (*p)
|
|
|
+ {
|
|
|
+ case PLC_LOGIC_NOT:
|
|
|
+ r[rp - 1] = (~r[rp - 1]) & 0x01;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PLC_LOGIC_AND:
|
|
|
+ r[rp - 2] = r[rp - 1] & r[rp - 2];
|
|
|
+ rp--;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PLC_LOGIC_OR:
|
|
|
+ r[rp - 2] = r[rp - 1] | r[rp - 2];
|
|
|
+ rp--;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PLC_LOGIC_XOR:
|
|
|
+ r[rp - 2] = r[rp - 1] ^ r[rp - 2];
|
|
|
+ rp--;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 全部计算完毕,rp应该等1.
|
|
|
+ if (rp != 1)
|
|
|
+ {
|
|
|
+ rt_err_set(ERR_CODE_PLC, 0);
|
|
|
+ rt_printf("plc_scan:i=%d,rp=%d\r\n", i, rp);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (g_plc[i].result != r[rp - 1])
|
|
|
+ {
|
|
|
+ g_plc[i].result = r[rp - 1];
|
|
|
+
|
|
|
+ // 开出
|
|
|
+ if (g_plc[i].do_index)
|
|
|
+ {
|
|
|
+ int type;
|
|
|
+ if (g_plc[i].result)
|
|
|
+ {
|
|
|
+ type = SW_DO_TYPE_ON;
|
|
|
+ soe_record_opt(EV_PLC_HZ, ((g_plc[i].do_owner << 8) | g_plc[i].do_index));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ type = SW_DO_TYPE_OFF;
|
|
|
+ soe_record_opt(EV_PLC_TZ, ((g_plc[i].do_owner << 8) | g_plc[i].do_index));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (g_plc[i].do_owner == 0)
|
|
|
+ {
|
|
|
+ sw_do_pub(g_plc[i].do_index - 1, type);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sw_do(g_plc[i].do_owner - 1, g_plc[i].do_index - 1, type);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 需要送主站
|
|
|
+ if (g_plc[i].cp && is_rec)
|
|
|
+ {
|
|
|
+ u8 value = g_plc[i].result ? 1 : 0;
|
|
|
+ soe_record_plc(i, value, g_plc[i].flag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/*------------------------------ 内部函数 -------------------------------------
|
|
|
内部函数以下划线‘_’开头,不需要检查参数的合法性.
|
|
|
*/
|