water tap

    1. //水龙头接口
    2. typedef struct tap_protocol{
    3. uint8_t start; //协议头-0xa5
    4. uint8_t len; //数据长度-0x0b(不包括协议头和长度字节)
    5. uint8_t work_mode; //工作模式
    6. uint8_t wifi_state; //wifi状态
    7. uint8_t in_water_tds_h; //进水tds高8位
    8. uint8_t in_water_tds_l; //进水tds低8位
    9. uint8_t pure_water_tds; //纯水tds
    10. uint8_t filter_life; //滤芯寿命状态
    11. uint8_t error; //故障
    12. uint8_t pbc_life_percent; //pbc滤芯寿命百分比
    13. uint8_t ro_life_percent; //ro滤芯寿命百分比
    14. uint8_t reverse_life_percent; //预留滤芯寿命百分比
    15. uint8_t checksum; //校验和
    16. }t_tap_protocol;
    17. typedef union tap_ptl_buf{
    18. t_tap_protocol tap_dat;
    19. uint8_t buf[13];
    20. }t_tap_ptl_buf;
    21. 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;
    }