📄 epm.c
字号:
#include "sys_parameter.h"
byte data Timer0_Count = 0;
bit overload_ind=0;
unsigned char data real_pulse_count = 0;
/*
* overload counter,6 minutes or 360 seconds polling
* 10 --- 1.0 kW 4.5A
* 20 --- 2.0 kW 9A
* 40 --- 4.0 kW 18A
* 80 --- 8.0 kW 36A
* 120 --- 12 kW 54A
*/
byte overload_counter[4];
byte epm_state[2];
byte data pulse_counter;
/* pulse received, set to 1 when poweron */
bit degree_ind = 1;
/*在中断里驱动用bit 就可以了*/
byte data pulse_tally = 0;
volatile unsigned short xdata Degree_Constant;
unsigned char pulse_constant_1_percent = 16; //脉冲常数的1/100, 0.01KW
static uchar xdata temp;
void epmInit(void)
{
epmOverloadChkInit();
Timer0_Count=0;
repair_relay_state();
overload_ind=0;
load_data(&temp,DB_MC,1);
/* 获取上次记录的脉冲计数 */
Count_direction=(bit)(0x01&ReadChar(DB_DSAVE+ReadChar(DB_MC)));
}
#define LOAD_CONTROL_THRESHOLD 0x89
void epmOverloadChkInit(void)
{
load_data(&overload_counter[0],DB_LZFH,4);
/* 拉闸负荷值不能为零 */
if(isBCDZero(&overload_counter[0],POWER_DATA_LEN) == OK)
{
overload_counter[0]=LOAD_CONTROL_THRESHOLD;
}
overload_ind=0;
}
/*
* 过载判断和处理函数,过载后拉闸一次
*/
void epmOverloadOper(void)
{
/* 判断是否有过载 */
if(overload_ind)
{
/* 当有过载指示时则拉闸一次 */
epmUiDisplayCode(EPM_uP__);
USR_RELAY_OFF_NO_SAVE();
Sys_Timer.resume_power_supply_timer = RESUME_POWER_SUPPLY_TIME;
}
epmOverloadChkInit();
overload_ind=0;
}
/*
* 继电器开/关失败的处理函数(6分钟执行一次).处理项包括:
* 1.继电器关失败时窃电电量的计算.
*/
void epmQDDLCalculate(void)
{
byte *qddl_data = data_buf;
if(relay_fail_off)
{
/* 如果有继电器关失败,读取窃电电量值 */
load_data(&qddl_data[0],DB_QDDL,POWER_DATA_LEN);
/* 窃电电量值加一 */
inc_bcd(&qddl_data[0]);
/* 保存窃电电量数据 */
save_data(&qddl_data[0],DB_QDDL,POWER_DATA_LEN);
}
}
/*
* 用户最大需求计算,并保存数据
*/
void epmZDXLCalculate(void)
{
byte *zdxl_data = data_buf;
/*
* 读取上一次记录的用户最大需量
*/
load_data(&zdxl_data[0],DB_ZDXL,POWER_DATA_LEN);
/*
* 计算当前6分钟用户使用的电量
*/
/* 读取拉闸负荷设置 */
load_data(&zdxl_data[4],DB_LZFH,POWER_DATA_LEN);
if(OK != isBCDZero(&zdxl_data[4],POWER_DATA_LEN))
{
if(compbcd(&zdxl_data[4],&overload_counter[0]))
{
/* 拉闸负荷-剩余负荷=已使用负荷 */
bcdsub(&zdxl_data[4],&overload_counter[0]);
/* 当前使用量与上一次使用量做比,记录大者 */
if(compbcd(&zdxl_data[0],&zdxl_data[4])==0)
{
save_data(&zdxl_data[4],DB_ZDXL,POWER_DATA_LEN);
}
}
}
}
/*
* 记录用户实际使用的电量
*/
static uchar xdata pulse_pos,pulse_num,pulse_dec,timer;
void epmPowerRecord(void)
{
byte *power_data = data_buf;
byte *powerbak_data = data_buf + POWER_DATA_LEN*5;
timer=0;
if(IsPowerOFF())
{
return;
}
/* 判断是否有脉冲计数 */
if(pulse_counter)
{
/* 获取当前脉冲计数单元的位置 */
load_data(&pulse_pos,DB_MC,1);
/* 获取上次记录的脉冲计数 */
load_data(&pulse_num,DB_DSAVE+pulse_pos,1);
ET0=0;
/* 上次记录的脉冲计数+当前的脉冲计数=总的脉冲计数 */
pulse_num+=pulse_counter;
pulse_dec=pulse_counter;
/* 清零当前脉冲计数,重新开始计数 */
pulse_counter=0;
ET0=1;
/*过负荷检查*/
if(!overload_ind)
{
while(pulse_dec > 0) /*判断是否进入拉闸复合*/
{
if(OK == isBCDZero(&overload_counter[0],POWER_DATA_LEN))
{
overload_ind=1;
break;
}
dec_bcd(&overload_counter[0]);
pulse_dec --;
}
}
/* 当当前脉冲大于100,表示用户已经用了1度电 */
if(pulse_num>=PULSE_PER_KWH)
{
degree_ind=1; /* 每用一度电才进入一次epmPowerMonitor */
pulse_num-=PULSE_PER_KWH;
/* 获取过零电量,剩余电量,累计用电量数据 */
load_data(&power_data[0],DB_SYDL,POWER_DATA_LEN*5);
/* 判断剩余电量是否为零 */
if(OK == isBCDZero(&power_data[DB_SYDL-DB_SYDL],POWER_DATA_LEN))
{
/* 当剩余电量等于零时,过零电量加1 */
inc_bcd(&power_data[DB_GLDL-DB_SYDL]);
}
else
{
/* 当剩余电量大于零时,剩余电量减1 */
dec_bcd(&power_data[DB_SYDL-DB_SYDL]);
}
/* 累计用电量加1 */
inc_bcd(&power_data[DB_LJDL-DB_SYDL]);
do{
/* 保存过零电量,剩余电量,累计用电量数据 */
save_data(&power_data[0],DB_GLDL,POWER_DATA_LEN*5);
/* 回读数据 */
load_data(&powerbak_data[0],DB_GLDL,POWER_DATA_LEN*5);
if(OK == IsEqual(power_data,powerbak_data,POWER_DATA_LEN * 5)) break;
/*延迟回避干扰*/
delays_sixteenth(2);
}while(++ timer < 3);
/* 获取记录当前脉冲计数单元的位置 */
if((++pulse_pos) >= DEC_LOOP_NUMBER) pulse_pos=0;
/* 保存当前脉冲计数 */
save_data(&pulse_pos,DB_MC,1);
save_data(&pulse_num,DB_DSAVE+pulse_pos,1);
}
else
{
/* 保存当前脉冲计数 */
save_data(&pulse_num,DB_DSAVE+pulse_pos,1);
}
}
}
uchar get_epm_state(void)
{
byte *sydl = data_buf;
byte *yjmx = data_buf + 4;
byte *gldl = data_buf + 8;
byte *gjdl = data_buf + 12;
load_data(&sydl[0],DB_SYDL,POWER_DATA_LEN);
if(OK == isBCDZero(&sydl[0],POWER_DATA_LEN)) // == 0
{
load_data(&gldl[0], DB_GLDL, POWER_DATA_LEN);
load_data(&yjmx[0], DB_YJMX, POWER_DATA_LEN);
if(compbcd(&gldl[0],&yjmx[0])) // gldl >= yjmx
{
return DB_STA0_RUN_A4;
}
else // gldl < yjmx
{
return DB_STA0_RUN_A3;
}
}
else // != 0
{
load_data(&gjdl[0],DB_BJDL1,POWER_DATA_LEN);
if(compbcd(&gjdl[0],&sydl[0])) // gjdl1 >= sydl
{
//load_data(&gjdl[0],DB_BJDL2,3);
//if(compbcd(&gjdl[0],&sydl[0])) // gjdl2 >= sydl
//{
// return DB_STA0_RUN_A2;
//}
//else // gjdl2 < sydl
//{
return DB_STA0_RUN_A1;
//}
}
else // gjdl1 < sydl
{
return DB_STA0_RUN_A0;
}
}
}
static uchar xdata new_state;
void epmPowerMonitor(void)
{
/* 只在有用1度电的时候或者子状态不正确的时候才进入检查电量操作 */
if((1==degree_ind)|| epm_state[1]>DB_STA0_RUN_A4 )
{
degree_ind=0;
new_state=get_epm_state();
if( (epm_state[1]&0xEF) == new_state )
{
if( epm_state[1]&0x10)//0x10
{
epm_state[1]=new_state;
epmSubStateSet();
}
}
else//有了改变
{
if(new_state)
{
epmUiDisplayCode(EPM___A1+new_state-1);
}
if(new_state>DB_STA0_RUN_A1)
{
USR_RELAY_OFF();
}
else
{
USR_RELAY_ON();
}
epm_state[1]=new_state;
epmSubStateSet();
epmPowerDisplayOn();
}
}
if(epm_state[1]) epmPowerDisplayOn();
else epmPowerDisplayOff();
}
static uchar xdata relay_state_temp;
void repair_relay_state(void)
{
/* 继电器should状态赋初值 */
load_data(&relay_state_temp,DB_RELAY_STA,1);
if(RELAY_STATUS_ON == relay_state_temp)
USR_RELAY_ON_NO_SAVE();
else
USR_RELAY_OFF_NO_SAVE();
}
void delays_sixteenth(byte sixteenth_sec)
{
uchar xdata old_EA;
old_EA = EA;
EA = 1;
while(sixteenth_sec)
{
if(sixteenth_flag)
{
sixteenth_flag=0;
WDI_RESET();
sixteenth_sec--;
}
}
EA = old_EA;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -