//——————————软串口
#include "public.h"//引脚定义(外部需设定端口方向及上拉状态)#define pSTX RC2#define pSRX RC1//引脚初始化#define SRX_Init() {TRISC1=1; WPUC1=1;} //输入, 上拉#define STX_Init() {TRISC2=0; RC2=1;} //输出, 高电平//---------------------------------------- 声明为外部变量extern uint8_t SRXREG; //接收寄存器extern bit _srxdone; //接受寄存器有数据标志extern uint8_t STXREG; //发送数据寄存器extern bit _stxdone; //发送寄存器为空标志//软串口物理层初始化void suart_phyinit();//软串口物理层驱动, 仅中断调用(根据需要调整速率-调用时间)void suart_phydriver();
//软件模拟串口收发通信协议uint8_t rCNTrec; //接收进入计数uint8_t rSEQreceive;//接收bit步骤uint8_t rCNTreceive;//接收bit计数uint8_t SRXPREG; //接收前端寄存器(数据首先保存在此处, 接收完成一个直接后再赋值到SRXREG)uint8_t SRXREG; //接收寄存器bit _srxdone; //接受寄存器有数据标志//发送部分uint8_t sCntisr; //发送进入计数uint8_t sSEQsend; //发送bit步骤uint8_t sCntSend; //发送bit计数uint8_t STXREG; //发送数据寄存器bit _stxdone; //发送寄存器为空标志//软串口物理层初始化void suart_phyinit(){//发送sCntisr = 0;sSEQsend = 0;sCntSend = 0;STXREG = 0;_stxdone = 1; //为1表示发送寄存器为空//接收rCNTrec = 0;rSEQreceive = 0;rCNTreceive = 0;SRXPREG = 0;SRXREG = 0;_srxdone = 0; //为0表示接收寄存器无数据}//软串口物理层驱动, 中断调用(根据需要调整速率)void suart_phydriver(){///////////////////////串口发送物理层驱动/////////////////////////////////3个计数周期进入一次if(++sCntisr >= 3){sCntisr = 0;//发送寄存器为空, 不进行下一步if(!_srxdone){switch(sSEQsend){// 起始位0:1bitcase 0:pSTX = 0;sSEQsend = 1;sCntSend = 0;break;// 数据位SENDcase 1://低位先发送if(STXREG & 0x01) { pSTX = 1; }else { pSTX = 0; }STXREG >>= 1;if((++sCntSend) >= 8){sCntSend = 0;sSEQsend = 2;}break;// 停止位(1bit)case 2:pSTX = 1;sSEQsend = 0;_srxdone = 1;break;default:pSTX = 1; //拉高电平sSEQsend = 0; //发送状态回归初始_srxdone = 1; //break;}}}//////////////////////串口接收物理层驱动///////////////////////////////switch(rSEQreceive){// 起始位bit0case 0:if(pSRX == 0) // 收到起始位bit0{rSEQreceive = 1;rCNTrec = 0;SRXPREG = 0;}break;// 8bits_bit1数据case 1:if(++rCNTrec == 4) // 第一次进来时为4个周期,提升容错率{ // 其它时机进来为3个周期,保持同步性rCNTrec = 1;if(pSRX == 1){SRXPREG |= 0x80;}SRXPREG >>= 1;rCNTreceive++;if(rCNTreceive >= 8){rCNTreceive = 0;rCNTrec = 0;rSEQreceive = 2;}}break;//结束case 2:_srxdone = 1;SRXREG = SRXPREG; //前端寄存器数据拷贝到后端寄存器SRXPREG = 0;rSEQreceive = 0;break;}}
——————————-主板
////////////////////////////connect main board///////////////////////////////
/*
灯板->主板
    1.控制命令
    2.滤芯寿命
    3.滤芯1寿命百分比
    4.滤芯2寿命百分比
主板->灯板
    1.设备状态(高压开关、废水阀、进水阀、增压泵)
    2.工作状态
    3.wifi
    4.故障
*/
#define         MB_SENDLEN  8
#define         MB_RECVLEN  8
typedef struct{
////////////////////// 发送 ///////////////////////////////////
    uint8_t     SendBuf[MB_SENDLEN];
    uint8_t     SendCnt;        //等待发送数据长度
////////////////////// 接收 ///////////////////////////////////
    uint8_t     RecvBuf[MD_RECVLEN];
    uint8_t     RecvCnt;        //接收数据长度
}main_board_t;
main_board_t    g_mBoard;
T_BYTE          mBoardF;
//#define     bRecvFrameDone  mBoardF.bit.b0  //接收完成一帧标志
void mainboard_Init()
{  
    //端口初始化
    SRX_Init();
    STX_Init();
    suart_phyinit();
}
//主板通讯
void main_board_isr()
{
//------------------- 发送
    if(_stxdone)
    {
        if(g_mBoard.SendCnt > 1)
        {
            g_mBoard.SendCnt--;
            STXREG = g_mBoard.SendBuf[MB_SENDLEN - g_mBoard.SendCnt];
            _stxdone = 0;
        }
    }
//------------------- 接收
    if(_srxdone)
    {
        if(g_mBoard.RecvCnt < MB_RECVLEN)
        {
            g_mBoard.RecvBuf[g_mBoard.RecvCnt] = SRXREG;
            _srxdone = 0;
            g_mBoard.RecvCnt++;
        }
    }
}
static uint8_t getCheckSum(uint8_t *ptr, uint8_t len)
{
    uint8_t chk = 0;
    while(len)
    {
        chk += *ptr;
        ptr++;
        len--;
    }
    return chk;
}
void main_board_Process()
{
    uint8_t x;
    //等待上电系统稳定
    if(!bpowerOn)
        return;
//------------------------------------- 接收处理
    if(g_mBoard.RecvCnt >= MB_RECVLEN)
    {
        if(g_mBoard.RecvBuf[MB_RECVLEN-1] == getCheckSum(g_mBoard.RecvBuf,(MB_RECVLEN-1)))
        {
            //校验正确, 表示通讯过程数据传输正确
            //判断起始码是否正确, 正确开始解码数据
            if(g_mBoard.RecvBuf[0] == 0xa5)
            {
                mDeviceStF.byte = g_mBoard.RecvBuf[1];
                mWorkMode       = g_mBoard.RecvBuf[2];
                mWifiSt         = g_mBoard.RecvBuf[3];
                mError          = g_mBoard.RecvBuf[4];
            }
        }
        else
        {
            //否则传输错误, 故障计数
        }
        g_mBoard.RecvCnt = 0;
    }
//------------------------------------- 发送数据处理
    if(g_mBoard.SendCnt == 0)
    {
        for(x=0; x<MB_SENDLEN; x++)
        {
            g_mBoard.SendBuf[x] = 0;
        }
        g_mBoard.SendBuf[0] = 0xa5;
        g_mBoard.SendBuf[1] = dCtrlCmd.byte;
        g_mBoard.SendBuf[2] = dFilterF.byte;
        g_mBoard.SendBuf[3] = gFilter.PP_work.wPercent;
        g_mBoard.SendBuf[4] = gFilter.RO_work.wPercent;
        g_mBoard.SendBuf[MB_SENDLEN-1] = getCheckSum(g_mBoard.SendBuf, MB_SENDLEN-1);
        g_mBoard.SendCnt = MB_SENDLEN;
    }
}
/*
引脚描述
    01. SEG3/AN3/TK3/RA3                    --    
    02. T0CKI/SEG4/AN4/TK4/RA4                --    BUZ
    03. SEG8/AN8/TK8/RB0                    --    LED1
    04.    INT/SEG9/AN9/TK9/RB1                --    LED2
    05.    SEG10/AN10/TK10/RB2                    --    LED3
    06.    CCP1/RX1/DT1/AN11/TK11/RB3            --    LED4
    07.    T1G/CCP2/TX1/CK1/AN12/TK12/RB4        --    LED5
    08.    T1CKI/AN13/TK13/RB5                    --    LED6
    09.    GND
    10.    VDD
    11.    RD2/TK15/AN15                        --    K1
    12.    RD1/TK24/AN24/TX0/CK0/SCL/ICSPDAT    --    
    13.    RD0/TK25/AN25/RX0/DT0/SDA/ICSPCLK    --
    14.    RC3/TK20/AN20/COM3
    15.    RC2/TK21/AN21/COM2                    --    DA  //TX
    16.    RC1/TK22/AN22/COM1                    --    CK  //RX
    17.    RC0/TK23/AN23/COM0
    18.    RA0/TK0/AN0/SEG0
    19.    RA1/TK1/AN1/SEG1
    20.    RA1/TK1/AN1/SEG1
*/
extern      volatile T_BYTE      mainRunF;
#define     b250usFlgg  mainRunF.bit.b0
#define     b1msFlgg    mainRunF.bit.b1
#define     b4msFlag    mainRunF.bit.b2
//------------------------------------------------------ 接收主板信息的解码数据
//byte1
extern      T_BYTE      mDeviceStF;  //主板检测设备状态
#define     bSwitch_High    mDeviceStF.bit.b0   //高压开关, 接通(启动)低电平, 断开(停止)高电平
#define     bValve_Waste    mDeviceStF.bit.b1   //废水阀
#define     bValve_Inlet    mDeviceStF.bit.b2   //进水阀
#define     bPump_Booster   mDeviceStF.bit.b3   //增压泵
//byte2
extern      uint8_t     mWorkMode;      //工作状态,0-待机,1-制水,2-冲洗
//byte3
extern      uint8_t     mWifiSt;        //wifi状态
//byte4
extern      uint8_t     mError;         //故障
//byte5, byte6 预留
//------------------------------------------------------ 发送主板数据
//byte1
extern      T_BYTE      dCtrlCmd;
#define     bWashing    dCtrlCmd.bit.b0     //冲洗
#define     bEntrReset  dCtrlCmd.bit.b1     //进入复位操作
#define     bSelcFilter dCtrlCmd.bit.b2     //选择滤芯
#define     bReset      dCtrlCmd.bit.b3     //复位滤芯
#define     bFastCheck  dCtrlCmd.bit.b4     //进入快检模式
//byte2
extern      T_BYTE      dFilterF;
#define     bPPLifeDone dFilterF.bit.b0     //PP滤芯寿命到达
#define     bROLifeDone dFilterF.bit.b1     //RO滤芯寿命到达
#define     bFilterFast dFilterF.bit.b2     //滤芯快检没送
#define     bFilterSets dFilterF.bit.b3     //滤芯寿命设置中
//byte3
//gFilter.PP_work.wPercent                  //PP滤芯寿命百分比
//byte4
//gFilter.RO_work.wPercent                  //RO滤芯寿命百分比
//byte5, byte6预留
#include <cms.h>
/*******************************************************
                    系统操作
********************************************************/
#define     EGI()       (GIE=1)
#define     DGI()       (GIE=0)
#define     clrwdt()    asm("CLRWDT")
#define     nop()       asm("NOP")
/*******************************************************
                    类型定义
********************************************************/
// 基本类型定义
#if 1
typedef   signed            char int8_t;
typedef   signed short      int int16_t;
typedef   signed            long  int32_t;
typedef unsigned            char uint8_t;
typedef unsigned short      int  uint16_t;
typedef unsigned              long uint32_t;
typedef int32_t  s32;
typedef int16_t  s16;
typedef int8_t   s8;
typedef uint32_t  u32;
typedef uint16_t  u16;
typedef uint8_t   u8;
typedef uint8_t     uchar;
#endif
//可取位类型
typedef union{
    uint8_t byte;
    struct bit{
        uint8_t b0:1; 
        uint8_t b1:1; 
        uint8_t b2:1; 
        uint8_t b3:1;
        uint8_t b4:1; 
        uint8_t b5:1; 
        uint8_t b6:1;
        uint8_t b7:1;
    }bit;
}T_BYTE;
//字长类型
typedef union{
    uint16_t word;
    uint8_t byte[2];
}uWORD;
/*******************************************************
                    宏定义
********************************************************/
#define TRUE                1
#define FALSE               0
#define ON                  1
#define OFF                 0
/*******************************************************
                    位定义
********************************************************/
#define    Set(x,y)    ((x) |= (1 << (y)))                //位置1
#define    Clr(x,y)    ((x) &= ~ (1 << (y)))            //位清0
#define    b0(x,y)        (((x) & (1 << (y))) == 0)        //位0判断 if(b0(x,y)) 判断是否为0
#define    b1(x,y)        ((x) & (1 << (y)))                //位1判断 if(b1(x,y)) 判断是否为1
/*******************************************************
                    高低字节定义
********************************************************/
#define HBYTE( v1 )          ( (uint8_t)((v1) >> 8) )
#define LBYTE( v1 )          ( (uint8_t)((v1) & 0xFF) )
/*******************************************************/
tkey
/////////////////////////////////////触摸按键//////////////////////////////////////
//variable
TKEY_T      gtkey;
/**********************************************************
函数名称: tkeyProc()
函数功能: 按键处理
入口参数: 无
出口参数: 按键事件-event 
备    注: 4MS
**********************************************************/
uint8_t tkeyProc()
{
    //filter
    if(gtkey.Map != READ_TKEY())
    {
        if((++gtkey.Debounce) >= DEBOUNCE_TICK)
        {            
            gtkey.Map   = READ_TKEY();
            gtkey.Debounce = 0;
        }
    }
    else
    {
        gtkey.Debounce = 0;
    }
    //tick count
    if(gtkey.State > 0)  gtkey.Tick++;
    //tkey state machine
    switch(gtkey.State)
    {
        case 0:
            //初始->按下, 超时->完全释放(重置)
            if(gtkey.Map != NO_TKEY)
            {                    
                gtkey.Tick  = 0;
                gtkey.State = 1;
            }
            else
            {
                gtkey.Tick  = 0;
                gtkey.Event = NO_EVE;
            }
        break;
        case 1:
            //按下->松手(释放), 按下->长按
            if(gtkey.Map == NO_TKEY)
            {
                gtkey.Tick = 0;
                gtkey.Event = EVE_CLICK;
                gtkey.State = 2;
            }
            else if(gtkey.Tick >= KTICK_200MS)
            {
                gtkey.Tick = 0;
                //gtkey.Event = EVE_CLICK;
                gtkey.State = 4;
            }
        break;
        case 2:
            //松手->按下(连按), 松手->超时完全释放
            if(gtkey.Map != NO_TKEY)
            {
                gtkey.Tick  = 0;
                gtkey.State = 3;
            }
            else if(gtkey.Tick >= KTICK_200MS)
            {
                gtkey.Tick   = 0;
                gtkey.Event  = EVE_NO;                    
                gtkey.State  = 0;
            }
        break;
        case 3:
            //按下(连按)->松手(释放), 按下(连按)->按下超时->强制释放
            if(gtkey.Map == NO_TKEY)
            {
                gtkey.Tick = 0;
                gtkey.Event = EVE_REPEAT;
                gtkey.State = 2;
            }
            else if(gtkey.Tick >= KTICK_200MS)
            {
                gtkey.Tick       = 0;
                gtkey.Event      = EVE_NO;                    
                gtkey.State      = 0;
            }
        break;
        case 4:
            //长按->响应, 长按->松手(释放)
            if(gtkey.Map != NO_TKEY)
            {
                if(gtkey.Tick == KTICK_3S)
                {
                    //3s触发一次
                    gtkey.Event = EVE_HOLD;
                }
            }
            else
            {
                gtkey.State = 0;
                gtkey.Tick = 0;
            }
        break;
        default:
            gtkey.State = 0;
            gtkey.Tick = 0;
        break;
    }   //end of switch(gtkey.State)
    //返回事件
    return gtkey.Event;
}   //end of tkeyProc()
/////////////////////////////////////触摸按键//////////////////////////////////////
#ifndef __TKEY_H
#define __TKEY_H
///////////////////////// include head file //////////////////////////////
#include    "typedef.h"
#include    "Touch_Kscan_Library.h"
///////////////////////// operater define //////////////////////////////
#define     READ_TKEY()         (_CMS_KeyFlag[0] & 0x01)   //bit0
///////////////////////// constant define //////////////////////////////
//4ms
#define     KTICK_200MS         50
#define     KTICK_3S            750
#define     DEBOUNCE_TICK       10   //40ms, 抖动时间
#define     NO_TKEY             0
///////////////////////// type define //////////////////////////////
//事件
enum e_EVE{
    EVE_NO      = 0x00,
    EVE_CLICK   = 0x01,     //短按松手、开始进入长按
    EVE_REPEAT  = 0x02,     //连按(重复)
    EVE_HOLD    = 0x10,     //长按(接触保持)
};
//type
typedef struct{
    uint8_t Event;
    uint8_t Map;
    uint8_t State;
    uint8_t Debounce;
    uint8_t Tick;
}TKEY_T;
/**********************************************************
函数名称: tkeyProc()
函数功能: 按键处理
入口参数: 无
出口参数: 按键事件-event 
备    注: 4MS
**********************************************************/
uint8_t tkeyProc();
#endif
isr
#include "public.h"
volatile    T_BYTE  mainRunF;
volatile uint8_t gRun1msCnt;
/***********************************************************************
函数功能:中断入口函数
***********************************************************************/
void interrupt isr()
{
    //定时器2中断, 125us
    if(TMR2IF)
    {
        TMR2IF = 0;
        b250usFlgg = ~b250usFlgg;
        if(b250usFlgg)
        {
            if(++gRun1msCnt >= 4)
            {
                gRun1msCnt = 0;
                b1msFlgg = 1;
            }
        }
        else
        {
            //低电压检测
            #ifdef USE_LVD_MD
            if(isLowVolt())
            {
                //计算持续时间
                if(glvdCnt < 255) 
                    glvdCnt++;
            }
            else
            {
                //计数清零
                glvdCnt = 0;
            }
            #endif
            //软串口驱动
            suart_phydriver();
            //主板通讯驱动
            main_board_isr();
        }
        //获取触摸键值, 扫描时间125us
        __CMS_GetTouchKeyValue();
        //蜂鸣器输出
        #ifdef BUZZER_EN
            BUZ_OUT();
        #endif
    }
#ifdef  LVD_INT_EN
    else 
    if(LVDIF)
    {
        //掉电标志
        LVDIF = 0;  //
    }
#endif
    else
    {
        PIR1 = 0;
        PIR2 = 0;
    }
}
filter
#include    "filter.h"
//-----------------滤芯
typedef struct{
    //滤芯1-PPC滤芯(PP棉+碳棒)
    filter_work_life_t PP_work;
//    filter_use_life_t  PP_use;
    //滤芯2-RO滤芯(反渗透膜)
    filter_work_life_t RO_work;
//    filter_use_life_t RO_use;
    //标志
}filter_t;
///////////////////////variable define/////////////////////////
filter_t    gFilter;    //滤芯对象
T_BYTE        filterF;    //滤芯标志
//pp滤芯工作计时
void PP_Work_Count(uint8_t cnt)
{
    if(!PP_LIFE_DONE)   //寿命未到达
        {
        gFilter.PP_work.wLife += cnt;
        if(gFilter.PP_work.wLife >= PP_WORK_LIFE)
            {
            PP_LIFE_DONE = 1;
            gFilter.PP_work.wPercent = 0;
        }
        else
        {
            gFilter.PP_work.wPercent = (uint8_t)(gFilter.PP_work.wLife / PP_WORK_LIFE);
        }
    }
}
//RO滤芯计数函数
void RO_Work_Count(uint8_t cnt)
{
    if(!RO_LIFE_DONE)   //寿命未到达
        {
        gFilter.RO_work.wLife += cnt;
        if(gFilter.RO_work.wLife >= RO_WORK_LIFE)
            {
            RO_LIFE_DONE = 1;
            gFilter.RO_work.wPercent = 0;
        }
        else
        {
            gFilter.RO_work.wPercent = (uint8_t)(gFilter.RO_work.wLife / RO_WORK_LIFE);
        }
    }
}
#if 0
uint8_t PP_Filter_CheckSum()
{
    uint8_t checksum;
    checksum = (uint8_t)( HBYTE(gFilter.PP_work.wLife)
                        +LBYTE(gFilter.PP_work.wLife)
                        +HBYTE(gFilter.PP_work.wMinCnt)
                        +LBYTE(gFilter.PP_work.wMinCnt) );
   return checksum;
}
uint8_t RO_Filter_CheckSum()
{
    uint8_t checksum;
    checksum = (uint8_t)( HBYTE(gFilter.RO_work.wLife)
                        +LBYTE(gFilter.RO_work.wLife)
                        +HBYTE(gFilter.RO_work.wMinCnt)
                        +LBYTE(gFilter.RO_work.wMinCnt) );
   return checksum;
}
#endif
void filter_Init()  //初次上电
{
    gFilter.PP_work.wLife = 0;
    gFilter.PP_work.wLifeSave = 0;
    gFilter.PP_work.wMinCnt = 0;
    gFilter.PP_work.wPercent = 100; //滤芯初始寿命百分百
    gFilter.RO_work.wLife = 0;
    gFilter.RO_work.wLifeSave = 0;
    gFilter.RO_work.wMinCnt = 0;
    gFilter.RO_work.wPercent = 100; //滤芯初始寿命百分百
//清除标志
    filterF.byte = 0;
}
//滤芯寿命处理函数
void filter_Process()   //500ms
{
    //-----------------------------------使用寿命
    //预留
    //-----------------------------------工作寿命
    if(bPump_Booster)       //增压泵开启
    {
        gFilter.PP_work.wMinCnt++;
        gFilter.RO_work.wMinCnt++;
    }
    //快检
    if(FILTER_FAST)
    {
        //快检按1s代表1h计算, 0.5s代表30分钟
        //每次进入, +30
        PP_Work_Count(30);
        RO_Work_Count(30);
    }
    else
    if(gFilter.PP_work.wMinCnt >= COUNT_ONE_MIN)
    {
        //一分钟进入, +1
        PP_Work_Count(1);
        RO_Work_Count(1);
    }
}
//滤芯复位, 0-PP滤芯
void filter_Reset(uint8_t type)
{
    //PP滤芯
    if(0==type)
    {
        gFilter.PP_work.wLife = 0;
        gFilter.PP_work.wLifeSave = 0;
        gFilter.PP_work.wMinCnt = 0;
        gFilter.PP_work.wPercent = 100; //滤芯初始寿命百分百
        PP_LIFE_DONE = 0;
        //更新记忆数据
        //PP_Filter_Save(); 
        //仅掉电记忆数据
    }
    //RO滤芯
    else
    {
        gFilter.RO_work.wLife = 0;
        gFilter.RO_work.wLifeSave = 0;
        gFilter.RO_work.wMinCnt = 0;
        gFilter.RO_work.wPercent = 100; //滤芯初始寿命百分百
        RO_LIFE_DONE = 0;
        //更新记忆数据
       // RO_Filter_Save();
    }
}
//滤芯进入快检模式
void filter_entr_FastCheck()
{
    //进入快检
    FILTER_FAST = 1;
    //备份当前寿命
    gFilter.PP_work.wLifeSave = gFilter.PP_work.wLife;
    gFilter.RO_work.wLifeSave = gFilter.RO_work.wLife;
}
//滤芯退出快检模式
//滤芯快检寿命到达
    //1. 报警指示完毕后
    //2. 报警指示中按键
//机器断电
void filter_exit_FastCheck()
{
    //退出快检
    FILTER_FAST = 0;
    //恢复进入快检前寿命
    gFilter.PP_work.wLife = gFilter.PP_work.wLifeSave;
    gFilter.RO_work.wLife = gFilter.RO_work.wLifeSave;
    //检查快检期间增加使用的寿命
    while(gFilter.PP_work.wMinCnt >= COUNT_ONE_MIN)
    {
        gFilter.PP_work.wMinCnt -= COUNT_ONE_MIN;        
        gFilter.PP_work.wLife += 1;
    }
    if(gFilter.RO_work.wMinCnt >= COUNT_ONE_MIN)
    {
        gFilter.RO_work.wMinCnt -= COUNT_ONE_MIN;
        gFilter.RO_work.wLife += 1;
    }
    //清除滤芯寿命到达标志
    PP_LIFE_DONE = 0;
    RO_LIFE_DONE = 0;
}
//保存数据
void filter_Save()
{
//------------------------------------------------------------------------------------
    ////////////////PP滤芯////////////////////
//工作寿命
    eeprom_Write(EEP_ADDR_PP_WLIFE_H, HBYTE(gFilter.PP_work.wLife));
    eeprom_Write(EEP_ADDR_PP_WLIFE_L, LBYTE(gFilter.PP_work.wLife));
    eeprom_Write(EEP_ADDR_PP_WMIN_H, HBYTE(gFilter.PP_work.wMinCnt));
    eeprom_Write(EEP_ADDR_PP_WMIN_L, LBYTE(gFilter.PP_work.wMinCnt));
//百分比
    eeprom_Write(EADR_PP_PERCENT, gFilter.PP_work.wPercent);
//------------------------------------------------------------------------------------
    ////////////////PP滤芯////////////////////
//工作寿命
    eeprom_Write(EEP_ADDR_RO_WLIFE_H, HBYTE(gFilter.RO_work.wLife));
    eeprom_Write(EEP_ADDR_RO_WLIFE_L, LBYTE(gFilter.RO_work.wLife));
    eeprom_Write(EEP_ADDR_RO_WMIN_H, HBYTE(gFilter.RO_work.wMinCnt));
    eeprom_Write(EEP_ADDR_RO_WMIN_L, LBYTE(gFilter.RO_work.wMinCnt));
//百分比
    eeprom_Write(EADR_RO_PERCENT, gFilter.RO_work.wPercent);
}
//记忆恢复
void filter_Memory()
{
    uint8_t x, y;
//------------------------------------------------------------------------------------
    ////////////////PP滤芯////////////////////
//工作寿命
    x = eeprom_Read(EEP_ADDR_PP_WLIFE_H);
    y = eeprom_Read(EEP_ADDR_PP_WLIFE_L);
    gFilter.PP_work.wLife = (uint16_t)((x<<8) + y);
    if(0xffff == (gFilter.PP_work.wLife & 0xffff))          //读取数据全为1, 认为数据错误
        gFilter.PP_work.wLife = 0;
//工作寿命分钟
    x = eeprom_Read(EEP_ADDR_PP_WMIN_H);
    y = eeprom_Read(EEP_ADDR_PP_WMIN_L);
    gFilter.PP_work.wMinCnt = (uint16_t)((x<<8) + y);
    if(0xffff == (gFilter.PP_work.wMinCnt & 0xffff))
        gFilter.PP_work.wMinCnt = 0;
//百分比
    gFilter.PP_work.wPercent = eeprom_Read(EADR_PP_PERCENT);
    if(0xff == (gFilter.PP_work.wPercent & 0xff))
        gFilter.PP_work.wPercent = 0;
//------------------------------------------------------------------------------------
    ////////////////PP滤芯////////////////////
//工作寿命
    x = eeprom_Read(EEP_ADDR_RO_WLIFE_H);
    y = eeprom_Read(EEP_ADDR_RO_WLIFE_H);
    gFilter.RO_work.wLife = (uint16_t)((x<<8) + y);
    if(0xffff == (gFilter.RO_work.wLife & 0xffff))          //读取数据全为1, 认为数据错误
        gFilter.RO_work.wLife = 0;
//工作寿命分钟
    x = eeprom_Read(EEP_ADDR_RO_WMIN_H);
    y = eeprom_Read(EEP_ADDR_RO_WMIN_L);
    gFilter.RO_work.wMinCnt = (uint16_t)((x<<8) + y);
    if(0xffff == (gFilter.RO_work.wMinCnt & 0xffff))
        gFilter.RO_work.wMinCnt = 0;
//百分比
    gFilter.RO_work.wPercent = eeprom_Read(EADR_RO_PERCENT);
    if(0xff == (gFilter.RO_work.wPercent & 0xff))
        gFilter.RO_work.wPercent = 0;    
}
#ifndef     __FILTER_H
#define     __FILTER_H
#include    "typedef.h"
//-------------------------工作寿命(制水或泵工作时间计数)
typedef struct{
    uint16_t    wLife;      //工作寿命(分钟)
    uint16_t    wLifeSave;  //备份
    uint16_t    wMinCnt;    //分钟计数
    uint8_t     wPercent;   //寿命百分比
}filter_work_life_t;
//-------------------------使用寿命(机器通电时间计数)
typedef struct{
    uint16_t    uLife;      //使用寿命(小时)
    uint16_t    uLifeSave;  //备份
    uint16_t    uHourCnt;   //小时计数
    uint8_t     uPercent;   //使用寿命百分比
}filter_use_life_t;
//滤芯1-PPC滤芯(PP棉+碳棒)
#define     PP_WORK_LIFE        3000    //50小时, 50*60=3000分钟
#define     PP_USE_LIFE         8640    //12个月, 12*30*24=8640小时
//滤芯2-RO滤芯(反渗透膜)
#define     RO_WORK_LIFE        7200    //120小时, 120*60=7200分钟
#define     RO_USE_LIFE         43200   //60个月, 60*30*24=43200小时
//counter
#define     COUNT_ONE_HOUR      7200    //1H=60*60=3600s 3600/(0.5s)=7200
#define     COUNT_ONE_MIN       120     //1M=60s 0.5s计数120
//save in eeprom
#define     EEP_CODE_START        0xa5
#define     EEP_ADDR_START        0
//PP
//工作寿命
#define     EEP_ADDR_PP_WLIFE_H   1
#define     EEP_ADDR_PP_WLIFE_L   2
#define     EEP_ADDR_PP_WMIN_H    3
#define     EEP_ADDR_PP_WMIN_L    4
//使用寿命
#define     EEP_ADDR_PP_ULIFE_H   5
#define     EEP_ADDR_PP_ULIFE_L   6
#define     EEP_ADDR_PP_UHOUR_H   7
#define     EEP_ADDR_PP_UHOUR_L   8
//RO
//工作寿命
#define     EEP_ADDR_RO_WLIFE_H   9
#define     EEP_ADDR_RO_WLIFE_L   10
#define     EEP_ADDR_RO_WMIN_H    11
#define     EEP_ADDR_RO_WMIN_L    12
//使用寿命
#define     EEP_ADDR_RO_ULIFE_H   13
#define     EEP_ADDR_RO_ULIFE_L   14
#define     EEP_ADDR_RO_UHOUR_H   15
#define     EEP_ADDR_RO_UHOUR_L   16
//校验
#define     EEP_ADDR_PP_CHECK     17
#define     EEP_ADDR_RO_CHECK     18
//百分比
#define     EADR_PP_PERCENT       19
#define     EADR_RO_PERCENT       20
//variable declear
extern  filter_t    gFilter;    //滤芯对象
extern  T_BYTE        filterF;    //滤芯标志
//------------------
#define    RO_LIFE_DONE    filterF.bit.b0        //RO寿命到达
#define    PP_LIFE_DONE    filterF.bit.b1        //PP寿命到达
#define    FILTER_FAST        filterF.bit.b2        //快检
//#define    RO_LIFE_SAVE    filterF.bit.b3      //RO寿命记忆更新
//#define    PP_LIFE_SAVE    filterF.bit.b4      //PP寿命记忆更新
#define    FILTER_WORKING    filterF.bit.b5      //滤芯工作中(增压泵开启中)
#define    RO_LIFE_RESET    filterF.bit.b6      //RO滤芯复位
#define    PP_LIFE_RESET    filterF.bit.b7      //PP滤芯复位
#endif
mcu
#include    "cms79f_mcu.h"
//mcu操作
void mcu_init()
{
   //禁止中断
    INTCON = 0x00;
   //外设中断请求寄存器
    PIR1 = 0;
    PIR2 = 0;
   //外设中断允许寄存器
    PIE1 = 0;
    PIE2 = 0;
    //设置系统时钟
    OPTION_REG = 0;     //预分频器分配给 TIMER0 模块
    OSCCON = 0x61;      //振荡器控制, Fsys=Fosc/2=8MHz
    //看门狗
    WDTCON = 0x01;      //使能定时器, 18ms
    clrwdt();
    //GPIO
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    //CMS79FT73x/CMS79F73x系列芯片使用触摸功能时RD2口需作为输出口
    //TRISD = 0x00;
    TRISD = 0x03;
    WPUA  = 0x00;
    WPUB  = 0x00;
    WPUC  = 0x00;
    WPUD  = 0x00;
    IOCB  = 0x00;
#ifdef USE_ADC_MD
    //ADC
    ADCON0 = 0x01;  //使能ADC
    ADCON1 = 0x00;  //数据左对齐, 12bit
    ADIE   = 0;
#endif
#ifdef USE_TMR2_MD
    //timer2
    TMR2   = 0;
    T2CON  = T2_CTL_SET;    //使能TMR2, 预分频1:1, 后分频1:2
    PR2    = T2_COUNT;      //125us
    TMR2IE = 1;             //使能TMR2中断
#endif
    //低电压检测
#ifdef  USE_LVD_MD
    LVDCON = LVD_SET_VAL;   //设置掉电检测电压
//不中断, 检测LVD_RES标志
//    LVDIE = 1;              //允许LVD中断, 中断中检测LVDIF标志位
#endif
    PEIE   = 1;
}
void mcu_refrush(void)
{
    //asm("clrwdt");
    WDTCON = 0x01;
    OPTION_REG = 0;
    PR2 = T2_COUNT;
    if(T2_CTL_SET != T2CON)
        T2CON = T2_CTL_SET;
//    INTCON = 0XC0;
//系统时钟
    OSCCON = 0x61;
}
#ifdef USE_ADC_MD
    //作为ADC结果临时存储区
    uint16_t AD_DATA;
    /**********************************************************
    函数名称: ad_Convert()
    函数功能: 开始AD转换
    入口参数: frq-ADC时钟, ch-转换通道
    出口参数: 无 
    备    注: Analog-to-digital conversion
    **********************************************************/
    uint8_t ad_Convert(unsigned char frq, unsigned char ch)
    {
        uint16_t wt;
        ADCON0 = (frq<<6) | (ch&0x07 << 2) | (AD_EN<<0);
        if(ch & 0x08)
            ADCON1 |= (1<<6);
        wt = 0x0fff;
        clrwdt();
        nop(); nop();
        GODONE = 1;
        while(GODONE)
        {
            nop();
            if(0 == (--wt))
                return 0;
        }
        AD_DATA = (uint16_t)((ADRESH + ADRESL)>>4);
        return 1;
    }
#endif
#ifdef USE_EEPROM_MD
    /***********************************************
    函数名称: eeprom_Write
    函数功能:写数据寄存器
    入口参数:Addr - 写入地址
              Value - 写入数值
    出口参数:返回值 0 - 写未准备好 1 - 写完毕
    备注:
    ************************************************/
    unsigned char eeprom_Write(unsigned char Addr,unsigned char Value)
    {
        static volatile bit B_GIE_On;
        static volatile unsigned char i = 0;
        if(WR)                                    //写还没有结束直接返回
            return 0;
        B_GIE_On = 0;                            //记录进来前是否已经开启中断
        if(GIE)
            B_GIE_On = 1;
        //将要写入的地址放入EEADDR寄存器
        EEADR = Addr;
        EEDAT= Value;                           //将要写入的数据给EEPROM的数据寄存器
        EEPGD = 0;                                //访问数据存储器
        WREN = 1;                                //允许写周期
        GIE = 0;                                //关闭中断
        while(GIE)
        {
            GIE = 0;                            //确保中断已关闭
            if(0 == --i)
                return 0;
        }
        EECON2 = 0x55;                            //给EECON2写入0x55
        EECON2 = 0xaa;                            //给EECON2写入0xaa
        WR = 1;                                    //启动写周期
        asm("nop");
        asm("nop");
        if(B_GIE_On)                            //若原来已开启中断的就开启中断    
            GIE = 1;                                                    
        WREN = 0;                                //禁止写入
        return 1;
    }
    /***********************************************
    函数名称: eeprom_Read
    函数功能:读数据寄存器
    入口参数:Addr - 读取地址
    出口参数:返回读取地址相应数值
    备注:
    ************************************************/
    unsigned char eeprom_Read(unsigned char Addr)
    {            
        //将要写入的地址放入EEADDR寄存器
        EEADR = Addr;
        EEPGD = 0;                            //访问数据存储器
        RD=1;                                //允许读操作
        asm("nop");
        asm("nop");
        return EEDAT;
    }
#endif
#ifdef  USE_LVD_MD
    enum e_D_VOLT{
        LVD_2V2 = 0,
        LVD_2V4,
        LVD_2V7,
        LVD_3V0,
        LVD_3V3,
        LVD_3V7,
        LVD_4V0,
        LVD_4V3,
    };
    enum e_D_LV_EN{
        D_LVOLT_EN = 1,
        D_LVOLT_DIS = 0,
    };
//当 LVD 模块使能后,需要延时 1ms 的时间才能够读取 LVD_RES 位,
//因为内部做了滤波处理,以减少在 VLVD 电压值附近时,LVD 输出结果的频繁波动。
    #define     LVD_SET_VAL ((LVD_4V0<<1) | (D_LVOLT_EN<<0))
    #define     isLowVolt()  {LVD_RES}
    #define     setLVDisr()     (LVDIE = 1)
//LVD 模块有自己的中断标志位,
//当设定好相关的中断使能位,电源电压低于设定的电压值时,会产生 LVD中断,
//中断标志位 LVDIF 将被置 1,中断产生。
#endif
#ifndef __CMS79F_MCU_H
#define __CMS79F_MCU_H
#include    "typedef.h"
//是否使用ADC模块
//#define     USE_ADC_MD
#define       USE_TMR2_MD
#define       USE_EEPROM_MD
#define       USE_LVD_MD    //低电压检测
#ifdef  USE_TMR2_MD 
//TMR2时钟源为系统时钟的四分之一
    enum e_TMR2_OPS{
        T2_OPS_1 = 0,
        T2_OPS_2,
        T2_OPS_3,
        T2_OPS_4,
        T2_OPS_5,
        T2_OPS_6,
        T2_OPS_7,
        T2_OPS_8,
        T2_OPS_9,
        T2_OPS_10,
        T2_OPS_11,
        T2_OPS_12,
        T2_OPS_13,
        T2_OPS_14,
        T2_OPS_15,
        T2_OPS_16,
    };
    enum e_TMR2_ON{
        T2_ON = 1,
        T2_OFF = 0,
    };
    enum e_TMR2_CPS{
        T2_CPS_1 = 0,
        T2_CPS_4,
        T2_CPS_16,
    };
    #define     T2_OUTPS(n)     (n<<3)  //后分频
    #define     T2_SET_ON(n)    (n<<2)  //使能
    #define     T2_CKPS(n)      (n<<0)  //预分频
    //系统时钟16M, T2时钟4M, 预分频1/4得到1MHz
    #define     T2_CTL_SET  T2_OUTPS(T2_OPS_1) | T2_SET_ON(T2_ON) | T2_CKPS(T2_CPS_4)
    #define     T2_COUNT    125     //125us
#endif
#ifdef USE_ADC_MD
    //ADC时钟
    enum e_AD_FOSC{
        FOSC_8  = 0,
        FOSC_16 = 1,
        FOSC_32 = 2,
        FOSC_RC = 3
    };
    enum e_AN_SEL{
        AD_AN0 = 0,
        AD_AN1 = 1,
        AD_AN2 = 2,
        AD_AN3 = 3,
        AD_AN4 = 4,
        AD_AN5 = 5,
        AD_AN6 = 6,
        AD_AN7 = 7,
        AD_AN8 = 8,
        AD_AN9 = 9,
        AD_AN10 = 10,
        AD_AN11 = 11,
        AD_AN12 = 12,
        AD_AN13 = 13,
        AD_AN14 = 14,
        AD_AN15 = 15,
        AD_AN16 = 16,
        AD_AN17 = 17,
        AD_AN18 = 18,
        AD_AN19 = 19,
        AD_AN20 = 20,
        AD_AN21 = 21,
        AD_AN22 = 22,
        AD_AN23 = 23,
        AD_AN24 = 24,
        AD_AN25 = 25,
        AD_AN_1V2 = 26, //1.2V固定参考看呀
    };
    //ADC使能
    enum e_ADEN{
        AD_DIS  = 0,
        AD_EN   = 1,
    };
    //ADC结果
    #define     AD_12BIT_DAT()      
    #define     AD_8BIT_DAT()       (uchar)(ADRESH)
    //临时结果区
    extern uint16_t AD_DATA;
    /**********************************************************
    函数名称: ad_Convert()
    函数功能: 开始AD转换
    入口参数: frq-ADC时钟, ch-转换通道
    出口参数: 无 
    备    注: Analog-to-digital conversion
    **********************************************************/
    uint8_t ad_Convert(unsigned char frq, unsigned char ch);
#endif
#ifdef USE_EEPROM_MD
    /***********************************************
    函数名称: eeprom_Write
    函数功能:写数据寄存器
    入口参数:Addr - 写入地址
              Value - 写入数值
    出口参数:返回值 0 - 写未准备好 1 - 写完毕
    备注:
    ************************************************/
    unsigned char eeprom_Write(unsigned char Addr,unsigned char Value);
    /***********************************************
    函数名称: eeprom_Read
    函数功能:读数据寄存器
    入口参数:Addr - 读取地址
    出口参数:返回读取地址相应数值
    备注:
    ************************************************/
    unsigned char eeprom_Read(unsigned char Addr);
#endif
#endif
main.c
/***********************************************************************
方案说明:
***********************************************************************/
/**********************************************************************/
/*修改说明*/
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
/*头文件*/
#include    <cms.h>
#include    "public.h"
#include    "delay.h"
#include    "Touch_Kscan_Library.h"
/**********************************************************************/
/*全局变量声明*/
/**********************************************************************/
/**********************************************************************/
/***********************************************
函数名称:system_init
函数功能:系统初始化
入口参数:无
出口参数:无
备注:
************************************************/
void system_init()
{
    clrwdt();
    EGI();
    //芯片初始化
    mcu_init();
    Delay_nms(200); //初始化MCU后延时200ms等待系统稳定
    //设备初始化
    //device_init();
    //////////////蜂鸣器////////////////////
    #ifdef  BUZZER_EN
        BUZ_INIT();
        bBuzOnOff = 0;
    #endif
    //应用初始化
    //app_init();
    //使能总中断
    DGI();
}
uint8_t gRun20msCnt;
uint8_t gRun100msCnt;
uint8_t gRun500msCnt;
/***********************************************************************
main主函数
***********************************************************************/
void main(void)
{
    /////////////////////////////////系统初始化/////////////////////////////////
    system_init();
    /////////////////////////////////大循环/////////////////////////////////    
    while(1)
    {
        clrwdt();
        //4ms基准
        if(b1msFlgg)
        {
            b1msFlgg = 0;
            if(++gRun4msCnt >= 4)
            {
                gRun4msCnt = 0;
                __CMS_CheckTouchKey();    //扫描按键, 4ms
                input_Process();
            }
            else if(gRun4msCnt == 1)
            {
                //
            }
            //20ms基准
            //100ms基准
            //500ms基准
        }
    }/////////////////the end while(1)//////////////////////
}
/**********************************************************************/
uint8_t glvdCnt;    //lvd标志计数
bit     blvdVerify; //低电压确认
void lvd_Store()    //4ms
{
    if(glvdCnt >= 4)    //持续检测到一段时间低电压, 认为拔掉了电源(掉电)
    {
        glvdCnt = 0;
        if(!blvdVerify)
        {
            blvdVerify = 1;
            if(FILTER_FAST)
            {
                filter_exit_FastCheck();
            }
            PP_Filter_Save();
            RO_Filter_Save();
            filter_Save();
        }
    }
}
//上电恢复记忆
void power_on_Restor()
{
    if(EEP_CODE_START != eeprom_Read(EEP_ADDR_START))
    {
        //初次上电
        eeprom_Write(EEP_ADDR_START, EEP_CODE_START);
        filter_Init();
    }
    else
    {
        filter_Memory();
    }
}
//输入处理
void input_Process()
{
    uint8_t event;
    event = tkeyProc();
    switch()
}
//---------------------------- 电压状态
uint8_t     gPowerOnCnt;
T_BYTE      powerF;
#define     bpowerOn        powerF.bit.b0       //上电延时等待系统稳定后确认
#define     bpowerOn2s      powerF.bit.b1       //上电2s
#define     bpowerOn10s     powerF.bit.b2       //上电10s
void power_Process()    //100ms
{
    if(gPowerOnCnt<255) gPowerOnCnt++;
    if(!bpowerOn)
    {
        if(gPowerOnCnt >= 2)
        {
            bpowerOn = 1;
        }
    }
    else if(!bpowerOn2s)
    {
        if(gPowerOnCnt >= 20)
        {
            bpowerOn2s = 1;
        }
    }
    else if(!bpowerOn10s)
    {
        if(gPowerOnCnt >= 100)
        {
            bpowerOn10s = 1;
        }
    }
}
                    