/****************************************************************************** 版权所有: 文件名称: protect.c 文件版本: 01.01 创建作者: xxxxxx 创建日期: 2012-03-28 功能说明: 保护整组处理过程 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ #define SW_I_NUM 4 // 突变量算法仅涉及三相相电流及零序电流 /*------------------------------ 类型结构 ------------------------------------- */ /*------------------------------ 全局变量 ------------------------------------- */ struct protect_stu g_protect; // 保护整组处理过程 TRELAY_T g_tRelay[SWITCH_NUM_MAX]; u16 wIQdCnt[SWITCH_NUM_MAX][SW_I_NUM]; // 突变量启动计数器 static DWORD dTAfterFault=0; /*------------------------------ 函数声明 ------------------------------------- */ static int _protect_amp_qd(u32 dStep); static int _protect_gzcl_init(void); static int _protect_gzcl_process(void); static int _protect_zzfg_check(u32 dStep); static int _protect_zzfg(void); static int _protect_sw_tz(u32 dStep); static int _protect_sw_hz(u32 dStep); static int _protect_alarm(void); static int _protect_rmt_sw (u32 dStep); static int _protect_sfsh_clr(void); static bool _protect_check_fault(int sw); /*------------------------------ 外部函数 ------------------------------------- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性. */ /****************************************************************************** 函数名称: protect_init 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护相关标志初始化 参数说明: 无 返回值: 成功返回0. 修改记录: */ int protect_init(void) { int i; // 初始化保护整组相关标志 memset(&g_protect, 0, sizeof(g_protect)); memset(&wIQdCnt,0,sizeof(wIQdCnt)); // 初始化保护相关标志 for(i=0;itSwSet[sw].bTT_bh_xbbs; for(oc=BH_GL1;oc<=BH_GL3;oc++) { TOC_T *poc = &g_tRelay[sw].tOC[oc]; OC_SET *pSet = &pRunSet->tSwSet[sw].toc[oc]; poc->sta.bFlag.bIaQD = OverRelay(g_ui[ui_begin+SW_AC_IA].m2[0], pSet->dI, pSet->dI_fh, poc->sta.bFlag.bIaQD); poc->sta.bFlag.bIbQD = OverRelay(g_ui[ui_begin+SW_AC_IB].m2[0], pSet->dI, pSet->dI_fh, poc->sta.bFlag.bIbQD); poc->sta.bFlag.bIcQD = OverRelay(g_ui[ui_begin+SW_AC_IC].m2[0], pSet->dI, pSet->dI_fh, poc->sta.bFlag.bIcQD); bIazx=CalDir_A(sw,poc->sta.bFlag.bIaQD&&pSet->bDir,pRunSet->tSwSet[sw].bTT_DIR_Inv); //方向计算 bIbzx=CalDir_B(sw,poc->sta.bFlag.bIbQD&&pSet->bDir,pRunSet->tSwSet[sw].bTT_DIR_Inv); bIczx=CalDir_C(sw,poc->sta.bFlag.bIcQD&&pSet->bDir,pRunSet->tSwSet[sw].bTT_DIR_Inv); poc->sta.bFlag.bIaxb =bxb&&XBCalc(sw,SW_AC_IA,pRunSet->tSwSet[sw].d_bh_xbcoe,poc->sta.bFlag.bIaQD); poc->sta.bFlag.bIbxb=bxb&&XBCalc(sw,SW_AC_IB,pRunSet->tSwSet[sw].d_bh_xbcoe,poc->sta.bFlag.bIbQD); poc->sta.bFlag.bIcxb=bxb&&XBCalc(sw,SW_AC_IC,pRunSet->tSwSet[sw].d_bh_xbcoe,poc->sta.bFlag.bIcQD); bQDD=poc->sta.bFlag.bIaQD||poc->sta.bFlag.bIbQD||poc->sta.bFlag.bIcQD; bxbbs=(poc->sta.bFlag.bIaxb||poc->sta.bFlag.bIbxb||poc->sta.bFlag.bIcxb); //谐波闭锁 if(BH_ALL_EN(sw)) { poc->sta.bFlag.bXBbs = (BH_ALL_EN(sw) && (pSet->bTz||pSet->bGj) && bQDD) && bxbbs; if( oc== BH_GL1) xb_bs_soe(g_protect.sw,dStep); } } } #endif #ifdef FUNC_SEND_FAULT_CURRENT void yc_refresh_en(int sw) { TRELAY_T *pR=&g_tRelay[sw]; int ui_begin; DWORD Ia,Ib,Ic; DWORD I0; ui_begin = UI_SW_INDEX_BEGIN(sw); Ia = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IA].m2[0]), 256, g_ui[ui_begin + SW_AC_IA].m2_factor_k); Ib = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IB].m2[0]), 256, g_ui[ui_begin + SW_AC_IB].m2_factor_k); Ic = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IC].m2[0]), 256, g_ui[ui_begin + SW_AC_IC].m2_factor_k); I0 = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_I0].m2[0]), 256, g_ui[ui_begin + SW_AC_I0].m2_factor_k); if(pR->bYcRefresh.bAGl) { pR->bYcRefresh.bAGl = false; g_sw_pub.ac_in[PUB_AC_YC9] = Ia; } if(pR->bYcRefresh.bBGl) { pR->bYcRefresh.bBGl = false; g_sw_pub.ac_in[PUB_AC_YC10] = Ib; } if(pR->bYcRefresh.bCGl) { pR->bYcRefresh.bCGl = false; g_sw_pub.ac_in[PUB_AC_YC11] = Ic; } if(pR->bYcRefresh.bLx) { pR->bYcRefresh.bLx = false; g_sw_pub.ac_in[PUB_AC_YC12] = I0; } if(g_run_stu.button_on) { int i=0; g_run_stu.button_on = false; for(i=PUB_AC_YC9;i<=PUB_AC_YC12;i++) { g_sw_pub.ac_in[i] = 0; } } } #endif /****************************************************************************** 函数名称: protect_polling 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护5ms巡检 参数说明: 无 返回值: 成功返回0. 修改记录: */ int protect_polling(void) { u64 us0; u64 dTDelta; // 5ms巡检时间片 // 首次进入初始化 if (!g_protect.update) { g_protect.t_rcd_bh = dTCounter; g_protect.update = 1; return 0; } // 取得5ms巡检的时间间隔 dTDelta = dTCounter - g_protect.t_rcd_bh; g_protect.t_rcd_bh = dTCounter; // 计算全波FFT us0 = ustimer_get_origin(); sw_cal_protect(); rt_stat_other_in(1,ustimer_get_duration(us0)/USTIMER_US); // 定值有修改,重新初始化 if(bRunSetModify) { ProtectRelayInit1(); bRunSetModify = 0; } #ifdef FUNC_DRIVE_JY clear_func_drive(dTDelta); #endif // 内部状态识别 run_status_check(dTDelta); if(rt_err_count())return -1; //系统异常,退出保护处理 // 公共轮巡类保护 { Pro_vol(dTDelta); // 电压告警逻辑 #ifdef XDL_ZT //小电流接地 xdl_protect(dTDelta); // 小电流接地保护 #endif PT_Check(dTDelta); FDL_Check(dTDelta); #ifdef FUN_HCBS hcbs_dataset(); #endif } // 开关类保护 for (g_protect.sw=0; g_protect.swzqd) { _protect_amp_qd(dTDelta); } #ifdef FUNC_DRIVE if(gb_drive.b_drive_on) { // 保护跳合闸处理 _protect_sw_tz(dTDelta); return 0; } #endif // 故障处理流程 if(pR->zqd) { switch(pR->gz_process) { // 保护处理初始化 case CXLC_BHIN: _protect_gzcl_init(); break; // 保护处理 case CXLC_BHCL: _protect_gzcl_process(); break; // 整组复归 case CXLC_ZZFG: _protect_zzfg(); break; default: watchdog_reset_cpu(51); break; } } #ifdef FUNC_SEND_FAULT_CURRENT yc_refresh_en(g_protect.sw); #endif _protect_alarm(); // 异常告警类逻辑 _protect_sfsh_clr(); // 清除手分、手合标志 } // 保护巡检完毕,检查事故总 _protect_sg_all(); rt_stat_other_in(2,ustimer_get_duration(us0)/USTIMER_US); return 0; } /****************************************************************************** 函数名称: protect_tbl_qd 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护突变量启动 参数说明: 无 返回值: 成功返回0. 修改记录: */ int protect_tbl_qd(void) { short pnSam[3] = {0}; long laaa; DWORD daaa; int i; u32 sw; int caulp = g_adc_dots_index; for (sw=0; swzqd) { continue; } // 保护未启动,获取故障的第一个点时刻,作为故障启动时刻,+1是因为 if((wIQdCnt[sw][SW_AC_IA] == 0) && (wIQdCnt[sw][SW_AC_IB] == 0) && (wIQdCnt[sw][SW_AC_IC] == 0) &&(wIQdCnt[sw][SW_AC_I0] == 0)) { pR->t_rcd_qd = dTCounter+1; pR->us_tbl = ustimer_get_origin(); pR->tblqd = 0; } else { if (!pR->tblqd) { pR->tblqd = 1; pR->tbldz = 0; pR->tblzzdz = 0; } } //保护未起动、突变量启动判断 for(i=0; i pRunSet->dTBLValue[sw] ) { wIQdCnt[sw][i] += 2; if(wIQdCnt[sw][i] >= TBLQDDSMK) { pR->uBHQD.bFlag.bTBQD = true; rt_printf_time("protect_tbl_qd:i=%d,daaa=%d,dTBLValue=%d.\r\n",i,daaa,pRunSet->dTBLValue[sw]); break; } } else { if(wIQdCnt[sw][i] >= 1) { wIQdCnt[sw][i]--; } } } if(pR->uBHQD.bFlag.bTBQD) { // 进入故障流程:故障初始化 pR->gz_process = CXLC_BHIN; // 保护总启动标志置位 pR->zqd = 1; pR->uBHQD.bFlag.bZQD = 1; // 清除计数 memset(&wIQdCnt[sw], 0, SW_I_NUM*2); // 突变量启动时间统计 rt_stat_in(&pR->tbl_stat, ustimer_get_duration(pR->us_tbl)/USTIMER_US); } } return 0; } // 速断幅值启动滤波加速,加快幅值启动过程 int protect_amp_qd_js(int sw) { #ifdef GD_AREA_ZHUHAI_V2 return 0; #else int i,v,r; int ui_begin; int chn_index; u32 m2_max; s16* dots; u32 threshold; // 寻找最大值的相 ui_begin = UI_SW_INDEX_BEGIN(sw); m2_max = 0; chn_index = 0; for(i=0;i<3;i++) { if(g_ui[ui_begin].m2[0] > m2_max && g_ui[ui_begin].chn_index != CFG_ADC_CHANNEL_ZERO) { m2_max = g_ui[ui_begin].m2[0]; chn_index = g_ui[ui_begin].chn_index; } ui_begin++; } if(m2_max == 0) { // 理论上,有采样通道的最大值相不可能不存在 // rt_printf("Pro_SDGJ:m2_max == 0.\r\n"); return 0; } // 在最大值的通道里,计算傅立叶的采样点中,检查相位相差180度的两点之和是否大约设定值。 // 条件满足就算存在干扰 dots = adc_fourier_address(chn_index,g_prot_index); threshold = (u32)rt_round(sqrt_32fix(m2_max)*pRunSet->fFZLBXS/Q16_BASE); r = 1; for(i=0; i= threshold) // 如果系数设置为0,则幅值加速没有效果。 { // 干扰存在 r = 0; break; } } { float it,iv; // it = (float)_Mul_Div_U(threshold*Q16_BASE, 256, g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k); // iv = (float)_Mul_Div_U(v*Q16_BASE, 256, g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k); it = (float)threshold*256/g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k; iv = (float)v*256/g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k; #if 0 // modify for xxxxxx 当输入量在保护定值的边界值时,会反复打印,导致装置重启 rt_printf("threshold=%d,v=%d,r=%d,m2_max=%d,fFZLBXS=%f.\r\n",threshold,v,r,m2_max,pRunSet->fFZLBXS); rt_printf_time("it=%f,iv=%f,iv/it=%f.\r\n",it,iv,iv/it); #endif } return r; #endif } // 零序幅值启动滤波加速,加快幅值启动过程 int protect_amp_lx_js(int sw) { #ifdef GD_AREA_ZHUHAI_V2 return 0; #else int i,v,r; int ui_begin; int chn_index; u32 m2_max; s16* dots; u32 threshold; ui_begin = UI_SW_INDEX(sw,SW_AC_I0); m2_max = g_ui[ui_begin].m2[0]; chn_index = g_ui[ui_begin].chn_index; if(m2_max == 0) { // 理论上,有采样通道的最大值相不可能不存在 rt_printf("protect_amp_lx_js:m2_max == 0.\r\n"); return 0; } // 在最大值的通道里,计算傅立叶的采样点中,检查相位相差180度的两点之和是否大约设定值。 // 条件满足就算存在干扰 dots = adc_fourier_address(chn_index,g_prot_index); threshold = (u32)rt_round(sqrt_32fix(m2_max)*pRunSet->fFZLBXS/Q16_BASE); r = 1; for(i=0; i= threshold) // 如果系数设置为0,则幅值加速没有效果。 { // 干扰存在 r = 0; break; } } { float it,iv; // it = (float)_Mul_Div_U(threshold*Q16_BASE, 256, g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k); // iv = (float)_Mul_Div_U(v*Q16_BASE, 256, g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k); it = (float)threshold*256/g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k; iv = (float)v*256/g_ui[UI_SW_INDEX_BEGIN(sw)].m2_factor_k; #if 0 // modify for xxxxxx 当输入量在保护定值的边界值时,会反复打印,导致装置重启 rt_printf("lx_threshold=%d,v=%d,r=%d,m2_max=%d,fFZLBXS=%f.\r\n",threshold,v,r,m2_max,pRunSet->fFZLBXS); rt_printf_time("lx_it=%f,iv=%f,iv/it=%f.\r\n",it,iv,iv/it); #endif } return r; #endif } /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /****************************************************************************** 函数名称: _protect_amp_qd 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护幅值启动 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_amp_qd(u32 dStep) { bool bQD; bool bFZJS=false; // 幅值加速 bool bFZQD=false; // 幅值加速 u32 sw = g_protect.sw; int i; TRELAY_T *pR=&g_tRelay[sw]; bQD = 0; //过流类启动 for(i=BH_GL1;i<=FA_DLBS;i++) { TOC_T *pSW = &g_tRelay[sw].tOC[i]; OC_SET *pSet = &pRunSet->tSwSet[sw].toc[i]; bool bY1=false,bEn; if(i<=BH_LXJS)bEn=BH_ALL_EN(sw); else bEn=FA_ALL_EN(sw); if (bEn&& (pSet->bTz||pSet->bGj)) { #ifdef DISP_SET_LX3 if(i==BH_LX1||i==BH_LX2||i==BH_LX3||i==BH_LXJS||i==FA_LX) #else if(i==BH_LX1||i==BH_LX2||i==BH_LXJS||i==FA_LX) #endif { bY1 = OverRelay(g_ui[UI_SW_INDEX(sw,SW_AC_I0)].m2[0], pSet->dI, pSet->dI, false); } else { #ifdef OCI_XB_0MS bY1 = OverRelay(g_sw[sw].m2_max, pSet->dI, pSet->dI, false) && (!pR->tOC[BH_GL1].sta.bFlag.bXBbs); #else bY1 = OverRelay(g_sw[sw].m2_max, pSet->dI, pSet->dI, false); #endif } } //幅值启动25ms延时 RunTR(&pSW->tFz25ms, bY1, dStep); bQD|=bY1; bFZQD|=pSW->tFz25ms.boolTrip; } //反时限启动 { TSETSW *pSet = &pRunSet->tSwSet[sw]; bool bY1; if (BH_ALL_EN(sw)&&pSet->bTT_FSX) { bY1 = OverRelay(g_sw[sw].fz_max, pSet->dIglfsx, pSet->dIglfsx, false); bFZQD|=bY1; } } //智能分布式启动判断 { TGOC_T *poc = &g_tRelay[sw].tgoc; GOC_SET *pSet = &pRunSet->tSwSet[sw].tGocSet; bool bY1=false,bY2=false; if (BH_GOOSE_EN(sw)) { bY1 = OverRelay(g_sw[sw].m2_max, pSet->dIgl, pSet->dIgl, false); bY2 = OverRelay(g_ui[UI_SW_INDEX(sw,SW_AC_I0)].m2[0], pSet->dIlx, pSet->dIlx, false); } //幅值启动25ms延时 RunTR(&poc->tglFz25ms, bY1, dStep); RunTR(&poc->tlxFz25ms, bY2, dStep); bQD|=(bY1|bY2); bFZQD|=poc->tglFz25ms.boolTrip; bFZQD|=poc->tlxFz25ms.boolTrip; #if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ECZD_CHAOZHOU_2022 if (BH_GOOSE_EN(sw)) { bY1 = OverRelay(g_sw[sw].m2_max, pSet->dIgl2, pSet->dIgl2, false); } //幅值启动25ms延时 RunTR(&poc->tgl2Fz25ms, bY1, dStep); bQD|=(bY1); bFZQD|=poc->tgl2Fz25ms.boolTrip; #endif } if (bQD) { if (!pR->fzqd) { pR->us_fz = ustimer_get_origin(); pR->fzqd = 1; pR->fzdz = 0; pR->fzzzdz = 0; dStep = 0; } // 幅值启动加速 #ifndef GD_AREA_ZHUHAI_V2 bFZJS = protect_amp_qd_js(sw); bFZJS |= protect_amp_lx_js(sw); //xj #endif } else { pR->fzqd = 0; } pR->uBHQD.bFlag.bFZQD = bFZJS||bFZQD ; // 幅值启动加速 // 其他启动,借助幅值启动,进入故障处理流程,以实现录波、出口、整组复归过程 { bool bY1=false; bY1|=pR->tgoc.sta.bFlag.bgzglQD ||pR->tgoc.sta.bFlag.bsdQD ||pR->tgoc.sta.bFlag.berrQD ||pR->tgoc.sta.bFlag.bextQD ||pR->tgoc.sta.bFlag.bllQD; for(i=0;i<8;i++) { bY1|=pR->tFdl[i].sta.bFlag.bTz; } #ifdef GD_AREA_ZHONGSHAN_2020 bY1|=pR->tgoc.tOc[FAG_GL1].sta.bFlag.bQD // 启动 ||pR->tgoc.tOc[FAG_GL2].sta.bFlag.bQD ||pR->tgoc.tOc[FAG_LX].sta.bFlag.bQD; #endif pR->uBHQD.bFlag.bBHQD = bY1||pR->tCHZ.sta.bFlag.bCHQD // 重合闸 || pR->tU0TZ.uZOV.bFlag.bQD // 合后接地跳闸 || pR->tDYJL.sta.bFlag.bQD // 电压解列 || pR->tPLJL.sta.bFlag.bQD // 频率解列 || pR->tXXTZ.uZOV.bFlag.bQD // 选线跳闸 || pR->tLostVot.uLostVot.bFlag.bQD // 失压分闸 || pR->tOVER_U0TZ.uZOV.bFlag.bTz //过零序电压跳闸 || pR->tOC[FA_GL].sta.bFlag.bQD || pR->tOC[FA_GL_II].sta.bFlag.bQD || pR->tOC[FA_LX].sta.bFlag.bQD //零序电流启动 #ifdef FUN_JDXX || pR->tJD.sta.bFlag.bTz // 接地选线跳 #endif ; } //幅值启动 + 其他启动 = 总启动 if (pR->uBHQD.bFlag.bFZQD || pR->uBHQD.bFlag.bBHQD) { WORD wSubCnt; #ifdef FUNC_DRIVE gb_drive.b_drive_on = false; #endif // 如果是幅值启动,故障启动时刻倒退25ms if(pR->uBHQD.bFlag.bFZQD) { wSubCnt = T_25ms; } else { wSubCnt = 0; } // 记录故障启动时刻 pR->t_rcd_qd = dTCounter - wSubCnt; // 进入故障流程:故障初始化 pR->gz_process = CXLC_BHIN; // 保护总启动标志置位 pR->zqd = 1; pR->uBHQD.bFlag.bZQD = 1; // 此时突变量未启动,将故障处理的等待限制取消 if(!pR->uBHQD.bFlag.bTBQD) { pR->uBHQD.bFlag.bQD25ms = true; } // 幅值启动时间统计 if (pR->uBHQD.bFlag.bFZQD) { rt_stat_in(&pR->fz_stat, ustimer_get_duration(pR->us_fz)/USTIMER_US); } rt_printf_time("开关%d辐值启动(bFZJS=%d)\r\n", sw,bFZJS); } return 0; } /****************************************************************************** 函数名称: _protect_gzcl_init 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护故障处理初始化 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_gzcl_init(void) { u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; int oc; // 校验保护启动标志: if(!pR->zqd) { watchdog_reset_cpu(52); } // 校验定值 if(!CheckRunSet()) { watchdog_reset_cpu(53); } // 初始化标志字与时间继电器 for(oc=0;oc<=FA_DLBS;oc++) { TOC_T *poc = &g_tRelay[sw].tOC[oc]; OC_SET *pSet = &pRunSet->tSwSet[sw].toc[oc]; if(!(oc==FA_GL||oc==FA_LX||oc==FA_GL_II))//FA逻辑不清所有标志位 { poc->sta.wfFlag=0; } if(oc != FA_DLBS) // 遮断返回时间需设置长一点,防止故障量跌落太快,闭锁不住 { InitTR(&poc->tQDTime, pSet->dT, PRO_RET_TIME); } else { InitTR(&poc->tQDTime, pSet->dT, T_200ms); } InitTR(&poc->tQD25ms, T_25ms, 0); // 突变量启动时预置定时器,因为突变量启动会死等35个采样点的延时,但实际置的延时只是20ms附近,没有过于精准 if(pR->uBHQD.bFlag.bTBQD) { PreSetTime(&poc->tQDTime, T_10ms+T_5ms); PreSetTime(&poc->tQD25ms, T_10ms); //rt_printf_time("dT = %d\r\n",dTCounter); } #ifdef YX_RESET_TIME if(pRunSet->dT_ZZFG>tRunPara.dTEventRst) { InitTR_Time(&pR->tTZZFG_5S0ms, pRunSet->dT_ZZFG, 0); //无故障延时5s } else { InitTR_Time(&pR->tTZZFG_5S0ms, tRunPara.dTEventRst, 0); //无故障延时5s } #else InitTR_Time(&pR->tTZZFG_5S0ms, pRunSet->dT_ZZFG, 0); //无故障延时5s #endif } // 取得故障启动时刻,以便故障处理流程中,第一次计算的时间片是从故障启动时刻开始 pR->t_rcd_gz = pR->t_rcd_qd; // 提前打开启动继电器,以节省硬件耗用时间 sw_do(sw,SW_DO_FZ,SW_DO_TYPE_SELECT_ON); sw_do(sw,SW_DO_BHT,SW_DO_TYPE_SELECT_ON); // 录波:保护启动 // 20160918:目前策略,启动不录波,动作时再录波 // rcd_start(sw,RECORD_WAVE_TYPE_QD, RECORD_LEN_TZQD); // 进入故障流程:故障处理 if(pR->gz_process == CXLC_BHIN) { pR->gz_process = CXLC_BHCL; } else { watchdog_reset_cpu(54); } // 巡检类保护,逻辑已经判断,如果延时已到达,可在此快速出口 _protect_sw_tz(0); return 0; } /****************************************************************************** 函数名称: _protect_gzcl_process 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护故障处理 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_gzcl_process(void) { // static DWORD dTAfterFault=0; u32 dTGZDelta; // 5ms故障巡检时间片 u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; u32 tmpstep; // 校验流程 if(pR->gz_process != CXLC_BHCL) { watchdog_reset_cpu(55); } // 突变量启动36采样点之后才进入故障处理,否则返回. dTAfterFault = dTCounter - pR->t_rcd_qd; if(dTAfterFault >= 24&&dTAfterFault<36) { #ifdef CPU_FUXI return 0; #else tmpstep=dTCounter; do { dTAfterFault = dTCounter - pR->t_rcd_qd; } while(dTAfterFault < 36); // 等待36点满后,重新计算一下全部的傅式值 sw_cal_protect(); GOC_dir_check(sw,dTCounter-tmpstep); //重新计算一下故障信息 pR->uBHQD.bFlag.bQD25ms = true; #endif } #ifdef CPU_FUXI else if(dTAfterFault>=36) { dTAfterFault=36; pR->uBHQD.bFlag.bQD25ms = true; } #endif // 更新故障处理的时间片 dTGZDelta = dTCounter -pR->t_rcd_gz; pR->t_rcd_gz = dTCounter; // 保护逻辑 if(pR->uBHQD.bFlag.bQD25ms) { #ifdef BH_BSDL_ENBLE Pro_BSTZ(sw,dTGZDelta,BH_DLBS,EV_BSTZ); #endif Pro_OC(sw,dTGZDelta,BH_GL1,EV_GL1TZ); Pro_OC(sw,dTGZDelta,BH_GL2,EV_GL2TZ); Pro_OC(sw,dTGZDelta,BH_GL3,EV_GL3TZ); Pro_LX(sw,dTGZDelta,BH_LX1,EV_LX1TZ); Pro_LX(sw,dTGZDelta,BH_LX2,EV_LX2TZ); #ifdef DISP_SET_LX3 Pro_LX(sw,dTGZDelta,BH_LX3,EV_LX3TZ); #endif Pro_Accheck(sw,dTGZDelta,BH_GLJS,EV_GLJS); Pro_Accheck(sw,dTGZDelta,BH_LXJS,EV_LXJS); // Pro_Accheck(sw,dTGZDelta,FA_GL,EV_FA_GL_TZ); // Pro_Accheck(sw,dTGZDelta,FA_LX,EV_FA_LX_TZ); fag_oc_gl(sw,dTGZDelta); fag_oc_lx(sw,dTGZDelta); fsxGL(sw,dTGZDelta); //反时限过流 } // 保护跳合闸处理 _protect_sw_tz(dTGZDelta); // 保护动作时间统计 if (_protect_check_fault(sw)) { if ((!pR->tbldz) && pR->tblqd) { rt_stat_in(&pR->tbldz_stat, ustimer_get_duration(pR->us_tbl)/USTIMER_US); pR->tbldz = 1; pR->tblqd = 0; } else if ((!pR->fzdz) && pR->fzqd) { rt_stat_in(&pR->fzdz_stat, ustimer_get_duration(pR->us_fz)/USTIMER_US); pR->fzdz = 1; pR->fzqd = 0; } } // 等待保护返回,转入整组复归流程 _protect_zzfg_check(dTGZDelta); return 0; } /****************************************************************************** 函数名称: _protect_gzcl_zzfg 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护故障整组复归检查 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_zzfg_check(u32 dStep) { bool bQD, bQDFH; u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; bool bY1=false; int i; for(i=0;i<=FA_DLBS;i++) { bY1|=(pR->tOC[i].sta.bFlag.bQD||pR->tOC[i].sta.bFlag.bXBbs|| pR->tOC[i].sta.bFlag.bTz||pR->tOC[i].sta.bFlag.bGj); } for(i=0;i<8;i++) { bY1|=pR->tFdl[i].sta.bFlag.bTz; } #ifdef GD_AREA_ZHONGSHAN_2020 bY1|=pR->tgoc.tOc[FAG_GL1].sta.bFlag.bQD // 复归 ||pR->tgoc.tOc[FAG_GL2].sta.bFlag.bQD ||pR->tgoc.tOc[FAG_LX].sta.bFlag.bQD; #endif bY1|=pR->uGLFSX.bFlag.bFXQD; bY1|=pR->tgoc.sta.bFlag.bglQD #if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_MAIN_2020 ||pR->tgoc.sta.bFlag.bgl2QD #endif ||pR->tgoc.sta.bFlag.blxQD ||pR->tgoc.sta.bFlag.bgzglQD ||pR->tgoc.sta.bFlag.bsdQD ||pR->tgoc.sta.bFlag.berrQD ||pR->tgoc.sta.bFlag.bextQD ||pR->tgoc.sta.bFlag.bllQD; // 检查保护是否返回 bQD = (bY1 ||pR->tU0TZ.uZOV.bFlag.bQD // 合后接地保护启动 ||pR->tDYJL.sta.bFlag.bQD ||pR->tPLJL.sta.bFlag.bQD || pR->tXXTZ.uZOV.bFlag.bQD // 选线跳闸 //||pR->tCHZ.sta.bFlag.bQDFG // 重合闸保护启动202004 ||pR->tCHZ.sta.bFlag.bCHQD // 重合闸保护启动 ||pR->tLostVot.uLostVot.bFlag.bQD // 失压分闸保护启动 ||pR->tTQHz.uTQHz.bFlag.bQD // 合环保护启动 ||pR->tTQHz.uTQHz.bFlag.bLock // 合环闭锁启动 ||pR->tOVER_U0TZ.uZOV.bFlag.bTz // 过零序电压跳闸 #ifdef FUN_JDXX || pR->tJD.sta.bFlag.bTz // 接地选线跳 #endif ); // 所有保护返回后,等待5S进入整组复归流程 RunTR(&pR->tTZZFG_5S0ms, !bQD, dStep); bQDFH = pR->tTZZFG_5S0ms.boolTrip; pR->uBHQD.bFlag.bZZFG = bQDFH; if(pR->uBHQD.bFlag.bZZFG && (pR->gz_process == CXLC_BHCL)) { pR->gz_process = CXLC_ZZFG; #ifdef CPU_FUXI dTAfterFault=0; #endif } return 0; } /****************************************************************************** 函数名称: _protect_zzfg 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护整组复归 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_zzfg(void) { u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; int oc; for(oc=0;oc<=FA_DLBS;oc++) { TOC_T *poc=&pR->tOC[oc];// 过流保护相关 poc->sta.wfFlag=0; ResetTR(&poc->tQDTime); ResetTR(&poc->tQD25ms); ResetTR(&poc->tFz25ms); #ifdef YX_RESET_TIME ResetTR(&poc->tGjEvRstTime); ResetTR(&poc->tTzEvRstTime); #endif } ResetTR(&pR->tgoc.tglFz25ms); ResetTR(&pR->tgoc.tlxFz25ms); // 重合闸标志复归,定时器复归 if(soe_check(EV_GOOSE_QC_QD+sw*EV_SW_NUM)==true) // 故障隔离启动 { soe_record_ev( EV_GOOSE_QC_QD+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_QC_FAIL+sw*EV_SW_NUM)==true) // 故障切除失败 { soe_record_ev( EV_GOOSE_QC_FAIL+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_QC_OK+sw*EV_SW_NUM)==true) // 故障切除成功 { soe_record_ev( EV_GOOSE_QC_OK+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_GL_QD+sw*EV_SW_NUM)==true) // 故障隔离启动 { soe_record_ev( EV_GOOSE_GL_QD+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_GL_FAIL+sw*EV_SW_NUM)==true) // 故障隔离失败 { soe_record_ev( EV_GOOSE_GL_FAIL+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_GL_OK+sw*EV_SW_NUM)==true) // 故障隔离成功 { soe_record_ev( EV_GOOSE_GL_OK+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_HZ_OK+sw*EV_SW_NUM)==true) // 故障切除成功 { soe_record_ev( EV_GOOSE_HZ_OK+sw*EV_SW_NUM,0, 0,0,0 ); } if(soe_check(EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM)==true) // 故障切除成功 { soe_record_ev( EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM,0, 0,0,0 ); } //if(soe_check(EV_GOOSE_LL_UNOK+sw*EV_SW_NUM)==true) // 自转电条件不满足返回 //{ // soe_record_ev( EV_GOOSE_LL_UNOK+sw*EV_SW_NUM,1, 0,0,0 ); //} //202004 //pR->tCHZ.sta.wfFlag=0; //pR->tCHZ.wAR_ActTimes=0; //ResetTR(&pR->tCHZ.tTCHJD_HJS); // 失压分闸标志复归,定时器复归 if(pR->tLostVot.uLostVot.bFlag.bTz) pR->tLostVot.uLostVot.wfFlag = 0; //只出口后才清标志 //ResetTR(&pR->tLostVot.tLostVotTime); //Z计时器禁止复归 // 合环标志复归,定时器复归 pR->tTQHz.uTQHz.wfFlag = 0; // 跳闸失败标志复归,定时器复归 ResetTR(&pR->tTripfail_2s); pR->uBHDZ.bFlag.bTZSB = 0; // 启动标志复归 pR->uBHQD.dfBHQDLogic = 0; // 整组复归定时器复归 ResetTR(&pR->tTZZFG_5S0ms); // 保护总启动标志复归 pR->zqd = 0; // 复归保护启动标志后,再复归启动继电器 // 如果有就地或远方的分、合闸操作,在继电器出口处会强制打开启动继电器 sw_do(sw,SW_DO_FZ,SW_DO_TYPE_SELECT_OFF); sw_do(sw,SW_DO_BHT,SW_DO_TYPE_SELECT_OFF); // 流程处理 if(pR->gz_process == CXLC_ZZFG) { pR->gz_process = CXLC_ZCCL; } else { watchdog_reset_cpu(57); } pR->tblqd = 0; pR->tbldz = 0; pR->tblzzdz = 0; pR->fzqd = 0; pR->fzdz = 0; pR->fzzzdz = 0; rt_printf_time("开关%d整组复归\r\n", sw); return 0; } /****************************************************************************** 函数名称: _protect_sw_tz 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护跳闸 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_sw_tz(u32 dStep) { bool bCur; bool bTz=false; u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; int i; #ifdef BH_BSDL_ENBLE u8 bh_bs = g_tRelay[sw].tOC[BH_DLBS].sta.bFlag.bQD; #endif #ifdef FUNC_DRIVE if(!gb_drive.b_drive_on) #endif { // 校验流程 if(pR->gz_process != CXLC_BHCL) { watchdog_reset_cpu(56); } } // 保护动作跳闸情况检测 for(i=BH_GL1;i<=FA_LX;i++) { bTz|=pR->tOC[i].sta.bFlag.bTz; } #ifdef GD_AREA_ZHONGSHAN_2020 for(i=FAG_GL1;i<=FAG_LX;i++) { bTz|=pR->tgoc.tOc[i].sta.bFlag.bTz; //跳闸 } #endif for(i=0;i<8;i++) { bTz|=pR->tFdl[i].sta.bFlag.bTz; if(pR->tFdl[i].sta.bFlag.bTz) pR->tCHZ.sta.bFlag.bCDWC = false; //重合闸放电 } bTz|=pR->uGLFSX.bFlag.bFXDZ; bTz|= (pR->tU0TZ.uZOV.bFlag.bTz // 合后接地保护动作 ||pR->tDYJL.sta.bFlag.bTz ||pR->tPLJL.sta.bFlag.bTz ||pR->tOVER_U0TZ.uZOV.bFlag.bTz // 过零序电压跳闸 ||pR->tLostVot.uLostVot.bFlag.bTz //失压分闸 #ifdef FUN_JDXX || pR->tJD.sta.bFlag.bTz // 接地选线跳 #endif ); #ifdef FUNC_DRIVE if(gb_drive.b_drive_on && pR->tSWST.uSWST.bFlag.bDIHW && gb_drive.b_fa_drive) { RunTR(&gb_drive.tQDTime_fz,true,dStep); } else { ResetTR(&gb_drive.tQDTime_fz); } #endif // 无分闸闭锁 #ifdef BH_BSDL_ENBLE pR->uBHDZ.bFlag.bBHTrip = bTz && (!pR->bBSTZ) && !bh_bs; #else pR->uBHDZ.bFlag.bBHTrip = bTz && (!pR->bBSTZ); #endif // 跳闸脉冲最短保持40ms RunTR(&pR->tTrip_BHT40MS, pR->uBHDZ.bFlag.bBHTrip, dStep); pR->uBHDZ.bFlag.bBHT = pR->tTrip_BHT40MS.boolTrip || pR->uBHDZ.bFlag.bBHTrip; #ifdef SELF_OPEN_RELEASE // 保护跳保持继电器 默认保持200ms,用于更准确的区分是保护跳 RunTR(&pR->tTripBHTKeep, pR->uBHDZ.bFlag.bBHT, dStep); pR->uBHDZ.bFlag.bBHTKeep = pR->tTripBHTKeep.boolTrip || pR->uBHDZ.bFlag.bBHT; #endif // 跳闸失败检查: 跳闸后持续2S有流或合位 bCur = ((!pR->tSWST.uSWST.bFlag.bSXWL) || pR->tSWST.uSWST.bFlag.bHZWZ); RunTR(&pR->tTripfail_hz, pR->uBHDZ.bFlag.bBHT, dStep); //跳闸失败,不与跳闸脉冲关联,防止失压分闸,跳闸脉冲较短,无法判位置 RunTR(&pR->tTripfail_2s, (pR->tTripfail_hz.boolTrip&&bCur), dStep); //跳闸失败,不与跳闸脉冲关联,防止失压分闸,跳闸脉冲较短,无法判位置 if (pR->tTripfail_2s.boolTrip) { pR->uBHDZ.bFlag.bTZSB = 1; } else { pR->uBHDZ.bFlag.bTZSB = 0; } // 有跳闸信号时,可由大电流闭锁不动作, // 无闭锁时,需保证一次动作信号仅一次出口 #ifdef FUNC_DRIVE if(!bTz) {//避免传动延时分闸时间设为0时无法分闸出口 pR->uBHDZ.bFlag.bTZOut = 0; } if(bTz || gb_drive.tQDTime_fz.boolTrip) #else if(bTz) #endif { if ((!pR->uBHDZ.bFlag.bTZOut) && (!pR->bBSTZ) && KZ_OUT_ALL_EN(sw) && g_run_stu.kz_out_tt) { sw_do(sw,SW_DO_HZ,SW_DO_TYPE_OFF); sw_do(sw,SW_DO_BHH,SW_DO_TYPE_OFF); sw_do(sw,SW_DO_YKH,SW_DO_TYPE_OFF); sw_do(sw,SW_DO_BHDZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_FZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_BHT,SW_DO_TYPE_ON); #ifdef CUSTOMIZE_BZT //备自投 bzt_oc_sw_off(sw); #endif #ifdef FUNC_DRIVE if(gb_drive.tQDTime_fz.boolTrip) { pR->uBHDZ.bFlag.bTZOut = 0; //传动结束后应返回原正常逻辑,不应影响原功能运行 ResetTR(&gb_drive.tQDTime_fz); } else #endif { pR->uBHDZ.bFlag.bTZOut = 1; } tRunPara.sysData.wSwTzCount++; rt_printf("开关%d保护跳闸\r\n", sw); } } else { pR->uBHDZ.bFlag.bTZOut = 0; } return 0; } /****************************************************************************** 函数名称: _protect_sw_hz 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-05-13 函数说明: 保护合闸 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_sw_hz(u32 dStep) { bool bHz=false; int sw=g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; // 保护动作合闸情况检测 bHz =(pR->tCHZ.sta.bFlag.bHz // 重合闸 || pR->tSDHZ.uSdhz_S.bFlag.bHz // 分段开关上电合闸 || pR->tSDHZ.uSdhz_L.bFlag.bHz); // 联络开关上电合闸 #ifdef FUNC_DRIVE if(gb_drive.b_drive_on && pR->tSWST.uSWST.bFlag.bDITW && gb_drive.b_fa_drive) { RunTR(&gb_drive.tQDTime_hz,true,dStep); } else { ResetTR(&gb_drive.tQDTime_hz); } #endif pR->uBHDZ.bFlag.bBHH=bHz; // 有合闸信号时,需保证一次动作信号仅一次出口 #ifdef FUNC_DRIVE if(!bHz) {//避免传动延时分闸时间设为0时无法分闸出口 pR->uBHDZ.bFlag.bHZOut = 0; } if(bHz || gb_drive.tQDTime_hz.boolTrip) #else if(bHz) #endif { if (!pR->uBHDZ.bFlag.bHZOut && !pR->bBSHZ && KZ_OUT_ALL_EN(sw)) { sw_do(sw,SW_DO_HZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_BHH,SW_DO_TYPE_ON); #ifdef FUNC_DRIVE if(gb_drive.b_drive_on) { gb_drive.b_drive_on = false; ResetTR(&gb_drive.tQDTime_hz); } #endif pR->uBHDZ.bFlag.bHZOut = 1; tRunPara.sysData.wSwHzCount++; //rt_printf("开关%d保护合闸\r\n", sw); } } else { pR->uBHDZ.bFlag.bHZOut = 0; } return 0; } void sw_op_fail(DWORD dStep) { int sw=g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; TSDHZ_T *pSW =&pR->tSDHZ; #ifdef CUSTOMIZE_BZT //备自投 UBZT *uBZT = &pR->tBzt.uBZT; #endif #if defined GD_AREA_MAIN_2020 || defined SW_FAIL_SINGLE_OUT //开关拒动发送失灵信号 static int status=0; #endif //分闸失败检查 RunTR(&pSW->tTz0ms2s, pR->uRmtSW.bTz_Doing, dStep); if(pSW->tTz0ms2s.boolTrip && (pR->run_stu.sw==2)) { if(soe_check(EV_TZFAIL+sw*EV_SW_NUM)==false) soe_record_ev(EV_TZFAIL+sw*EV_SW_NUM, 1, 0,0,0 ); if(soe_check(EV_SWFAIL+sw*EV_SW_NUM)==false) soe_record_ev(EV_SWFAIL+sw*EV_SW_NUM, 1, 0,0,0 ); #ifdef FUNC_DRIVE if(gb_drive.b_drive_soe) { if(soe_check(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM)==false) { soe_record_ev(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM, 1, 0,0,0 ); } gb_drive.b_drive_on = false; gb_drive.b_drive_soe = false; } #endif pR->uRmtSW.bTz_Doing = 0; #ifdef CUSTOMIZE_BZT //备自投 if(uBZT->bBZT.bZF && uBZT->bBZT.bSYFZ) { uBZT->bBZT.bSYFZ = 0; pR->tSWST.uSWST.bFlag.bBZTSY = 0; } #endif ResetTR(&pSW->tTz0ms2s); #ifdef FUNC_DRIVE_JY if(gb_drive.b_drive_on) { gb_drive.b_drive_on = false; if(soe_check(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM)==false) //不停电传动开关拒分 { soe_record_ev(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM, 1, 0,0,0 ); } if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==false) //传动结束 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 1, 0,0,0 ); } if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==true) //传动结束返回 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 0, 0,0,0 ); } } gb_drive.b_drive_success = false; #endif } #ifdef SOE_RECORD_DELAY //分闸动作check if(soe_check(EV_TZFAIL+sw*EV_SW_NUM)==true)//分闸拒动:清空延时SOE QUEUE { if(g_soe_queue.fzsoe_wait_flag) memset((char *)&g_soe_queue.delay_fzsoe_tab,0,sizeof(DELAY_SOE_DATA)*DELAY_SOE_MAX);//clear delay_fzsoe_tab[] buffer g_soe_queue.fzsoe_wait_flag = false; g_soe_queue.fzsoe_delay_flag = false; g_soe_queue.delay_fzsoe_count = 0; } else if(g_soe_queue.fzsoe_wait_flag && (pR->run_stu.sw==1))//启动转录: 分闸SOE QUEUE非空 && 分位(分闸成功) { int i; g_soe_queue.fzsoe_delay_flag = true; g_soe_queue.fzsoe_wait_flag = false; for(i=0;itHz0ms2s, pR->uRmtSW.bHz_Doing, dStep); if(pSW->tHz0ms2s.boolTrip && (pR->run_stu.sw==1)) { if(soe_check(EV_HZFAIL+sw*EV_SW_NUM)==false) soe_record_ev(EV_HZFAIL+sw*EV_SW_NUM, 1, 0,0,0 ); if(soe_check(EV_SWFAIL+sw*EV_SW_NUM)==false) soe_record_ev(EV_SWFAIL+sw*EV_SW_NUM, 1, 0,0,0 ); #ifdef FUNC_DRIVE if(gb_drive.b_drive_soe) { if(soe_check(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM)==false) { soe_record_ev(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM, 1, 0,0,0 ); } gb_drive.b_drive_on = false; gb_drive.b_drive_soe = false; } #endif #ifdef FUNC_DRIVE_JY if(gb_drive.b_drive_on || gb_drive.b_drive_success_again) { if(soe_check(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM)==false) //不停电传动开关拒合 { soe_record_ev(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM, 1, 0,0,0 ); } if(gb_drive.b_drive_success_again) { if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==false) //传动结束 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 1, 0,0,0 ); } if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==true) //传动结束返回 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 0, 0,0,0 ); } } gb_drive.b_drive_success_again = false; gb_drive.b_drive_on = false; } gb_drive.b_drive_success = false; #endif if(pSW->uSdhz_L.bFlag.bX_HZEvent) { #ifndef GD_AREA_ZHONGSHAN_2020 //中山2020不报分布式恢复失败SOE if(soe_check(EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM)==false) soe_record_ev(EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM, 1, 0,0,0 ); #endif } pSW->uSdhz_L.bFlag.bX_HZEvent = false; pR->uRmtSW.bHz_Doing = 0; ResetTR(&pSW->tHz0ms2s); } #ifdef SOE_RECORD_DELAY //合闸动作check if(soe_check(EV_HZFAIL+sw*EV_SW_NUM)==true)//合闸拒动:清空延时SOE QUEUE { if(g_soe_queue.hzsoe_wait_flag) memset((char *)&g_soe_queue.delay_hzsoe_tab,0,sizeof(DELAY_SOE_DATA)*DELAY_SOE_MAX);//clear delay_hzsoe_tab[] buffer g_soe_queue.hzsoe_wait_flag = false; g_soe_queue.hzsoe_delay_flag = false; g_soe_queue.delay_hzsoe_count = 0; } else if(g_soe_queue.hzsoe_wait_flag && (pR->run_stu.sw==2))//启动转录: 合闸SOE QUEUE非空 && 合位(合闸成功) { int i; g_soe_queue.hzsoe_delay_flag = true;//转录标志 g_soe_queue.hzsoe_wait_flag = false; for(i=0;irun_stu.hw_change = (pR->run_stu.sw==1) ? true : false || pR->run_stu.hw_change; if(pR->run_stu.hw_change && ((pR->run_stu.sw==2)?true:false)) // 开关由分到合 { pR->uRmtSW.bHz_Doing = false; pR->run_stu.hw_change = false; if(soe_check(EV_HZFAIL+sw*EV_SW_NUM)==true) soe_record_ev(EV_HZFAIL+sw*EV_SW_NUM, 0, 0,0,0 ); if(soe_check(EV_SWFAIL+sw*EV_SW_NUM)==true) soe_record_ev(EV_SWFAIL+sw*EV_SW_NUM, 0, 0,0,0 ); if(soe_check(EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM)==true) soe_record_ev( EV_GOOSE_HZ_FAIL+sw*EV_SW_NUM,0, 0,0,0 ); #ifdef FUNC_DRIVE if(soe_check(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM)==true) { soe_record_ev(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM, 0, 0,0,0 ); } #endif #ifdef FUNC_DRIVE_JY if(gb_drive.b_drive_on_check) { gb_drive.b_drive_on_check = false; } if(soe_check(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM)==true) //不停电传动开关拒合返回 { soe_record_ev(EV_DRIVE_HZ_FAIL+sw*EV_SW_NUM, 0, 0,0,0 ); } if(gb_drive.b_drive_success || gb_drive.b_drive_success_again) { if(BH_ALL_EN(sw)) { gb_drive.b_drive_on = false; } if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==false) //传动结束 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 1, 0,0,0 ); } if(soe_check(EV_DRIVE_END+sw*EV_SW_NUM)==true) //传动结束返回 { soe_record_ev(EV_DRIVE_END+sw*EV_SW_NUM, 0, 0,0,0 ); } if(soe_check(EV_DRIVE_SUCESS+sw*EV_SW_NUM)==false) //不停电传动成功 { soe_record_ev(EV_DRIVE_SUCESS+sw*EV_SW_NUM, 1, 0,0,0 ); } if(soe_check(EV_DRIVE_SUCESS+sw*EV_SW_NUM)==true) //不停电传动成功返回 { soe_record_ev(EV_DRIVE_SUCESS+sw*EV_SW_NUM, 0, 0,0,0 ); } gb_drive.b_drive_success = false; gb_drive.b_drive_success_again = false; } #endif #ifdef SELF_OPEN_RELEASE pR->uRmtSW.bSwTz = false; #endif #ifdef CUSTOMIZE_BZT //备自投 if(uBZT->bBZT.bZF && uBZT->bBZT.bSYFZ) { uBZT->bBZT.bSYFZ = 0; pR->tSWST.uSWST.bFlag.bBZTSY = 0; } #endif } //跳闸失败返回 pR->run_stu.tw_change = (pR->run_stu.sw==2) ? true : false || pR->run_stu.tw_change; if(pR->run_stu.tw_change && ((pR->run_stu.sw==1)?true:false)) // 开关由合到分 { #ifdef SELF_OPEN_RELEASE if(!pR->uBHDZ.bFlag.bBHTKeep) { pR->uRmtSW.bSwTz = true; //开关拉杆分闸 } #endif pR->uRmtSW.bTz_Doing = false; pR->run_stu.tw_change = false; if(soe_check(EV_TZFAIL+sw*EV_SW_NUM)==true) soe_record_ev(EV_TZFAIL+sw*EV_SW_NUM, 0, 0,0,0 ); if(soe_check(EV_SWFAIL+sw*EV_SW_NUM)==true) soe_record_ev(EV_SWFAIL+sw*EV_SW_NUM, 0, 0,0,0 ); #ifdef FUNC_DRIVE if(soe_check(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM)==true) { soe_record_ev(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM, 0, 0,0,0 ); } #endif #ifdef CUSTOMIZE_BZT //备自投 if(uBZT->bBZT.bZF && uBZT->bBZT.bSYFZ) { if((g_sw[sw].do_cfg_index[SW_DO_JX1_SY] < g_equ_config->do_num) && (g_sw[sw].do_cfg_index[SW_DO_JX2_SY] == 0xffff)) { sw_do(sw,SW_DO_JX1_SY,SW_DO_TYPE_ON); } /*else if((g_sw[sw].do_cfg_index[SW_DO_JX2_SY] < g_equ_config->do_num) && (g_sw[sw].do_cfg_index[SW_DO_JX1_SY] == 0xffff)) { sw_do(sw,SW_DO_JX2_SY,SW_DO_TYPE_ON); }*/ uBZT->bBZT.bSYFZ = 0; pR->tSWST.uSWST.bFlag.bBZTSY = 0; } #endif #ifdef FUNC_DRIVE_JY if(soe_check(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM)==true) //不停电传动开关拒分返回 { soe_record_ev(EV_DRIVE_TZ_FAIL+sw*EV_SW_NUM, 0, 0,0,0 ); } #endif } #if defined GD_AREA_MAIN_2020 || defined SW_FAIL_SINGLE_OUT //开关拒动发送失灵信号 if(soe_check(EV_SWFAIL+sw*EV_SW_NUM)==true) { sw_do(sw,SW_DO_UNSTUCK_SINGLE,SW_DO_TYPE_ON); if(status==0) { status=1; //输出空接点 //rt_printf("开关拒动失灵信号发送开始\r\n"); } } else if((soe_check(EV_SWFAIL+sw*EV_SW_NUM)==false)&&(status==1)) { sw_do(sw,SW_DO_UNSTUCK_SINGLE,SW_DO_TYPE_OFF); status=0; //不输出空接点 //rt_printf("开关拒动失灵信号发送结束\r\n"); } #endif #ifdef FUNC_DRIVE RunTR(&gb_drive.tQDTime_fz_end, (gb_drive.bTz_Doing && gb_drive.b_drive_process), dStep); if(gb_drive.tQDTime_fz_end.boolTrip) { gb_drive.bTz_Doing = 0; } RunTR(&gb_drive.tQDTime_hz_end, (gb_drive.bHz_Doing && gb_drive.b_drive_process), dStep); if(gb_drive.tQDTime_hz_end.boolTrip) { gb_drive.bHz_Doing = 0; } //分/合闸后延时结束传动 if(gb_drive.tQDTime_fz_end.boolTrip || gb_drive.tQDTime_hz_end.boolTrip) { gb_drive.b_drive_on = false; gb_drive.b_drive_process = false; gb_drive.bQuit = true; ResetTR(&gb_drive.tQDTime_fz_end); ResetTR(&gb_drive.tQDTime_hz_end); if(soe_check(EV_DRIVE_BEGIN+sw*EV_SW_NUM)==true) { soe_record_ev(EV_DRIVE_BEGIN+sw*EV_SW_NUM, 0, 0,0,0 ); } } #endif } /****************************************************************************** 函数名称: _alarm_process 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 异常告警类逻辑 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_alarm(void) { u32 sw = g_protect.sw; TRELAY_T *pR=&g_tRelay[sw]; TSWST *pSW = &pR->tSWST; // 弹簧未储能告警 if (pSW->uSWST.bFlag.bWCN) { if(soe_check(EV_TH_WCN+sw*EV_SW_NUM)==false) { soe_record_ev(EV_TH_WCN+sw*EV_SW_NUM, 1, 0,0,0 ); } } else { if(soe_check(EV_TH_WCN+sw*EV_SW_NUM)==true) { soe_record_ev(EV_TH_WCN+sw*EV_SW_NUM, 0, 0,0,0 ); } } if (pSW->uSWST.bFlag.bKZHL) { if(soe_check(EV_KZHL+sw*EV_SW_NUM)==false) { soe_record_ev(EV_KZHL+sw*EV_SW_NUM, 1, 0,0,0 ); } } else { if(soe_check(EV_KZHL+sw*EV_SW_NUM)==true) { soe_record_ev(EV_KZHL+sw*EV_SW_NUM, 0, 0,0,0 ); } } // 跳位有流告警 if (pSW->uSWST.bFlag.bTWYL && KZ_OUT_ALL_EN(sw)) { if(soe_check(EV_TWYL+sw*EV_SW_NUM)==false) { soe_record_ev(EV_TWYL+sw*EV_SW_NUM, 1, 0,0,0 ); } } else { if(soe_check(EV_TWYL+sw*EV_SW_NUM)==true) { soe_record_ev(EV_TWYL+sw*EV_SW_NUM, 0, 0,0,0 ); } } // 跳闸失败 if (pR->uBHDZ.bFlag.bTZSB && KZ_OUT_ALL_EN(sw)) { if(soe_check(EV_TZFAIL+sw*EV_SW_NUM)==false) { soe_record_ev(EV_TZFAIL+sw*EV_SW_NUM, 1, 0,0,0 ); } } else { if(soe_check(EV_TZFAIL+sw*EV_SW_NUM)==true) { soe_record_ev(EV_TZFAIL+sw*EV_SW_NUM, 0, 0,0,0 ); } } return 0; } /************************************************************************** 函数名称:_protect_rmt_sw 函数版本:1.00 作者: mwd 创建日期:2007.9.29 函数功能说明:开关遥控:遥控器、PDA 输入参数: 输出参数: 返回值: 函数扇入清单: 日志: ***************************************************************************/ static int _protect_rmt_sw(u32 dStep) { u32 sw = g_protect.sw; URMTSW *pRmtsw=&g_tRelay[sw].uRmtSW; RUN_STU_SW *pRunstu=&g_tRelay[sw].run_stu; TRELAY_T *pR=&g_tRelay[sw]; u8 Ycn= !(pR->run_stu.wcn && pRunSet->tSwSet[sw].bTT_WCN);//已储能 RunTR(&pR->tMb_yuk_time, g_run_stu.mb_yuk, dStep);//预置按键取消 if(pR->tMb_yuk_time.boolTrip) g_run_stu.mb_yuk=0; if (((((g_rmt_op.cmd == CMD_HZ)||pRunstu->sw_sh||g_run_stu.mb_hz) && (!g_run_stu.yf) && Ycn) || g_tPDA.bPDAHz || g_tPDA.bMsgHz)&&(!fa_bs_hz(sw))) //有手合信号 { #ifdef TQ_SOFT_YB if(pRunSet->tSwSet[sw].bTT_TQ && pRunstu->bTQ && pRunstu->safe_auto && !pRunstu->tytq &&pRunSet->bTT_TQ_YB ) #else if(pRunSet->tSwSet[sw].bTT_TQ && pRunstu->bTQ && pRunstu->safe_auto) #endif { pRmtsw->bTQHz=true; } else if(!pRmtsw->bHandHz) { pRmtsw->bHandHz = true; pRmtsw->bHandHz_fa = true; #ifdef CUSTOMIZE_BZT //备自投 BZT_ManualOnOffHandle(sw, SW_DO_FD_HZ); #endif sw_do(sw,SW_DO_HZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_YKH,SW_DO_TYPE_ON); if(g_rmt_op.cmd == CMD_HZ) { soe_record_opt(EV_433M_HZ, 1); } else if (pRunstu->sw_sh) { soe_record_opt(EV_HAND_HZ, 1); } else if (g_run_stu.mb_hz) { soe_record_ev(EV_MB_HZ, 1, 0,0,0 ); g_run_stu.mb_hz=0; } else if(g_tPDA.bPDAHz) { soe_record_opt(EV_PDA_HZ, 1); } else { soe_record_opt(EV_MSG_HZ, 1); } } //pRmtsw->bTQHz=false; //手合将同期合闸标志清零?? g_tPDA.bPDAHz=false; g_tPDA.bMsgHz=false; g_rmt_op.cmd = CMD_NILL; } #if 0//科陆东自V1&V2版本临时测试用, 佛山局用的永磁模块未储能时无法带动继电器,我司用开出5模拟一个该信号 if(pRunstu->wcn) { sw_do(sw,SW_RST_SY,SW_DO_TYPE_ON); sw_do(sw,SW_RST_SY1,SW_DO_TYPE_OFF); } else { sw_do(sw,SW_RST_SY1,SW_DO_TYPE_ON); sw_do(sw,SW_RST_SY,SW_DO_TYPE_OFF); } #else //v3版本储能信号开出 if(pRunstu->wcn) { sw_do(sw,SW_DO_CN,SW_DO_TYPE_OFF); } else { sw_do(sw,SW_DO_CN,SW_DO_TYPE_ON); } //rt_printf("pRunstu->wcn=%d \r\n",pRunstu->wcn); #endif #ifdef GD_AREA_YUNAN_LP//交流失电开出 //sw_do(sw,SW_DO_LOST_AC,SW_DO_TYPE_SELECT_ON); sw_do(sw,SW_DO_LOST_AC,SW_DO_TYPE_ON); #endif if (((((g_rmt_op.cmd == CMD_FZ)||pRunstu->sw_sf||g_run_stu.mb_fz) && (!g_run_stu.yf)) || g_tPDA.bPDATz || g_tPDA.bMsgTz)&&(!pR->bBSTZ)) //有手跳信号 { if(!pRmtsw->bHandTz) { pRmtsw->bHandTz = true; pRmtsw->bHandTz_fa = true; sw_do(sw,SW_DO_HZ,SW_DO_TYPE_OFF); sw_do(sw,SW_DO_BHH,SW_DO_TYPE_OFF); #ifdef CUSTOMIZE_BZT //备自投 sw_do(sw,SW_DO_FD_FZ,SW_DO_TYPE_ON); #endif sw_do(sw,SW_DO_BHDZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_FZ,SW_DO_TYPE_ON); sw_do(sw,SW_DO_YKT,SW_DO_TYPE_ON); if(g_rmt_op.cmd == CMD_FZ) { soe_record_opt(EV_433M_TZ,1); } else if (pRunstu->sw_sf) { soe_record_opt(EV_HAND_TZ, 1); } else if (g_run_stu.mb_fz) { soe_record_ev(EV_MB_TZ, 1, 0,0,0 ); g_run_stu.mb_fz=0; } else if(g_tPDA.bPDATz) { soe_record_opt(EV_PDA_TZ,1); } else { soe_record_opt(EV_MSG_TZ,1); } } g_tPDA.bPDATz=false; g_tPDA.bMsgTz=false; g_rmt_op.cmd = CMD_NILL; } //手持遥控复归 C 信号复归 if(g_rmt_op.cmd == CMD_FG) { SignalReset(0,false); g_rmt_op.cmd = CMD_NILL; rt_printf("遥控器复归信号产生\r\n"); } return 0; } /****************************************************************************** 函数名称: _protect_sfsh_clr 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 清除手分、手合标志 参数说明: 无 返回值: 成功返回0. 修改记录: */ static int _protect_sfsh_clr(void) { URMTSW *pRmtsw=&g_tRelay[g_protect.sw].uRmtSW; pRmtsw->bHandHz = false; pRmtsw->bHandTz = false; return 0; } /****************************************************************************** 函数名称: _protect_check_fault 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 检查保护是否返回 参数说明: 无 返回值: 成功返回0. 修改记录: */ static bool _protect_check_fault(int sw) { int i; TRELAY_T *pR=&g_tRelay[sw]; bool bY1=false; for(i=BH_GL1;i<=FA_LX;i++) { bY1|=(pR->tOC[i].sta.bFlag.bTz||pR->tOC[i].sta.bFlag.bGj); } for(i=0;i<8;i++) { bY1|=pR->tFdl[i].sta.bFlag.bTz; } bY1|=pR->tgoc.sta.bFlag.bglTz #if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_MAIN_2020 ||pR->tgoc.sta.bFlag.bgl2Tz #endif ||pR->tgoc.sta.bFlag.blxTz ||pR->tgoc.sta.bFlag.bgzglTz ||pR->tgoc.sta.bFlag.bsdTz ||pR->tgoc.sta.bFlag.bextTz ||pR->tgoc.sta.bFlag.berrTz ||pR->tgoc.sta.bFlag.bllhz; bY1|=pR->uGLFSX.bFlag.bFXDZ; bY1|= (pR->tCHZ.sta.bFlag.bHz ||pR->tXXTZ.uZOV.bFlag.bTz || pR->tU0TZ.uZOV.bFlag.bTz || pR->tDYJL.sta.bFlag.bTz || pR->tPLJL.sta.bFlag.bTz || pR->tLostVot.uLostVot.bFlag.bTz ||pR->tOVER_U0TZ.uZOV.bFlag.bTz // 过零序电压跳闸 #ifdef FUN_JDXX || pR->tJD.sta.bFlag.bTz // 接地选线跳 #endif ); if(bY1) { return true; } return false; } /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ int protect_stat_reset(void) { int sw; for(sw=0; swtbl_stat,"突变量"); rt_stat_init(&pR->tbldz_stat,"突变量动作"); rt_stat_init(&pR->tblzzdz_stat,"突变量整组动作"); rt_stat_init(&pR->fz_stat,"幅值"); rt_stat_init(&pR->fzdz_stat,"幅值动作"); rt_stat_init(&pR->fzzzdz_stat,"幅值整组动作"); } return 0; } int protect_printf_process(void) { int sw; rt_printf("[突变量启动耗时(us):]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swtbl_stat); } rt_printf("\r\n[突变量动作耗时(us):]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swtbldz_stat); } rt_printf("\r\n[突变量整组动作耗时(us):]\r\n"); rt_printf("[需用分闸继电器输入分位开入,防抖为0s]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swtblzzdz_stat); } rt_printf("\r\n[幅值启动耗时(us):]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swfz_stat); } rt_printf("\r\n[幅值动作耗时(us):]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swfzdz_stat); } rt_printf("\r\n[幅值整组动作耗时(us):]\r\n"); rt_printf("[需用分闸继电器输入分位开入,防抖为0s]\r\n"); rt_printf("sw\tname\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for (sw=0; swfzzzdz_stat); } return 0; } #ifdef YB_AUTO_SELECT bool fa_yb_enable(int sw) { bool bY1=false; if ((short)g_sw[sw].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID ) { bY1=g_tRelay[sw].run_stu.fatt&&pRunSet->bTT_SOFT_FA_YB; // FA } else { bY1=pRunSet->bTT_SOFT_FA_YB; // FA } return bY1; } bool goose_yb_enable(int sw) { bool bY1=false; if ((short)g_sw[sw].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) { bY1=g_tRelay[sw].run_stu.fa_g_tt&&pRunSet->bTT_SOFT_GOOSE_YB; // 智能分布式把手 } else { bY1=pRunSet->bTT_SOFT_GOOSE_YB; } return bY1; } bool bh_yb_enable(int sw) { bool bY1=false; if ((short)g_sw[sw].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) { bY1=g_tRelay[sw].run_stu.bhtt&&pRunSet->bTT_SOFT_BH_YB; // 保护 } else { bY1=pRunSet->bTT_SOFT_BH_YB; // 保护 } return bY1; } #endif //#ifdef GD_AREA_ZHONGSHAN_2020 //中山要求通信异常,全系统均异常 #if defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_MAIN_2020 || defined YB_AUTO_SELECT bool fa_fun_true(int sw) { bool bY1=false,bY2=false,bY3=false; #ifdef YB_AUTO_SELECT if ((short)g_sw[sw].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) { bY1=g_tRelay[sw].run_stu.fa_g_tt&&pRunSet->bTT_SOFT_GOOSE_YB; // 智能分布式把手 } else { bY1=pRunSet->bTT_SOFT_GOOSE_YB; } if ((short)g_sw[sw].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) { bY2=g_tRelay[sw].run_stu.bhtt&&pRunSet->bTT_SOFT_BH_YB; // 保护 } else { bY2=pRunSet->bTT_SOFT_BH_YB; // 保护 } if ((short)g_sw[sw].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID ) { bY3=g_tRelay[sw].run_stu.fatt&&pRunSet->bTT_SOFT_FA_YB; // FA } else { bY3=pRunSet->bTT_SOFT_FA_YB; // FA } #elif defined GD_AREA_MAIN_2020 bY1=g_tRelay[sw].run_stu.fa_g_tt&&pRunSet->bTT_SOFT_GOOSE_YB; // 智能分布式把手 bY2=g_tRelay[sw].run_stu.bhtt&&pRunSet->bTT_SOFT_BH_YB; // 保护 bY3=g_tRelay[sw].run_stu.fatt&&pRunSet->bTT_SOFT_FA_YB; // FA #else bY1=g_tRelay[sw].run_stu.fa_g_tt&&pRunSet->bTT_SOFT_GOOSE_YB // 智能分布式把手 &&((pRunSet->tSwSet[sw].tGocSet.bsw_fz&&pRunSet->bTT_SOFT_BH_YB&&!pRunSet->bTT_SOFT_FA_YB) ||(!pRunSet->tSwSet[sw].tGocSet.bsw_fz&&pRunSet->bTT_SOFT_FA_YB&&!pRunSet->bTT_SOFT_BH_YB)); bY2=g_tRelay[sw].run_stu.bhtt&&pRunSet->bTT_SOFT_BH_YB // 保护 &&(!pRunSet->bTT_SOFT_FA_YB&&!pRunSet->bTT_SOFT_GOOSE_YB); bY3=g_tRelay[sw].run_stu.fatt&&pRunSet->bTT_SOFT_FA_YB // FA &&(!pRunSet->bTT_SOFT_BH_YB&&!pRunSet->bTT_SOFT_GOOSE_YB); #endif return (bY1||bY2||bY3); } #endif /*------------------------------ 文件结束 ------------------------------------- */