//——————————软串口
#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:1bit
case 0:
pSTX = 0;
sSEQsend = 1;
sCntSend = 0;
break;
// 数据位SEND
case 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)
{
// 起始位bit0
case 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;
}
}
}