📄 main.c
字号:
#include "msp430x41x.h"
#include "string.h"
#include "general.h"
#include "protocol.h"
// 系统秒计数
//unsigned char TimerSecond=0;
// 系统分钟计数
//unsigned char TimerMinute=0;
// 系统中各种事件指示标志
unsigned char SystemIndication;
// 外电掉电或低电压标识
unsigned char BreakOrLowPowerFlag;
// 当前记量属性
unsigned char PowerAttribute=0;
// 最大功率限制
//unsigned long PowerLimit=0;
// 记量计数,分别是正峰/正平/正谷/正尖/反峰/反平/反谷/反尖/正向校验/反向校验
__no_init unsigned char PowerScalar[10];
unsigned char PowerPulseCounter=0;
unsigned char PowerPulseConstant_;
// 系统时间信息
#ifdef _HARDWARE_RTC
unsigned char g_time[8];
#else
__no_init unsigned char g_time[7];
#endif
#ifdef _HARDWARE_RTC
unsigned char SystemTime_MonthHex;
#endif
// 定时器定时时长数组 - 定时单位改为秒
unsigned short TimerCounter[TIMER_NUMBER];
// 反向累计时间
unsigned char TotleTimeOfMiuns=0;
// 定时器处理函数数组
PROC_FUNC TimerProc[TIMER_NUMBER];
// 系统定时器Tick记数
unsigned char SystemTimeTick=0;
// 定时器处理函数 - 定时器时长以秒为单位
void RedundancyTimerProc(void)
{
unsigned char index;
for(index=0;index<TIMER_NUMBER;index++)
{
if(TimerCounter[index])
{
TimerCounter[index]--;
if(!TimerCounter[index])
{
TimerProc[index]();
}
}
}
}
// 电量数据存储操作-该处的存储只是当前月数据存储
void PowerDataStoreSlave(unsigned short addr,unsigned char data)
{
unsigned long resultdata,tempdata;
tempdata=Hex2Bcd((unsigned long)data);
E2promRead(addr,(unsigned char *)&resultdata,4);
resultdata=__bcd_add_long(resultdata,tempdata);
E2promWrite(addr,(unsigned char *)&resultdata,4);
}
// 电量数据存储
void PowerDataStoreProc(unsigned char addr_offset,unsigned char pwr_data)
{
unsigned char temp;
if(pwr_data)
{
temp=addr_offset*4;
// 保存至全局记录区
PowerDataStoreSlave(ADDRESS_OF_TOTAL_POWER_PLUS+temp,pwr_data);
// 保存至当前月数据记录区
PowerDataStoreSlave(ADDRESS_OF_MONTH_CURRENT+temp,pwr_data);
}
}
void PowerDataStore(void)
{
unsigned char ii,jj,zf_totle[2]={0,0};
// 完成总电量的计算
for(ii=0;ii<COUNT_OF_CHARGE_RATE;ii++)
{
zf_totle[0]+=PowerScalar[ii];//总正电量计算
zf_totle[1]+=PowerScalar[ii+4];//总反电量计算
}
for(jj=0;jj<2;jj++)
{
// 如果校验不通过,则丢弃该次数据
if(zf_totle[jj]==PowerScalar[8+jj])
{
// 数据校验通过,首先完成hex到bcd的转换,之后完成数据存储
for(ii=0;ii<COUNT_OF_CHARGE_RATE;ii++)
{
// 保存峰,平,谷电量
PowerDataStoreProc(jj*5+ii+1,PowerScalar[ii+jj*4]);
}
// 保存总电量
PowerDataStoreProc(jj*5,zf_totle[jj]);
}
}
// 清零计量数据
MemSetTo0(PowerScalar,10);
ReadPPC();
}
unsigned char GetPowerAttribute(void)
{
return((unsigned char)(PowerAttribute&0x07));
}
// 电量脉冲计算
void PowerPulseCalculate(void)
{
unsigned char pwr_attr;
pwr_attr=(unsigned char)GetPowerAttribute();
if((PowerPulseConstant_!=8)&&(PowerPulseConstant_!=16)&&(PowerPulseConstant_!=32))
{
PowerPulseConstant_=16;
}
while(PowerPulseCounter>=PowerPulseConstant_)
{
// 正向计量属性统计
PowerScalar[pwr_attr&0x03]++;
// 正向校验和累加
PowerScalar[8]++;
// 如果是反向电量,则在相应费率的正向处也累加
if(pwr_attr&ATTRIBUTE_OF_PLUS_MINUS)
{
// 反向计量属性统计
PowerScalar[pwr_attr&0x07]++;
// 反向校验和累加
PowerScalar[9]++;
}
// 更新脉冲计数
_DINT();
PowerPulseCounter-=PowerPulseConstant_;
_EINT();
}
// 之前的累计电量超过1度才保存,保存至临时数据区
if(PowerScalar[8]>=PULSE_COUNT_OF_PER_DEGREE)
{
PowerDataStore();
}
}
// 结算日,结算时间判断及历史数据存储
void MonthSpanDetect(void)
{
unsigned char monthinfo,data[4],i,temp;
#ifndef _HARDWARE_RTC
unsigned char time_bcd[7];
#endif
#ifndef _HARDWARE_RTC
GetSystemTimeBcd(time_bcd);
#endif
MonthSpanDetectStart:
// 设置本月为默认结算月
#ifdef _HARDWARE_RTC
monthinfo=SystemTime_MonthHex;
#else
monthinfo=g_time[SPACE_OF_MONTH];
#endif
// 读取记录的数据信息
E2promRead(ADDRESS_OF_SETTLEMENT_HOUR,data,3);
// 如果本月不等于上次结算月
if(monthinfo!=data[2])
{
// 计算本月与上次结算月之间的差
temp=(unsigned char)((monthinfo-data[2]+12)%12);
// 如果差大于1,则强制结算上月
if(temp>=2)
{
// 查找上月的月信息
monthinfo=(monthinfo+11)%12;
goto SURE_TO_SETTLEMENT;
}
// 如果今天大于结算日的日期,则结算
#ifdef _HARDWARE_RTC
if(g_time[SPACE_OF_DAY]>data[1])
#else
if(time_bcd[SPACE_OF_DAY]>data[1])
#endif
{
goto SURE_TO_SETTLEMENT;
}
// 如果今天等于结算日的日期
#ifdef _HARDWARE_RTC
else if(g_time[SPACE_OF_DAY]==data[1])
#else
else if(time_bcd[SPACE_OF_DAY]==data[1])
#endif
{
// 如果结算时间到了,则结算
#ifdef _HARDWARE_RTC
if(g_time[SPACE_OF_HOUR]>=data[0])
#else
if(time_bcd[SPACE_OF_HOUR]>=data[0])
#endif
{
goto SURE_TO_SETTLEMENT;
}
}
}
return; //未到结算时间,则退出
SURE_TO_SETTLEMENT:
// 结算之前数据强制记录
PowerDataStore();
for(i=0;i<40;i+=4)
{
// 读出当月的数据记录
E2promRead(ADDRESS_OF_MONTH_CURRENT+i,data,4);
// 将读出的数据写入历史记录区
E2promWrite(ADDRESS_OF_MONTH_LOG+40*(monthinfo)+i,data,4);
}
// 清零当月数据记录
_memset0_and_write_e2prom_(ADDRESS_OF_MONTH_CURRENT,40);
// 更新结算月份记录
// 月信息从0开始至11代表1月至12月
E2promWrite(ADDRESS_OF_SETTLEMENT_RECODE_MON,&monthinfo,1);
// 清除对过时的标记
_memset0_and_write_e2prom_(ADDRESS_OF_SUCCESSSETTIME_FLAG,1);
// 如果本月不等于刚刚结算过的月,则重新判断是否结算结算
// 这里的处理主要是为了解决不能实时结算多个月的问题
#ifdef _HARDWARE_RTC
if(SystemTime_MonthHex!=monthinfo)
#else
if(g_time[SPACE_OF_MONTH]!=monthinfo)
#endif
goto MonthSpanDetectStart;
}
void SaveTimeOfMiuns(void)
{
if(TotleTimeOfMiuns)
PowerDataStoreSlave(ADDRESS_OF_POWER_TIME_MINUS,TotleTimeOfMiuns);
TotleTimeOfMiuns=0;
}
// 计量属性之平/谷/峰/尖确认,每分钟执行一次
void ExesAttributeDetect()
{
unsigned char data[6],ptcnt; // 时段信息临时存储
unsigned char ii,idx,temp;
#ifndef _HARDWARE_RTC
unsigned char time_bcd[7];
#endif
#ifndef _HARDWARE_RTC
GetSystemTimeBcd(time_bcd);
#endif
// 读取时段数
ReadPeriodOfTimeCount(&ptcnt);
if(ptcnt>12) ptcnt=12;
// 置idx为时段数减1
idx=ptcnt-1;
// 如果时段数不只一个的话
if(ptcnt>1)
{
// 读取前2个时段信息
E2promRead(ADDRESS_OF_TIME_SECT,data,6);
// 如果第一个时段比第二个时段的时间大
if(data[2]>data[5])
{
idx=(idx+1)%ptcnt;
}
// 如果前两个时段的小时数相等
else if(data[2]==data[5])
{
// 如果第一个时段比第二个时段的时间大
if(data[1]>data[4])
{
idx=(idx+1)%ptcnt;
}
}
}
// 置费率初始值
E2promRead(ADDRESS_OF_TIME_SECT+idx*3,&temp,1);
// 查找目前所处时段
for(ii=0;ii<ptcnt;ii++)
{
idx=(idx+1)%ptcnt;
// 读取时段表
E2promRead(ADDRESS_OF_TIME_SECT+idx*3,data,3);
// 如果系统时间的小时大于时段表中的小时,则更新费率属性
#ifdef _HARDWARE_RTC
if(g_time[SPACE_OF_HOUR]>data[2])
#else
if(time_bcd[SPACE_OF_HOUR]>data[2])
#endif
{
temp=data[0];
}
#ifdef _HARDWARE_RTC
else if(g_time[SPACE_OF_HOUR]==data[2])
#else
else if(time_bcd[SPACE_OF_HOUR]==data[2])
#endif
{
// 如果系统时间的分钟大于时段表中的分钟,则更新费率属性
#ifdef _HARDWARE_RTC
if(g_time[SPACE_OF_MINUTE]>=data[1])
#else
if(time_bcd[SPACE_OF_MINUTE]>=data[1])
#endif
{
temp=data[0];
}
}
}
if(temp!=0) temp--;
// 反向累计时间
if(GetPowerAttribute()&ATTRIBUTE_OF_PLUS_MINUS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -