📄 rtc_dsp.c
字号:
#include <Reg936.h>
#include <Meter_def.h>
#include <General.h>
#include <var.h>
//**********************************************************
//函数申明
//**********************************************************
void RTC_Dsp_Proc(void); //时间、显示事件处理
void BatWorkState_Proc(void); //电池工作状态处理
void KBG_Even_Proc(void); //开表盖事件处理
void KDNH_Even_Proc(void); //开端钮盒事件处理
void Dsp_Proc(void); //显示处理
void Rev_Even_Proc(void); //电能反向事件处理
void DspPara_Read(void); //读显示控制参数
void Ery_Balance(void); //电量冻结
void Temp_Equalize(void); //时钟温度补偿
void Fee_CHK(void); //费率检查和切换
void MeterStateChange(void); //电表在新进状态时,连续运行36小时后自动切换至运行状态
void RTC_Init(void); //RTC初始化设置
void RTC_Read(void); //时间读取
void RTC_BAK(void); //时间备份
void SECINC(void); //秒加1
void Display(uchar idata *ptr); //LCD数据刷新
void RTC_Set(uchar staddr,uchar idata *ptr,uchar len); //RTC设置
bit DateTerm(void); //日期条件判断
bit DateCHK(uchar idata *ptr); //日期正确性判断
bit TimeCHK(uchar idata *ptr); //时间正确性判断
uchar pt(uchar year,uchar month); //
long int DateDifferenceCal(uchar idata *pDate1,uchar idata *pDate2);//日期时间差计算
uchar Temp_Read(void); //温度测量
uchar LastMonthSN(uchar sn); //历史月份计算
uchar BlnDateCheck(uchar addr2); //电能结算日期判断
//**********************************************************
//函数外部引用
//**********************************************************
extern void CreateRealTimeEry(void);
extern void PowerDownProcess(void);
extern bit Write24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
extern bit Read24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
//**********************************************************
// 名称: RTC_Dsp_Proc()
// 功能: 时钟、显示处理
// 说明:
//**********************************************************
void RTC_Dsp_Proc(void)
{
Watchdog_feed(); //喂狗
//费率检查
if((Fee0==0)&&(Fee1==0))
{
Fee_Flag = 1; //置位费率检查标志
}
//显示方式检查
if( (DspParaCHK!=~(DspPara[0]+DspPara[1]+DspPara[2]))||(DspTime!=~DspTimeCHK)||(DspDataReadFlag==1) )
{
DspDataReadFlag = 0;
DspPara_Read(); //显示控制参数校对处理
}
//显示刷新
if(DspFlag==1) //显示刷新标志位(1秒刷新一次)
{
DspFlag = 0; //清除显示刷新标志位
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
if(Sec>=0x59) //整分时刻任务事件处理
{
RTC_Read(); //1分钟间隔校时
if(Sec<=0x02) //3秒时间窗口
{
if(Min&0x01) RTC_BAK(); //逢单时间备份(2分钟备份一次)
//AdjDate = DateTerm(); //日期条件检查
if(((Min==0x00)||(Min==0x30))) //半小时间隔判断检查
{
Fee_Flag = 1; //时段费率检查标志位
RTC_Init(); //时钟配置初始化(刷新)
if(Min==0x00) //整点时刻任务处理
{
EryBln_Flag = 1; //电量冻结计算标志
Temp_Equalize(); //1小时时钟温度补偿
}
}
}
}
else SECINC(); //秒加1
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
////////////////////////////////////////////////////////////
KBG_Even_Proc(); //开表盖事件处理
KDNH_Even_Proc(); //开端钮盒事件处理
Rev_Even_Proc(); //电能反向事件处理
////////////////////////////////////////////////////////////
Dsp_Proc(); //显示处理
}
//监控主循环是否正常运行
MainMonitor = 0;
//监控Timer0是否正常运行
T0Monitor++;
if(T0Monitor>1000) AUXR1 |= 0x08; //软件复位
//保证外部中断1正常运行
EX1 = 0;
IT1 = 1;
IP0H |= 0x04;
IP0 &=~0x04;
EX1 = 1;
CMP1 = 0x38;
CMP2 = 0x38;
//未用功能模块关闭
PCONA = 0x55; //0101 0101
//关闭未用之中断
EC = 0; //关比较器中断
EX0 = 0; //关闭外部中断0
EST = 0; //关闭TX发送中断
EBO = 0; //关闭掉电检测中断
EI2C = 0; //关闭I2C中断
ESPI = 0; //关闭SPI模块
SPCTL = 0x84;
//////////////////////////////////////////////////////////////
if(CommFlag==0) //不在通讯状态
{
HW38K = 1;
if(COMMSEL==0) //默认红外通讯
{
KBPATN = 0xFF;
KBCON = 0x00; //PATN_SEL=0
KBMASK = 0x40; //打开RS485通讯唤醒
IP1 &=~0x02; //中断优先级为0级(最低)
IP1H &=~0x02;
EKBI = 1; //键盘中断使能
}
}
if((CommFlag==1)&&(ES==0)) //串口异常
{
ReinitUARTFlag = 1; //UART重新初始化标志
}
//////////////////////////////////////////////////////////////
if(Fee_Flag==1)
{
Fee_CHK(); //时段费率处理
}
if(EryBln_Flag==1)
{
Ery_Balance(); //结算日处理(日、时)
MeterStateChange(); //电表在新进状态时,连续运行36小时后自动切换至运行状态
}
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
//**********************************************************
// 名称: void BatWorkState_Proc(void)
// 功能:
// 说明: 电池工作状态处理
//**********************************************************
void BatWorkState_Proc(void)
{
long int BatWorkTime1,BatWorkTime2;
uchar Temp;
Watchdog_feed(); //喂狗
///////////////////////////////////////////////////////////////////////////
//上次断电时电能反向处理(电能反向终止事件是否发生)
Read24C64(CommVariant,0x00,0x16,1); //上次断电前电能是否反向标志
if(CommVariant[0]==0xAA) //发生电能反向终止事件
{
Read24C64(CommVariant,0x00,0x10,4); //读取上次系统掉电时间
Write24C64(CommVariant,0x04,0xC7,4); //写发生电能反向终止事件时间
}
///////////////////////////////////////////////////////////////////////////
//读取上次断电时电池工作状态
Read24C64(CommVariant,0x00,0xEA,2); //电池工作状态+校验
if(CommVariant[0]!=~CommVariant[1])
{
CommVariant[0] = 0x00; //默认为电池处于欠压状态
CommVariant[1] = 0xFF;
}
if(CMP2&0x02) //电池电压高
{
//Battery = 0x00; //电池不工作
if(CommVariant[0]==0x00) BatUpFlag = 0x01; //电池上电标志
else Battery = 0x01; //电池有效工作
MeterRunFlag &= 0xFB; //电池电压正常
CommVariant[0] = 0xAA;
CommVariant[1] = 0x55;
}
else //电池电压低
{
//Battery = 0x00; //电池不工作
if(CommVariant[0]==0xAA) BatAlert = 0x01; //电池报警标志
////////////////////////////////////////////
MeterRunFlag |= 0x04; //电池欠压
SystemCheckFlag |= 0x01; //电池欠压液晶指示
////////////////////////////////////////////
CommVariant[0] = 0x00;
CommVariant[1] = 0xFF;
}
//回写电池工作状态
Write24C64(CommVariant,0x00,0xEA,2);
//读取当前时间
RTC_Read();
CommVariant[10] = RTC[1]; //Min
CommVariant[11] = RTC[2]; //Hour
CommVariant[12] = RTC[4]; //Day
CommVariant[13] = RTC[5]; //Month
CommVariant[14] = RTC[6]; //Year
CommVariant[15] = ~SumCHK(&CommVariant[5],5);
if(Battery) //电池处于有效工作状态
{
Read24C64(CommVariant,0x00,0x10,6); //读取上次系统掉电时间
CommVariant[6] = ~SumCHK(CommVariant,5);
if(CommVariant[5]!=CommVariant[6])
{
CommVariant[4] = Year; //年
CommVariant[3] = Month; //月
CommVariant[2] = Day; //日
CommVariant[1] = Hour; //时
CommVariant[0] = Min; //分
}
//返回本次上电与上次下电之工作时间(分钟)
BatWorkTime1 = DateDifferenceCal(&CommVariant[2],&CommVariant[12]); //计算相差天数
BatWorkTime1 = BatWorkTime1*24*60 + BCD2HEX(CommVariant[11])*60 + BCD2HEX(CommVariant[10]);
BatWorkTime2 = BatWorkTime1 - BCD2HEX(CommVariant[1])*60 - BCD2HEX(CommVariant[0]);
//读取电池工作时间
Read24C64(CommVariant,0x00,0xE6,4); //电池工作时间+校验
Temp = CommVariant[0]+CommVariant[1]+CommVariant[2];
if(CommVariant[3]!=~Temp) ArrayInit(CommVariant,4); //清零
//电池工作时间累加
BatWorkTime1 = BCD2HEX(CommVariant[2])*10000+BCD2HEX(CommVariant[1])*100+BCD2HEX(CommVariant[0]);
BatWorkTime2 += BatWorkTime1;
//以BCD码形式保存数据
Temp = (uchar)(BatWorkTime2/10000);
CommVariant[2] = HEX2BCD(Temp);
BatWorkTime2 = BatWorkTime2%10000;
Temp = (uchar)(BatWorkTime2/100);
CommVariant[1] = HEX2BCD(Temp);
Temp = (uchar)(BatWorkTime2%100);
CommVariant[0] = HEX2BCD(Temp);
CommVariant[3] = ~(CommVariant[0]+CommVariant[1]+CommVariant[2]);
//回写电池工作时间
Write24C64(CommVariant,0x00,0xE6,4);
}
if(BatAlert) //电池报警
{
Write24C64(&CommVariant[10],0x00,0xE0,6); //电池报警+校验
}
if(BatUpFlag) //电池上电
{
ArrayInit(CommVariant,10);
Write24C64(CommVariant,0x00,0xE0,10); //电池相关数据清零
}
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
//**********************************************************
// 名称: Rev_Even_Proc()
// 功能:
// 说明: 电能反向事件处理
//**********************************************************
void Rev_Even_Proc(void)
{
uchar Temp=0;
//电能反向事件监测
if(REVP==0)
{
RevDeLayTimer++;
}
else
{
RevSec = 0x00;
RevDeLayTimer = 0x00;
//////////////////////////////////////////////////
MeterRunFlag &= 0xEF;
//////////////////////////////////////////////////
if(EryRev==1) Temp = 0xC7; //电能反向终止事件判断
EryRev = 0; //电能反向标志清零
}
//电能反向开始事件判断
if(RevDeLayTimer>3)
{
//////////////////////////////////////////////////
MeterRunFlag |= 0x10;
//////////////////////////////////////////////////
if(EryRev==0) Temp = 0xC3; //发生电能反向起始事件
EryRev = 1; //电能反向标志置位
}
//写当前月最后一次反向起/止时间
if(Temp>0)
{
CommVariant[0] = Min; //分
CommVariant[1] = Hour; //时
CommVariant[2] = Day; //日
CommVariant[3] = Month;//月
Write24C64(CommVariant,0x04,Temp,4);
}
//电能反向累计总时间计算
if(EryRev==1) RevSec++;
if(RevSec>59) //反向时间累计满1分钟处理
{
RevSec = 0x00;
for(Temp=0;Temp<2;Temp++)
{
Read24C64(CommVariant,0x04,0xC0+Temp*0x10,3);
//0xD0--->有功反向累计总时间
//0xC0--->当前月总反向累计时间
BCDINC(CommVariant,3); //+1
Write24C64(CommVariant,0x04,0xC0+Temp*0x10,3); //回写
}
}
}
//**********************************************************
// 名称: Dsp_Proc()
// 功能:
// 说明: 液晶显示处理
//**********************************************************
void Dsp_Proc(void)
{
uchar i,j,addr1,nFee;
uchar DspBuf[8]; //显示缓冲区
DspSec++; //轮显时间+1
if(CommLCDSec>0) CommLCDSec--; //液晶通讯指示显示时间-1
if(LCDShowMode==1) //液晶显示屏查看模式
{
if(LCDViewSec==0)
{
DspPtr = 0x00;
LCDShowMode = 0; //查询结束,切换为正常轮显模式
DspSec = 0; //显示计数清零
}
else --LCDViewSec; //液晶显示屏查看时间-1
}
if(LCDShowMode==0) //正常轮显模式
{
//显示项目切换
if( (DspSec>=BCD2HEX(DspTime)) || (ProgActiveFlag==0xFF) ) //轮显时间满或者按键轮显,更新显示指针
{
DspSec = 0; //显示计数清零
DspCtrl3 &= 0x3F; //屏蔽DspPtr=(22、23);
if((SystemCheckFlag&0x07)!=0) DspCtrl3 |= 0x40; //DspPtr=22
else DspCtrl3 &= ~0x40;
i = 0x00; //轮显指针处理
do
{
DspPtr++;
if(DspPtr<8) i = (DspCtrl1>>DspPtr)&0x01; //第一显示控制字节判断(0~7)
else if(DspPtr>15) //第三显示控制字节判断(16~21)
{
i = (DspCtrl3>>(DspPtr-16))&0x01;
if(DspPtr>=23) DspPtr = 0xFF; //显示项判断结束
}
else i = (DspCtrl2>>(DspPtr-8))&0x01; //第三显示控制字节判断(8~15)
} while(i==0x00);
}
}
//各页变量数据形成
if(DspPtr<10) //显示指针0~9
{
i = 3; //预置为6个“8”字LED显示
if(DspPtr==0) //当前日期显示
{
DspExch[2] = Year;
DspExch[1] = Month;
DspExch[0] = Day;
//i = 3;
}
else if(DspPtr==1) //当前时间显示
{
DspExch[2] = Hour;
DspExch[1] = Min;
DspExch[0] = Sec;
//i = 3;
}
else if(DspPtr==2) //自动抄表日期
{
Read24C64(CommVariant,0x08,0x88,2);
for(j=0;j<2;j++) DspExch[j] = CommVariant[j];
i = 2;
}
else if((DspPtr==3)||(DspPtr==4)) //资产条形码号:显示高六位--->3 ; 显示低六位--->4 .
{ //电表局号高6位
i = 3;
if(DspPtr==4) i = 0;
Read24C64(CommVariant,0x00,0xF7+i,3);
for(j=0;j<3;j++) DspExch[j] = CommVariant[j];
i = 3;
}
else if(DspPtr==5) //屏幕循显时间
{
DspExch[0] = DspTime;
i = 1;
}
else if(DspPtr==6) //输出脉冲宽度:80mS
{
DspExch[0] = 0x80;
DspExch[1] = 0x00;
i = 2;
}
else if(DspPtr==7) //电表有功常数:1600imp/kWh
{
DspExch[0] = 0x00;
DspExch[1] = 0x16;
i = 2;
}
else if(DspPtr==8) //有功反向累计总时间
{
Read24C64(CommVariant,0x04,0xD0,3);
for(j=0;j<3;j++) DspExch[j] = CommVariant[j];
//i = 3;
}
else //现在执行时段表编号
{
Read24C64(CommVariant,0x09,0x4F,1);
DspExch[0] = CommVariant[0];
DspExch[0] += 1;
i = 1;
}
//显示数据拆分
DspBuf[2] = DspExch[0]&0x0F; //LED6(最低位)
DspBuf[3] = DspExch[0]>>4; //LED5
DspBuf[4] = DspExch[1]&0x0F; //LED4
DspBuf[5] = DspExch[1]>>4; //LED3
DspBuf[6] = DspExch[2]&0x0F; //LED2
DspBuf[7] = DspExch[2]>>4; //LED1(最高位)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -