water tap
//水龙头接口
typedef struct tap_protocol{
uint8_t start; //协议头-0xa5
uint8_t len; //数据长度-0x0b(不包括协议头和长度字节)
uint8_t work_mode; //工作模式
uint8_t wifi_state; //wifi状态
uint8_t in_water_tds_h; //进水tds高8位
uint8_t in_water_tds_l; //进水tds低8位
uint8_t pure_water_tds; //纯水tds
uint8_t filter_life; //滤芯寿命状态
uint8_t error; //故障
uint8_t pbc_life_percent; //pbc滤芯寿命百分比
uint8_t ro_life_percent; //ro滤芯寿命百分比
uint8_t reverse_life_percent; //预留滤芯寿命百分比
uint8_t checksum; //校验和
}t_tap_protocol;
typedef union tap_ptl_buf{
t_tap_protocol tap_dat;
uint8_t buf[13];
}t_tap_ptl_buf;
t_tap_ptl_buf tap;
perified
#define pHIGHSW RB6 //高压开关, 接通(启动)低电平, 断开(停止)高电平
#define pWASTEVALVE RB5 //废水阀, waste valve
#define pINLETVALVE RB4 //进水阀, inlet valve
#define pBOOSTERPUMP RB3 //增压泵, booster pump
//pHighPressSwitch
//p_SW_High
//p_VALVE_Waste
//p_Valve_Inlet
//p_Pump_Booster
typedef enum{
Standby = 0, //待机
Produce, //制水
Washing, //冲洗
}e_work_mode;
uint8_t gWorkMode;
//高压开关, 接通(启动)低电平, 断开(停止)高电平
//漏水检测, 正常高电平, 漏水低电平
void work_Proc()
{
switch(gWorkMode)
{
case Standby:
//进水阀关闭、废水阀关闭、增压泵关闭
break;
case Produce:
//进水阀开启、废水阀关闭、增压泵开启
break;
case Washing:
//进水阀开启、废水阀开启、增压泵开启
break;
}
}
isr
bit g_bRun250usFlag;
bit g_bRun1msFlag;
uint8_t g_u8Run1msCnt;
//全部中断入口
void interrupt isr()
{
uint8_t Res1;
//TMR2 125us中断
if(TMR2IF)
{
TMR2IF = 0;
g_bRun250usFlag = ~g_bRun250usFlag;
if(g_bRun250usFlag)
{
if(++g_u8Run1msCnt >= 4)
{
g_u8Run1msCnt = 0;
g_bRun1msFlag = 1;
}
}
else
{
//串口发送数据
if(TRMT1) //发送数据寄存器空, 可以写入数据
{
if(wait_send_len > 0)
{
TXREG1 = *tx_buf_ptr;
tx_buf_ptr++;
wait_send_len--;
}
}
if(TRMT0)
{
//TXREG1 = 0xff;
}
}
}
else
if(RC0IF)
{
if(FERR0)
{
//读RCREG0
RCREG0; //帧错误
return;
}
}
else
//串口1
//-------------------------------------------
//接收控制,如果接收标志位为1,说明有数据接收完毕
//RCIF在寄存器被读出后自动清零
if(RC1IF) //读RCREG1清零
{
#if 0
if(FERR1)
{
RCREG1; //帧错误
return;
}
Recebuffer[rececount] = RCREG1; //将接收缓冲区内容读出
rececount++;
if(rececount >= 4) //接收完一帧数据,处理数据
{
rececount = 0;
}
if(OERR1) //如果有溢出错误
{
CREN1 = 0; //清零CREN位可将OERR位清零
CREN1 = 1; //再次将CREN置一,以允许继续接收
}
#endif
//一帧24字节,9600波特率, 24*9*104=22464us=22ms, 接收一帧数据约要22ms
Res1 = RCREG1;
if(FERR1) //帧错误
return;
#if 0
uart_receive_input(Res1);
#else
//wifi
if(1 == rx_buf_out - rx_buf_in) {
//串口接收缓存已满
}else if((rx_buf_in > rx_buf_out) && ((rx_buf_in - rx_buf_out) >= sizeof(wifi_uart_rx_buf))) {
//串口接收缓存已满
}else {
//串口接收缓存未满
if(rx_buf_in >= (unsigned char *)(wifi_uart_rx_buf + sizeof(wifi_uart_rx_buf))) {
rx_buf_in = (unsigned char *)(wifi_uart_rx_buf);
}
*rx_buf_in ++ = Res1;
}
#endif
}
else
{
//清除所有中断请求标志
PIR1 = 0; //外设中断请求寄存器1
PIR2 = 0; //外设中断请求寄存器2
}
}
public
#ifndef __PUBLIC_H
#define __PUBLIC_H
//===============================================================================
// Unit : 广东贝磁电子科技有限公司研发部软件组 |
// Product Type : 净水器 |
// Customer & Model : 碧信(RO-800G-WIFI) |
// MCU : CMS79FT7381 - SOP28 |
// Volt : 5V |
// Oscillator : 16MHz |
// Watchdog : Enable |
// Reset : |
// Description : |
// Author : 陶茂亮 |
// Version Info : V1.0.0-20220610 create |
// Program Language : C |
//-----------------------------------Oooo---------------------------------------+
/*
引脚定义:
//重定义为15-28pin
01. AN3/RA3 -- DISP_DA 显示通信DAT
02. AN4/RA4 -- DISP_CK 显示通信CLK
03. AN5/RA5 -- BUZ
04. AN6/RA6 -- MOTOR_PHASE_D
05. AN7/RA7 -- MOTOR_PHASE_C
06. AN8/RB0 -- MOTOR_PHASE_B
07. AN9/RB1 -- MOTOR_PHASE_A
08. AN10/RB2 --
09. RX1/AN11/RB3 -- BOOST_PUMP 增压泵
10. TX1/AN12/RB4 -- INLET_VALVE 进水阀
11. AN13/RB5 -- WASTE_VALVE 废水阀
12. AN14/RB6 -- HIGH_PRESS_SWITCH 高压开关
13. GND --
14. VDD --
//重定义为1-14pin
15. AN16/RD2 --
16. ICSPDAT/TX0/SCL/AN24/RD1 -- TAP_TX 水龙头通信TX
17. ICSPCLK/RX0/SDA/AN25/RD0 -- TAP_RX 水龙头通信RX
18. TX1/SDA/AN16/RC7 -- WIFI_TX
19. RX1/SCL/AN17/RC6 -- WIFI_RX
20. AN18/RC5 -- TDS_PURE_OUT1
21. AN19/RC4 -- TDS_PURE_AD 纯水
22. AN20/RC3 -- TDS_PURE_OUT2
23. AN21/RC2 -- TDS_RAW_OUT1
24. AN22/RC1 -- TDS_RAW_AD 原水
25. AN23/RC0 -- TDS_RAW_OUT2
26. AN0/RA0 --
27. AN1/RA1 -- LEAKING 漏水
28. AN2/RA2 -- NTC 温度
*/
#define DEV_produce_water_module //制水
#define DEV_wifi //wifi
#define DEV_water_cap //水龙头
#define DEV_display_board //显示板
#define DEV_buzzer //蜂鸣器
#define DEV_tds_module //tds
#define DEV_leaking //漏水
#define DEV_filter_life //滤芯寿命
//工作模式
typedef enum{
standby = 0, //待机
produce_water, //制水
wash, //冲洗
}purifier_mode_e;
//设备状态
typedef struct{
uint8_t switch_highpress : 1; //高压开关(High pressure switch)
uint8_t pump_boost : 1; //增压泵
uint8_t valve_inlet : 1; //进水阀
uint8_t valve_waste : 1; //废水阀(waste water)
uint8_t leaking : 1; //漏水
uint8_t : 3;
}dev_status_t;
typedef struct{
uint8_t temperature; //用于计算TDS值
uint16_t tds_inlet; //进水TDS
uint16_t tds_pure; //纯水TDS
}tds_value_t;
//沸水流量控制器
typedef struct{
//步进电机控制值
}waste_flow_regulator_t;
//滤芯寿命
typedef struct{
uint16_t produce_hour; //制水时间(小时)
uint16_t produce_hour_cnt; //制水时间计时
uint16_t poweron_hour; //通电时间(小时)
uint16_t poweron_hour_cnt; //通电时间计时
}filter_ele_life_t;
//滤芯
typedef struct{
filter_ele_life_t PBC_Filter; //PBC复合滤芯寿命
filter_ele_life_t RO_Filter; //RO复合滤芯寿命
}filter_ele_t;
typedef struct{
uint8_t status;
}wifi_status_t;
typedef struct{
purifier_mode_e sys_mode; //工作模式
dev_status_t dev_st; //设备工作状态
tds_value_t tds; //tds值
waste_flow_regulator_t rgl;
filter_ele_t filter;
}purifier_status_t; //净水器状态结构体
/*
1. 高压开关
2. 步进电机-废水比调节
3. 漏水检测
4. 水龙头(智能、灯环), 串口通信
5. 进水阀、废水阀
6. 增压泵
7. 蜂鸣器
8. wifi, 串口通信
9. 纯水TDS、进水TDS
10、温度NTC
11. 灯板, 自定义通信协议
按功能对象划分
> 制水、冲洗操作
> 高压开关、步进电机、进水阀、废水阀、增压泵
> 外部通信(指示、输入) - 操作显示
> wifi、水龙头、灯板
> 蜂鸣器
> TDS检测
> 纯水TDS、进水TDS
> 温度NTC
> 故障
> 漏水检测
*/
//#define EN_FILTER_LIFE_PRODUCE_WATER //使能计算滤芯制水时间寿命
typedef struct{
#ifdef EN_FILTER_LIFE_PRODUCE_WATER
uint16_t min_prdt_wtr; //制水时间(分钟)
uint8_t sec_prdt_wtr; //制水时间(秒)
#endif
uint16_t hour_power; //通电时间(小时)
uint16_t hcnt_power; //通电时间(计数至小时)
}filter_life_t; //滤芯寿命
//tds_life_t PBC_filter;
//tds_life_t RO_filter;
//优先存储通电小时、制水分钟这些紧急的,
//这样即便后面的没有保存成功也能将寿命计时的影响降到最低
#define EEP_DATA_START_1 0xa5
#define EEP_DATA_START_2 0x5a
#define EEP_ADDR_START_1 0
#define EEP_ADDR_START_2 1
//PBC膜寿命记忆地址
#define EEP_ADDR_PBC_MIN_PROD_L 2
#define EEP_ADDR_PBC_MIN_PROD_H 3
#define EEP_ADDR_PBC_SEC_PROD 4
#define EEP_ADDR_PBC_HOUR_PWR_L 5
#define EEP_ADDR_PBC_HOUR_PWR_H 6
#define EEP_ADDR_PBC_HOURC_PWR_L 7
#define EEP_ADDR_PBC_HOURC_PWR_H 8
//RO膜寿命记忆地址
#define EEP_ADDR_RO_MIN_PROD_L 9
#define EEP_ADDR_RO_MIN_PROD_H 10
#define EEP_ADDR_RO_SEC_PROD 11
#define EEP_ADDR_RO_HOUR_PWR_L 12
#define EEP_ADDR_RO_HOUR_PWR_H 13
#define EEP_ADDR_RO_HCNT_PWR_L 14
#define EEP_ADDR_RO_HCNT_PWR_H 15
//校验
#define EEP_ADDR_CRC_DATA 16
#endif
main
#include "public.h"
#include "./JWBR2S_sdk/wifi.h"
void app_init()
{
//wifi模块初始化
wifi_protocol_init();
}
/**********************************************************
函数名称: System_Init()
函数功能: 系统初始化
入口参数: 无
出口参数: 无
**********************************************************/
void System_Init()
{
clrwdt();
dgi();
mcu_init();
drive_rigister();
app_init();
egi();
}
/**********************************************************
函数名称: main
函数功能: 主函数
入口参数: 无
出口参数: 无
**********************************************************/
void main()
{
#if 1
/******************************************************************/
asm("clrwdt");
Init_ic();
Delay_nms(200); //上电延时200ms
Init_ram(); //上电给初值
#endif
System_Init();
while(1)
{
clrwdt(); //每次进入循环都将清看门狗
//wifi服务程序
wifi_uart_service();
}
}
mcu
#include "cms79f7xx_mcu.h"
#define T2_CTL_SET 0x0c
#define T2_COUNT 250
/***********************************************************************
函数功能:串口1初始化
入口参数:
返回数据:
备注:
***********************************************************************/
void uart1_init()
{
#if 0
SPBRG1 = 102; //设置波特率为9600 bps,误差0.16%
SYNC1 = 0; //0为异步模式,1为同步模式
SCKP1 = 0;
SPEN1 = 1; //允许串口操作
RC1IE = 1; //接收中断
TX1IE = 0; //发送中断
RX9EN1 = 0; //0为8位接收,1为9位接收
TX9EN1 = 0; //0为8位发送,1为9位发送
CREN1 = 1; //0为禁止接收,1为使能接收
TXEN1 = 1; //0为禁止发送,1为使能发送
#else
//异步模式, 数据不取反, 8bit数据发送, 发送使能
TXSTA1 = 0b00100000;
//使能串口, 8bit数据接收, 接收使能
RCSTA1 = 0b10011000;
//波特率9600
SPBRG1 = 103;
//使能接收中断, 除能发送中断
RC1IE = 1; //接收中断
TX1IE = 0; //发送中断
#endif
}
/***********************************************************************
函数功能:串口0初始化
入口参数:
返回数据:
备注:
***********************************************************************/
void uart0_init()
{
#if 0
SPBRG0 = 102;
SYNC0 = 0; //异步
SCKP0 = 0; //数据是否取反后到达接收缓冲区
SPEN0 = 1; //使能串口
RC0IE = 1; //接收中断
TX0IE = 0; //发送中断
RX9EN0 = 0;
TX9EN0 = 0;
CREN0 = 1;
TXEN0 = 1;
#else
//TX9EN0=0, TXEN0=1, SYNC0=0, SCKP0=0
//异步模式, 数据不取反, 8bit数据发送, 发送使能
TXSTA0 = 0b00100000;
//SPEN0=1, RX9EN0=0, CREN0=1
//使能串口, 8bit数据接收, 接收使能
RCSTA0 = 0b10011000;
SPBRG0 = 103; //波特率9600
//使能接收中断,除能发送中断
RC0IE = 1;
TX0IE = 0;
#endif
}
/***********************************************************************
函数功能: 芯片初始化
入口参数:
返回数据:
备注:
***********************************************************************/
void mcu_init()
{
nop();
clrwdt();
//禁止中断
INTCON = 0x00;
PIR1 = 0;
PIR2 = 0;
PIE1 = 0;
PIE2 = 0;
//设置系统时钟
OPTION_REG = 0; //预分频器分配给 TIMER0 模块
OSCCON = 0x71; //振荡器控制, Fsys=Fosc/1=16MHz
//看门狗
WDTCON = 0x01; //使能定时器, 18ms
clrwdt();
//GPIO
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;
TRISA = 0x00;
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x00;
WPUA = 0x00;
WPUB = 0x00;
WPUC = 0x00;
WPUD = 0x00;
IOCB = 0x00;
//ADC
ADCON0 = 0x01; //使能ADC
ADCON1 = 0x00; //数据左对齐, 12bit
ADIE = 0;
//timer2
TMR2 = 0;
T2CON = T2_CTL_SET; //使能TMR2, 预分频1:1, 后分频1:2
PR2 = T2_COUNT; //125us
TMR2IE = 1; //使能TMR2中断
//水龙头tap - 串口0
uart0_init();
//wifi - 串口1
uart1_init();
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;
}
#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 ADC_INT_EN() (ADIE=1)
// #define ADC_INT_DIS() (ADIE=0)
// #define CLR_ADC_INT_FLAG() (ADIF=0)
//ADC结果
#define AD_12BIT_DAT()
#define AD_8BIT_DAT() (uchar)(ADRESH)
//作为ADC结果临时存储区
uint16_t AD_DATA;
/**********************************************************
函数名称: adc_Convert()
函数功能: 开始ADC转换
入口参数: frq-ADC时钟, ch-转换通道
出口参数: 无
备 注: Analog-to-digital conversion
**********************************************************/
uint8_t adc_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 = 0;
clrwdt();
nop(); nop();
GODONE = 1;
while(GODONE)
{
nop();
if((++wt) >= 0x0fff)
return 0;
}
AD_DATA = (uint16_t)((ADRESH + ADRESL)>>4);
return 1;
}
#endif
/***********************************************
函数名称: 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;
}