⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 measure.c

📁 单相多功能代码,计量芯片采用ADE7737做为计量,SPI通讯,仅供参考,不得用于商业
💻 C
字号:
#include "measure.h"
#include "sys_time.h"
#include "storage.h"
#include "pub_func.h"
#include "i2c.h"
#include "string.h"

// 当前时段表表号
_sys_potinfo_s _SysPotInfo;
// 当前记量属性(正向尖,峰,平,谷;反向尖,峰,平,谷)
unsigned char PowerAttribute=0;
// 当前时段
unsigned char CurrentPotNum;

/******************************************
* 时区确认
* 说明:1.时区信息在E2prom中的存储一定要按照时间
*       由小到大排序
*     2.在一个月内可以有多个时区
******************************************/
void ZoneAttributeDetect(void)
{
    unsigned char zoneinfo[2],zonecnt,zonenum,i;

    // 读时区数
    ReadBcdCountInfo(ADDR_OF_TIMEZONE_COUNT,&zonecnt,13,1);

    // 时区号初始化为最后一个时区
    zonenum=zonecnt-1;

    for(i=0;i<zonecnt;i++)
    {
        // 读时区信息(月,日)
        FramRead(BASE_ZTSTA+i*3+ZT_OFFSET_DAY,zoneinfo,2);
        // 如果当前月大于时区信息的月,则继续寻找下一个时区信息
        if(_sys_time.months>zoneinfo[1])
        {
            // 保存时区号
            zonenum=i;
        }
        // 如果当前月等于时区信息的月,则判断日期
        else if(_sys_time.months==zoneinfo[1])
        {
            // 如果当前日大于等于时区信息的日
            if(_sys_time.days>=zoneinfo[0])
            {
                // 保存时段表号
                zonenum=i;
            }
        }
    }
    //保存当前的时区号
    _SysPotInfo.zonenum=zonenum;
}

/******************************************
* 费率属性确认
******************************************/
void ExesAttributeDetect(void)
{
    unsigned char i,exes,potnum=_SysPotInfo.potcnt;

    // 初始化当前费率(取当日时段表中最后一个日时段费率)
    exes=_SysPotInfo.potinfo[(_SysPotInfo.potcnt-1)*3+POT_OFFSET_EXES];

    for(i=0;i<_SysPotInfo.potcnt;i++)
    {
        // 如果系统时间的小时大于时段表中的小时,则更新费率属性
        if(_sys_time.hours>_SysPotInfo.potinfo[i*3+POT_OFFSET_HOUR])
        {
            exes=_SysPotInfo.potinfo[i*3+POT_OFFSET_EXES];
            potnum=i;
        }
        else if(_sys_time.hours==_SysPotInfo.potinfo[i*3+POT_OFFSET_HOUR])
        {
            // 如果系统时间的分钟大于时段表中的分钟,则更新费率属性
            if(_sys_time.minutes>=_SysPotInfo.potinfo[i*3+POT_OFFSET_MINUTE])
            {
                exes=_SysPotInfo.potinfo[i*3+POT_OFFSET_EXES];
                potnum=i;
            }
        }
    }

    exes--;
    if(exes>7)
    {
        exes=0x02;
    }
    if(PowerAttribute!=exes)
    {
        // 如果切换了费率,则保存当天电量数据
        //StorePowerData();
        // 保存需量数据
        //SaveRequirePowerData();
        // 刷新当前费率属性
        PowerAttribute=exes;
    }
    CurrentPotNum=potnum;
}

// 春节日期定义
const unsigned char _SpringFestivalDate[50]=
{
    36,// {0x02,0x06},//2000年2月05日
    24,// {0x01,0x24},//2001年1月24日
    43,// {0x02,0x12},//2002年2月12日
    32,// {0x02,0x01},//2003年2月01日
    22,// {0x01,0x22},//2004年1月22日
    40,// {0x02,0x09},//2005年2月09日
    29,// {0x01,0x29},//2006年1月29日
    49,// {0x02,0x18},//2007年2月18日
    38,// {0x01,0x07},//2008年2月07日
    26,// {0x01,0x26},//2009年1月26日
    45,// {0x02,0x14},//2010年2月14日
    34,// {0x02,0x03},//2011年2月03日
    23,// {0x01,0x23},//2012年1月23日
    41,// {0x02,0x10},//2013年2月10日
    31,// {0x01,0x31},//2014年1月31日
    50,// {0x02,0x19},//2015年2月19日
    39,// {0x02,0x08},//2016年2月08日
    28,// {0x01,0x28},//2017年1月28日
    47,// {0x02,0x16},//2018年2月16日
    36,// {0x02,0x05},//2019年2月05日
    25,// {0x01,0x25},//2020年1月25日
    43,// {0x02,0x12},//2021年2月12日
    32,// {0x02,0x01},//2022年2月01日
    22,// {0x01,0x22},//2023年1月22日
    41,// {0x02,0x10},//2024年2月10日
    29,// {0x01,0x29},//2025年1月29日
    48,// {0x02,0x17},//2026年2月17日
    37,// {0x02,0x06},//2027年2月06日
    26,// {0x01,0x26},//2028年1月26日
    44,// {0x02,0x13},//2029年2月13日
    34,// {0x02,0x03},//2030年2月03日
    23,// {0x01,0x23},//2031年1月23日
    42,// {0x02,0x11},//2032年2月11日
    31,// {0x01,0x31},//2033年1月31日
    50,// {0x02,0x19},//2034年2月19日
    39,// {0x02,0x08},//2035年2月08日
    28,// {0x01,0x28},//2036年1月28日
    46,// {0x02,0x15},//2037年2月15日
    35,// {0x02,0x04},//2038年2月04日
    24,// {0x01,0x24},//2039年1月24日
    43,// {0x02,0x12},//2040年2月12日
    32,// {0x02,0x01},//2041年2月01日
    22,// {0x01,0x22},//2042年1月22日
    41,// {0x02,0x10},//2043年2月10日
    30,// {0x01,0x30},//2044年1月30日
    48,// {0x02,0x17},//2045年2月17日
    37,// {0x02,0x06},//2046年2月06日
    26,// {0x01,0x26},//2047年1月26日
    45,// {0x02,0x14},//2048年2月14日
    33// {0x02,0x02},//2049年2月02日
};

/******************************************
* 公共假日确认
* 节假日优先级为:春节>公共假日>周休日
******************************************/
unsigned short PublicVacationDetect(void)
{
    unsigned short addr,addr1;
    unsigned char pvinfo[2],temp=0,pvcnt,i;

    // 读周休日状态字
    FramRead(ADDR_OF_WEEKEND_STATUS,&pvcnt,1);
    if(!(pvcnt&(0x01<<_sys_time.week)))
    {
        temp|=0x01;
        addr=ADDR_OF_SPRING_FEST;
    }
    
    // 读公共假日数
    ReadBcdCountInfo(ADDR_OF_PUB_VACATION_COUNT,&pvcnt,13,1);
    for(i=0;i<pvcnt;i++)
    {
        addr1=BASE_PUBV+i*3+PUBV_OFFSET_DAY;
        // 读公共假日信息(月,日)
        FramRead(addr1,pvinfo,3);
        // 如果当前月和日等于公共假日信息的月和日
        if((_sys_time.months==pvinfo[1])&&(_sys_time.days==pvinfo[0]))
        {
            // 保存当前公共假日状态为公共假日
            temp|=0x10;
            addr=addr1-1;
            break;
        }
    }
    
    // 判断是否为春节三天
    if(_sys_time.months<2)
    {
        pvcnt=Bcd2HexChar(_sys_time.years);
        if(pvcnt<50)
        {
            pvinfo[0]=_sys_time.months*31+Bcd2HexChar(_sys_time.days);
            pvinfo[1]=_SpringFestivalDate[pvcnt]-1;
            pvinfo[0]=(unsigned char)((unsigned char)pvinfo[0]-(unsigned char)pvinfo[1]);
            if(pvinfo[0]<=2)
            {
                // 保存当前公共假日状态为春节
                temp|=0x20;
                addr=ADDR_OF_WEEKEND;
            }
        }
    }

    if(temp)
    {
        _SysPotInfo.pubvacstate=temp;
        return(addr);
    }
    return(0);
}

/******************************************
* 确认日时段表号
******************************************/
void GetPeriodOfTimeTableNum(void)
{
    unsigned short addr_pottbl;
    unsigned char pottblcnt,temp;

    // 读取本日公共假日号
    addr_pottbl=PublicVacationDetect();

    // 读取本日所在时区号
    ZoneAttributeDetect();

    if(_SysPotInfo.pubvacstate==0)
    {
        // 如果本日不是公共假日,则读相应时区的时段表号
        addr_pottbl=BASE_ZTSTA+_SysPotInfo.zonenum*3+ZT_OFFSET_POTNUM;
    }

    // 读取日时段表数
    ReadBcdCountInfo(ADDR_OF_POT_COUNT,&pottblcnt,13,1);
    // 读取本日时段表号
    FramRead(addr_pottbl,&temp,1);
    temp=Bcd2HexChar(temp);
    if((temp==0)||(temp>pottblcnt))
    {
        temp=1;
    }
    _SysPotInfo.pottblnum=temp;
    //ReadBcdCountInfo(addr_pottbl,&_SysPotInfo.pottblnum,pottblcnt,1);
}

/******************************************
* 确认时段信息
******************************************/
void EnsurePeriodOfTime(void)
{
    unsigned short addr;
    unsigned char i,exescnt;

    // 清数据结构
    memset((unsigned char *)&_SysPotInfo.chksum,0x0,sizeof(_sys_potinfo_s));

    // 读取日时段表信息
    GetPeriodOfTimeTableNum();

    // 读取时段数
    ReadBcdCountInfo(ADDR_OF_POT_SWITCH_COUNT,&_SysPotInfo.potcnt,13,1);

    // 读取费率数
    ReadBcdCountInfo(ADDR_OF_FRATE_COUNT,&exescnt,5,1);

    addr=BASE_POT_T+(_SysPotInfo.pottblnum-1)*BASE_POT_T_OFFSET;
    for(i=0;i<_SysPotInfo.potcnt;i++)
    {
        // 读取时段表中的时间信息(时,分)
        // 读取时段表中的费率信息
        FramRead(addr,(unsigned char *)&_SysPotInfo.potinfo[i*3],3);
        // 如果当前费率不在范围内,则强制置为"平电量"
        if(_SysPotInfo.potinfo[i*3+POT_OFFSET_EXES]>exescnt)
        {
            _SysPotInfo.potinfo[i*3+POT_OFFSET_EXES]=2;
        }
        addr+=3;
    }

    // 更新本日日期和当前时间
    _SysPotInfo.day=_sys_time.days;
    _SysPotInfo.hour=_sys_time.hours;
    _SysPotInfo.year=_sys_time.years;

    // 读取结算日信息
    FramRead(ADDR_OF_AUTO_RDDATA_DATE,(unsigned char *)&_SysPotInfo.balance_hour,2);

    // 读取上次结算月信息
    FramRead(ADDR_OF_SETTLEMENT_RECODE_MON,(unsigned char *)&_SysPotInfo.last_balance_mon,2);

    // 读取需量周期时间(最大60分钟,默认15分钟)
    ReadBcdCountInfo(ADDR_OF_REQ_CYCLE,&_SysPotInfo.reqtime,60,15);
    //_SysPotInfo.reqtime=1;
    // 读取滑差时间(最大60分钟,默认5分钟)
    ReadBcdCountInfo(ADDR_OF_SLIP_TIME,&_SysPotInfo.reqtime_huacha,60,5);
    _SysPotInfo.reqtime_huacha=1;

    // 读取电表常数
    FramRead(ADDR_OF_METER_CONSTANT_A+1,(unsigned char *)&exescnt,1);
    exescnt=Bcd2HexChar(exescnt);
    if((exescnt!=8)&&(exescnt!=16)&&(exescnt!=32))
    {
        _SysPotInfo.constant_a=8;
    }
    else
    {
        _SysPotInfo.constant_a=exescnt;
    }
    _SysPotInfo.watt=(0x2000/_SysPotInfo.constant_a)*10;

    // 电压有效范围
    //AptoticDataRead(ADDR_OF_REGV_MIN_VALUE,(unsigned char *)&_SysPotInfo.regv_min,4);
    //_SysPotInfo.regv_min=Bcd2HexShort(_SysPotInfo.regv_min);
    //_SysPotInfo.regv_max=Bcd2HexShort(_SysPotInfo.regv_max);
    _SysPotInfo.regv_max=2640;
    // 失压条件
    FramRead(ADDR_OF_LV_CONDITION+2,(unsigned char *)&addr,2);
    _SysPotInfo.lostv_con=Bcd2HexShort(addr);
    // 失流条件
    FramRead(ADDR_OF_LI_CONDITION+1,(unsigned char *)&addr,2);
    _SysPotInfo.losti_con=Bcd2HexShort(addr);

    // 额定电流
    FramRead(ADDR_OF_RATED_IB,(unsigned char *)&addr,2);
    _SysPotInfo.currentcoe=Bcd2HexShort(addr);

    // 声光报警控制字
    FramRead(ADDR_OF_ALARM_RAYCTL_WORD,(unsigned char *)&_SysPotInfo.alarm_light,2);

    // 读ADE7753配置信息
    exescnt=0;
    for(i=0;i<50;i++)
    {
        //addr=ADDR_OF_ADE_BASE+i*3;
        //FramRead(addr,(unsigned char *)&_SysPotInfo.ade7758_info[exescnt],_ade7758_wr_bytes[i]);
        //exescnt+=_ade7758_wr_bytes[i];
    }
    
    // 计算校验和
    _SysPotInfo.chksum=GetChkSumRvrs((unsigned char *)&_SysPotInfo.regv_min,sizeof(_sys_potinfo_s)-4);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -