夜雨聆风学习资料网

ARTICLE · 1271054

【软件和硬件介绍 】基于STM32的智能洗碗机|自动洗涤、WiFi远程控制、多模式运行

【软件和硬件介绍 】基于STM32的智能洗碗机|自动洗涤、WiFi远程控制、多模式运行

 

  🤞大家好,这里是5132单片机毕设项目分享,今天给大家分享的是《基于STM32的智能洗碗机设计》!

实物购买方式见文末!

软件和硬件介绍

——————————————————

基于 STM32 的智能洗碗机

硬件设计 · 软件架构 · 程序设计思路

版本:V2.0

第一部分硬件介绍

1硬件总体方案

整机硬件由「一块自制主控 PCB + 一组外置执行器 + 两路传感器」构成。主控 PCB 以 STM32F103C8T6 最小系统板为插件核心,板上集成电源输入与滤波、OLED 与按键的人机接口、传感器输入接口、三路继电器驱动电路、TB6612FNG 电机驱动、以及 WiFi、风扇、消毒灯、蜂鸣器接口。外置部分为排水泵、补水泵、加热模块、直流电机(喷淋臂)、5W 紫外消毒灯与散热风扇。

这样划分的好处是:主控板只负责「弱电控制」,所有大电流、市电相关的器件全部外置,通过接线端子和继电器隔离。既降低了 PCB 的布线难度与发热风险,也方便替换不同功率的执行器——换一个更大功率的加热模块,只需换继电器后端,主控板不用动。

图 1-1系统总体结构框图

2主控单元与最小系统

2.1为什么选 STM32F103C8T6

资源匹配:本项目需要 1 路 12 位 ADC(水位)、1 路定时器 PWM(电机调速)、1 路 USART(WiFi)、1 路 I2C(OLED),F103C8T6 提供 2 个 ADC、3 个通用定时器、3 个 USART、2 个 I2C,余量充足。

主频足够:72MHz 主频配合硬件乘除法,可以在 20ms 的按键消抖周期内完成一次完整的采集、判断与显示刷新。

生态成熟:标准外设库(SPL)资料丰富、例程齐全,便于快速搭建与后续修改;20KB SRAM 对 128×64 的 OLED 显存(1KB)绰绰有余。

成本与可获得性:最小系统板价格低、易采购,插装在自制板上便于更换与复用。

表 1-1主控芯片主要参数

参数

STM32F103C8T6

内核

ARM Cortex-M3

主频

72MHz(8MHz 外部晶振经 PLL 倍频)

Flash / SRAM

64KB / 20KB

ADC

2 个 12 位 ADC,共 10 个外部通道

定时器

4 个通用定时器(TIM2/3/4/5)+ 2 个高级定时器 + 2 个基本定时器

通信接口

3 个 USART、2 个 I2C、2 个 SPI、1 个 CAN、1 个 USB

封装

LQFP48

2.2时钟与供电

系统时钟由 8MHz 外部晶振经 PLL 9 倍频得到 72MHz;RTC 使用独立的 32.768kHz 晶振(LSE),并由 BT2 纽扣电池座上的 CR2032 单独供电,实现整机断电后继续走时。供电方面,Type-C 接口(USB6)输入 5V,经自锁开关 U40 控制整板总电源,1000μF 电解电容与 100nF 瓷片电容并联滤波——大电容吸收电机与继电器动作时的电流冲击,小电容旁路高频噪声。

3传感器检测电路

3.1DS18B20 水温检测

DS18B20 是单总线数字温度传感器,测温范围 −55~+125℃,在 12 位分辨率下精度可达 0.0625℃。它的优点是输出即数字量,不需要额外的运放或 ADC 校准,单根数据线即可完成通信,抗干扰能力强,特别适合水汽环境。

接线:VDD 接 3.3V、GND 接地、DQ 数据脚接 PB0,数据脚需 4.7kΩ 上拉电阻(板上已有)。

数据格式:原始值为 16 位有符号整数,低 4 位为小数部分,实际温度 = 原始值 × 0.0625。

程序处理:为便于比较与上报,程序内部统一按「实际温度 ×10」的整数保存,例如 23.5℃ 存储为 235,这样既保留了 0.1℃ 分辨率,又避免了浮点运算在中断中的开销。

3.2水位检测

水位采用电阻式水位传感器。其原理是:传感器正面有一排平行裸露的导电条,水浸没高度不同,导电条之间的等效电阻不同,经板上分压后输出 0~3.3V 的模拟电压。电压越高表示浸没越深、水位越高。

接线:信号脚接 PA0(ADC_Channel_0),供电 3.3V。

标定:程序将 ADC 采样值按比例映射为 0~100 的相对水位值,工程中只启用这一路 ADC 通道,其余通道保留为扩展用。

抗干扰:单次采样取多次平均,并对结果做限幅,防止水面波动导致读数跳变引起误判。

工程实现说明:本项目的传感器的抽象层(AD.c)以「传感器表」的形式管理,每一项包含名称、是否启用、端口、引脚、ADC 通道与换算系数。目前表中仅「水位」一项处于启用状态,其余项以注释形式保留,便于后续扩展(如浊度、pH 等)。

4执行机构与驱动电路

4.1三路继电器驱动(排水泵 / 补水泵 / 加热模块)

排水泵、补水泵、加热模块三者都是「通电即工作」的大电流负载,采用继电器做电气隔离与开关控制。选用 SRD-05VDC-SL-C 型 5V 继电器,触点容量满足水泵与加热模块的需求。驱动电路为经典的三极管开关:

控制端:STM32 的 GPIO(PA3 排水泵、PA6 补水泵、PA7 加热模块)经 2kΩ 基极限流电阻接到 S8050 的基极。

开关端:S8050 的集电极接继电器线圈负极,线圈正极接 5V,发射极接地。GPIO 输出高电平时三极管饱和导通,继电器吸合。

续流保护:继电器线圈两端反向并联 1N4007。线圈断电瞬间会产生数倍于电源电压的反向电动势,若无续流二极管,这个尖峰很容易击穿三极管;并联后能量经二极管泄放,三极管得以保护。

软件约定:三路继电器均为「高电平吸合」,程序中统一用 Bit_SET / Bit_RESET 封装,避免各处直接操作寄存器。

表 1-2三路继电器分配

继电器

用途

控制引脚

驱动器件

保护

RLY5

排水泵

PA3

S8050 + 2kΩ 基极电阻

1N4007 续流二极管

RLY6

补水泵(进水泵)

PA6

S8050 + 2kΩ 基极电阻

1N4007 续流二极管

RLY7

加热模块

PA7

S8050 + 2kΩ 基极电阻

1N4007 续流二极管

4.2TB6612FNG 电机驱动(喷淋臂)

喷淋臂由直流电机带动,需要正反转与调速能力。TB6612FNG 是双通道 H 桥驱动芯片,单通道持续电流 1.2A、峰值 3.2A,内置过热与低压保护,逻辑端 3.3V 可直接与 STM32 相连,无需电平转换。

表 1-3TB6612FNG 接线

TB6612FNG 引脚

STM32 引脚

作用

AIN1 / AIN2

PA4 / PA5

方向控制:一高一低正转,一低一高反转,双低滑行

PWMA

PA1(TIM2_CH2)

速度控制:PWM 占空比 0~100%

STBY

接高电平

待机控制,拉高使能

VM / VCC / GND

5V / 3.3V / GND

电机电源 / 逻辑电源 / 地

AO1 / AO2

直流电机

电机输出

PWM 参数计算:系统时钟 72MHz,定时器 TIM2 预分频设为 36,得到 2MHz 计数时钟,再设自动重装值为 100,则 PWM 频率 = 72MHz / 36 / 100 = 20kHz。20kHz 已超出人耳听觉范围上限,电机不会发出啸叫;同时占空比的分辨率为 1%,正好对应 0~100% 的整数百分比调节,软件上用五档(0/25/50/75/100)即可满足洗涤需求。

4.3风扇、消毒灯与蜂鸣器

散热风扇(PA2):由 S8550 PNP 三极管驱动,低电平开启。风扇在风干阶段与加热阶段强制开启,前者用于吹干内胆,后者用于散热。

5W 紫外消毒灯(PB1):经 CN3 端子接入,由开关管控制,低电平点亮,消毒阶段点亮 30 秒。

有源蜂鸣器(PA8):低电平触发。因为有源蜂鸣器内部自带振荡电路,只需给直流电平即可发声,软件上用简单的延时开关实现不同节奏的提示音(按键短鸣、完成长鸣、故障连鸣)。

5人机接口

5.1OLED 显示

显示采用 0.96 英寸 SSD1306 驱动的 128×64 单色 OLED,通过软件 I2C 与主控通信:PB8 作 SCL、PB9 作 SDA。选择软件 I2C 而非硬件 I2C,是因为 SSD1306 的时序要求宽松,软件模拟更易调试,也不占用硬件 I2C 外设。

字库:8×16 ASCII 字库用于数字与英文字母,16×16 汉字字库用于中文提示,另有 8×6 小字库用于参数行。

显存模型:SSD1306 内部为 8 页 × 128 列的显存,每页 8 行像素,一次写入 8 位对应一列的 8 个像素。

寻址方式:本工程采用页内寻址绘制——绘制汉字时分别向第 (行−1)×2 页与第 (行−1)×2+1 页写入上下半个字模,列坐标则按「列号 × 16」计算;绘制 ASCII 时列坐标按「列号 × 8」计算。这样做的代价是同一行内汉字与 ASCII、以及相邻两行之间在显存上会互相覆盖,这也是实际屏幕上出现字符叠加观感的原因(详见《用户操作说明书》中的实机画面)。

刷新策略:只刷新发生变化的区域——时间区每秒刷一次,模式名与状态区在切换时刷新,避免整屏重绘造成闪烁。

5.2按键输入

4 个轻触按键(TS665CJ)分别接 PB3、PB4、PB5、PB6,采用「外部中断下降沿触发 + 定时器 20ms 消抖」的方案。

为什么用中断而不是轮询:洗涤流程中主循环需要维持状态机的节奏,若用轮询会因主循环周期不确定而漏键。

消抖:按键按下时引脚电平会抖动 5~15ms,程序在下降沿中断中置标志,再由 TIM1 的 20ms 周期任务读取并确认电平,确认稳定后才生成键值,既避免了抖动误触发,也不阻塞主循环。

键值映射:按键表按「端口、引脚、键码」三元组定义。需要注意的是,本板因布线关系,键码与引脚并非顺序对应(K1→PB3、K2→PB5、K3→PB6、K4→PB4),程序在表中显式定义,业务层只认键码,不受影响。

表 1-4按键表定义

按键

端口

引脚

键码

有效电平

K1

GPIOB

PB3

1

低电平(按下接地)

K2

GPIOB

PB5

3

低电平

K3

GPIOB

PB6

4

低电平

K4

GPIOB

PB4

2

低电平

6WiFi 通信电路

联网采用 ESP-01S 模块(ESP8266 内核,8MB Flash),出厂烧录机智云 GAgent 固件。模块通过 2×4 排针插座(U37)插装在板上,与主控以串口相连,波特率 9600bps。

接线:模块 TX → PB11(USART3_RX),模块 RX → PB10(USART3_TX),另接 3.3V 与 GND。

为什么用 USART3:USART1 通常用于调试打印,USART2 引脚与其他功能复用,USART3 的 PB10/PB11 在本板上无冲突。

电平注意:ESP-01S 为 3.3V 器件,不能用 5V 直供;模块启动瞬间电流可达 200mA 以上,因此供电端需保证足够的去耦容量。

协议:主控侧在 gizwits_product.c 中把本地变量映射为机智云数据点,由协议层负责打包/解包,业务代码不直接处理协议帧。

7元器件清单概览

整套物料共 32 类、58 件(含备件),按功能可分为主控类、显示与交互类、传感器类、驱动类、执行器类、结构件与接插件类。下表列出主要器件,完整清单见配套的《洗碗机元器件清单汇总.xlsx》。

表 1-5主要元器件(概览)

类别

主要器件

数量

主控

STM32F103C8T6 最小系统板(U47)

1

显示与交互

0.96″ OLED(U2)、TS665CJ 轻触按键、有源蜂鸣器 BUZZER1、红色 LED

1 / 4 / 1 / 4

传感

DS18B20 水温传感器、电阻式水位传感器(U50)

1 / 1

通信

ESP-01S WiFi 模块(U37)

1

驱动

SRD-05VDC-SL-C 继电器 ×3、S8050 ×3、1N4007 ×3、2kΩ ×3、TB6612FNG(U14)

多

执行器

排水泵、补水泵、加热模块、直流电机(U28)、5W 紫外消毒灯(CN3)、散热风扇(CN2)

各 1

电源与接插

Type-C(USB6)、自锁开关(U40)、1000μF(C3)、100nF(C1)、接线端子、XH 端子

多

结构

CR2032 电池座(BT2)、M2 螺丝 ×4

1 / 4

第二部分软件介绍

1软件总体架构

软件基于 STM32F10x 标准外设库开发,采用「前后台」结构:中断服务程序负责时间基准、按键捕获与串口收发,主循环负责业务调度。代码按职责分为四层,上层只依赖下层的接口,不直接触碰寄存器。

表 2-1软件分层结构

层次

主要文件

职责

应用层

main.c、config.c

模式调度、洗涤流程状态机、阈值管理、定时任务、显示内容组织

设备抽象层

config.c 中的设备表 / 按键表 / 传感器表 / 阈值表 / 定时任务表

用「表驱动」统一管理 7 路设备、4 个按键、2 路传感器、3 项阈值参数

板级驱动层

OLED.c、Key.c、AD.c、DS18B20.c、DCMotor.c、Buzzer.c、MyRTC.c、GPIO_OUT.c、GPIO_IN.c

封装各外设的初始化与读写

协议层

gizwits_product.c、gizwits_protocol.c

机智云数据点映射、协议打包与解析、网络对时

表驱动的设计是本工程的一个关键取舍。以设备表为例,7 路执行器被抽象为同一张表,每项记录名称、端口、引脚、有效电平与开关标志,于是「打开加热器」「关闭排水泵」这类操作可以写成同一个函数,传入设备索引即可,避免了 7 段几乎相同的开关代码。按键表、阈值表同理。日后新增一路设备,只需在表中加一行,业务代码无需改动。

表 2-2表驱动数据结构

表

内容

规模

设备表 devices[]

消毒灯 PB1、加热器 PA7、补水泵 PA6、排水泵 PA3、风扇 PA2、电机、蜂鸣器 PA8

7 项

按键表 keys[]

(GPIOB, PB3, 键码 1)、(GPIOB, PB5, 键码 3)、(GPIOB, PB6, 键码 4)、(GPIOB, PB4, 键码 2)

4 项

传感器表 sensorParams[]

水位(启用)、温度(保留)

2 项

阈值表 thresholdParams[]

S_W 水位阈值、WDB 温度阈值、Stp 步长

3 项

菜单表 menuItems[][]

每个模式最多 4 个选项的菜单文本

按模式

定时任务表 timerTasks[]

周期任务与回调

按需

2程序启动与主循环

2.1初始化顺序

初始化顺序经过刻意安排:先建立系统节拍(NVIC 分组与延时函数),再初始化依赖节拍的模块(RTC、蜂鸣器),然后是显示与输入(OLED、按键),接着是数据采集(ADC、DS18B20),最后是输出(GPIO_OUT、电机)。这样即使某个外设初始化失败,也能通过 OLED 或蜂鸣器给出提示。

代码 2-1系统初始化(System_Init)

void System_Init(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);delay_init();/* SysTick 延时基准 */BoardLed_Init();MyRTC_Init();/* RTC + 后备电池 */Buzzer_Init();OLED_Init();/* 软件 I2C:PB8=SCL, PB9=SDA */Key_Init();/* EXTI 下降沿 + TIM1 20ms 消抖 */Ad_Init();/* ADC1_CH0 → PA0 水位 */GPIO_OUT_Init();/* 继电器/风扇/消毒灯等输出 */GPIO_IN_Init();DS18B20_Init();/* 单总线 → PB0 */DCMotor_Init();/* TIM2_CH2 PWM → PA1 */ThresholdParams_LoadDefaults();/* S_W=50, WDB=55, Stp=5 */MY_Gizwits_Init();/* 机智云协议初始化 */}

需要说明的是 BOOT_SHOW_PERINF 宏被设为 0:上电时跳过开机信息页,直接进入模式菜单。这样调试时省去每次 2 秒的等待,也避免了开机页在显存中残留影响后续页面。

2.2主循环

主循环不做任何阻塞等待,四个任务按顺序「跑一遍就走」:

代码 2-2主循环(main)

int main(void){System_Init();while (1){userHandle();/* 采集、状态机推进、显示刷新 */gizwitsHandle();/* 云端数据上报与命令解析 */gizwitsNTPTask();/* 网络对时(低频) */Key_GetNum();/* 读取消抖后的键值 */}}

这里有一个容易踩的坑:如果把洗涤流程写成「开泵 → delay(30000) → 关泵」,那么这 30 秒内按键、显示、云端通信全部停摆,用户按 K4 也停不下来,超温保护也无法及时响应。因此本工程所有流程等待都采用非阻塞计时——只记录「开始时刻」,每轮循环比较已运行时间,到点才切换状态。这就是主循环必须保持「跑一遍就走」的原因。

3洗涤流程状态机(程序设计核心)

3.1为什么用状态机

洗碗是一个典型的「多阶段、带反馈、有超时」的时序过程:每个阶段都有明确的进入动作、退出条件和超时保护,而且阶段之间有依赖(不先进水不能加热,不排水不能风干)。用状态机描述这类过程有三个好处:

结构清晰:每个状态只关心「我现在做什么、什么条件走」,不用写成层层嵌套的 if。

安全可控:任何阶段都能被外部事件(按 K4、超温、缺水)立即打断,并统一走「安全退出」路径。

易于调整:阶段的时间参数全部宏定义,改节奏只改宏,不改逻辑。

3.2状态划分

表 2-3洗涤流程状态划分

状态

进入动作

退出条件

超时保护

IDLE 待机

全部执行器关闭

收到启动命令

—

DRAIN 排水

开排水泵

水位降到下限 或 到时

DRAIN_TIMEOUT 30s

FILL 进水

开补水泵

水位达到阈值 或 到时

FILL_TIMEOUT 30s

PREWASH 预洗

开电机低速

到时

PREWASH 20s

HEAT 加热

开加热器 + 风扇

水温到设定值 或 超时

HEAT_TIMEOUT 100s

MAIN_WASH 主洗

开电机 + 维持加热

到时

MAIN_WASH 30s

RINSE 漂洗

开电机 + 换水

到时

RINSE 30s

DRY 风干

关加热,开风扇

到时

DRY 120s

DISINFECT 消毒

点亮紫外灯

到时

DISINFECT 30s

DONE 完成

蜂鸣 3 秒

到时回到 IDLE

BUZZER 3s

FAULT 故障

关闭所有输出、连鸣

用户确认复位

—

3.3状态迁移的实现

状态机每轮循环只做三件事:判断当前状态的退出条件是否满足、记录进入下一状态的时刻、执行新状态的进入动作。下面是一段体现核心思路的示意代码(工程中对应 DishwasherAutoState 的 switch 分支):

代码 2-3状态机的非阻塞推进

static void Dishwasher_Run(void){uint32_t elapsed = Now_ms() - stateEnterMs;/* 已运行时间 */switch (autoState){case FILL:Pump_Fill_On();if (WaterLevel >= ShuiWeiYu || elapsed >= FILL_TIMEOUT)State_Enter(HEAT);/* 水位到位或超时 → 加热 */break;case HEAT:Heater_On();Fan_On();if (TempX10 >= TempDs18b20Yu * 10)State_Enter(MAIN_WASH);/* 温度到位 → 主洗 */else if (elapsed >= HEAT_TIMEOUT)State_Enter(FAULT);/* 加热超时 → 故障 */else if (TempX10 >= OVER_TEMP_X10)/* 75.0℃ 超温保护 */State_Enter(FAULT);break;case MAIN_WASH:Motor_SetSpeed(SPEED_MID);if (elapsed >= MAIN_WASH_TIME)State_Enter(RINSE);break;/* … 其余状态同构 … */}}

这段代码里最值得注意的两点:第一,没有任何 delay 或 while 等待,函数执行时间是微秒级,因此可以被高频调用;第二,所有退出条件都带「或超时」的兜底——传感器坏了、水管堵了,流程不会永远卡死,而是走故障路径。这是家用电器控制软件的基本要求。

3.4时间参数与可调性

表 2-4流程时间参数(宏定义)

宏定义

值

含义

调整场景

DRAIN_MIN

5s

排水最短时间

排水管路长时调大,确保残留水排净

DRAIN_TIMEOUT

30s

排水最长时间

防止水位传感器失效时无限排水

FILL_TIMEOUT

30s

进水最长时间

防止进水管断水时无限进水

PREWASH_TIME

20s

预洗时长

餐具较脏时调大到 30~40s

HEAT_TIMEOUT

100s

加热最长时间

冬季水温低时可适当加大

MAIN_WASH_TIME

30s

主洗时长

演示时调小,实用时调到 3~5 分钟

RINSE_TIME

30s

漂洗时长

同上

DRY_TIME

120s

风干时长

环境湿度大时加长

DISINFECT_TIME

30s

消毒时长

按消毒灯功率调整

BUZZER_TIME

3s

完成提示音时长

按使用习惯调整

RTC_MAX_STEP

5s

RTC 单次最大修正量

防止网络对时跳变导致流程计时异常

OVER_TEMP_X10

750

超温门限(75.0℃)

安全门限,不建议修改

EMPTY_LEVEL

5

判定无水的下限

水槽结构变化时可微调

4模式调度与菜单系统

系统通过两个变量共同决定界面:SystemMode 记录当前所处的工作模式,M_Switch 记录当前显示的是「菜单」还是「功能页」。这样的双变量设计让「进入」与「返回」变得非常简单——返回时只需把 M_Switch 置 1,不必保存和恢复页面内部的临时状态。

代码 2-4工作模式枚举(SystemMode)

typedef enum {MODE_YUANCHENG = 0,/* 远程模式 */MODE_AUTO,/* 自动模式 */MODE_MANUAL,/* 手动模式 */MODE_DINGSHI,/* 定时模式 */MODE_THRESHOLD,/* 阈值设置 */MODE_TIME_SET,/* 时间设置 */MODE_COUNT,/* 模式总数(用于取模循环) */MODE_USER,/* 用户模式 */MODE_YUYIN/* 语音模式 */} SystemMode;

菜单项以二维数组 menuItems[MODE_TOTAL][4] 组织,每一项最多 4 个选项的显示文本。翻页时用「索引 + 1 再对 MODE_COUNT 取模」实现首尾循环,避免边界判断。屏幕上同时可见三项,选中项前显示「>>」,这也是用户判断当前选中位置的唯一依据。

5阈值参数管理

可在线调整的参数被抽象为统一的阈值参数表,每项包含名称、当前值、默认值、最小值、最大值与在屏幕上的显示位置。这样「在阈值设置页循环切换参数」「加减并限幅」都只需一次通用实现,不必为每个参数单独写代码。

代码 2-5阈值参数表

typedef struct {const char *name;/* 显示名,如 "S_W" */int16_t*value;/* 指向实际变量的指针 */int16_tdef;/* 默认值 */int16_tmin;/* 下限 */int16_tmax;/* 上限 */uint8_trow;/* 屏幕行 */uint8_tcol;/* 屏幕列 */} ThresholdParam;static ThresholdParam thresholdParams[] = {{ "S_W", &ShuiWeiYu,50, 0, 100, 2, 3 },/* 水位阈值 */{ "WDB", &TempDs18b20Yu,55, 0, 75,2, 4 },/* 温度阈值 */{ "Stp", &Step,5, 1, 10,2, 5 },/* 调节步长 */};

限幅逻辑在写入处统一处理:数值超出 [min, max] 时钳位到边界并给出短鸣提示。这一步很重要——如果没有限幅,用户把温度阈值误调到 200℃ 后,加热器会一直加热到超温保护才停,而超温保护只是最后一道防线,不应被频繁依赖。

6OLED 显示设计

显示内容按「固定区 + 变化区」划分:顶部一行固定显示 RTC 时间(每秒刷一次),第二行显示模式名与当前环节,第三行显示水位与温度等实时值,最下方显示设备开关符号。这种分区让刷新量降到最低。

本工程 OLED 采用页内寻址:绘制一个 16×16 汉字时,先向第 (行−1)×2 页写入字模的前 16 字节(上半字),再向第 (行−1)×2+1 页写入后 16 字节(下半字),列坐标按「(列−1)×16」计算;绘制 8×16 ASCII 时列坐标按「(列−1)×8」计算。由于页的位置由行号唯一决定,同一行内汉字与 ASCII 的列基准不同、相邻行又共用相邻页,实际屏幕上就会出现字符相互覆盖的观感。这是该驱动方案的真实特性,交付资料中的 26 张屏幕画面均按此寻址方式还原,与实机一致。

(a)自动模式待机页

(b)阈值设置页

图 2-1屏幕显示效果(按真实寻址方式还原,与实机一致)

7按键处理

按键的可靠性直接影响使用体验。本工程采用「下降沿中断 + 定时器消抖 + 键值队列」的三段式处理:

第一段(中断):EXTI 检测到下降沿后只做一件事——置位对应按键的标志位,不做任何延时。

第二段(定时器):TIM1 每 20ms 进入一次,读取标志后再采样一次引脚电平;两次电平一致才认为按键有效,并生成键值放入队列。20ms 大于轻触按键的典型抖动时间(5~15ms)。

第三段(主循环):Key_GetNum() 从队列取键值返回给业务层,业务层只关心「按了哪个键」,不关心消抖细节。

另外还做了「松开检测」:只有检测到按键松开后才允许产生下一个键值,避免长按被识别为连续多次按键。这也意味着本机的操作全部是点按,符合家电的使用习惯。

8物联网通信设计

8.1数据流

上行:主控采集到的水温、水位、流程状态被填入机智云数据结构体,由协议层打包成协议帧,经 USART3 发给 ESP-01S,模块再通过 WiFi 上传到云端,App 拉取后显示。下行则相反:App 下发的开关命令由模块收到后转发给主控,协议层解析出具体数据点,主控据此改变本地设备状态或阈值。

8.2数据点映射

本工程共定义 16 个数据点。其中有两点值得注意:一是温度上报使用「×10 的整数」而非浮点,避免不同平台浮点精度差异导致显示抖动;二是设备开关全部用布尔量,与本地设备表的开关标志一一对应,因此在 App 上点开关与在本地手动模式下点开关,走的是同一段执行代码,行为完全一致。

表 2-5数据点与本地变量的映射

数据点

类型

读写

映射的本地变量 / 功能

TempDs18b20

数值

只读

水温 ×10

ShuiWei

数值

只读

水位相对值 0~100

flag_RE_BEN

布尔

可写

加热器(设备表索引)

flag_BU_SHUI_BEN

布尔

可写

补水泵

flag_PAI_SHUI_BEN

布尔

可写

排水泵

flag_DCMotor

布尔

可写

直流电机

flag_FENG_SHAN

布尔

可写

散热风扇

flag_Buzzer

布尔

可写

蜂鸣器

flag_LED

布尔

可写

紫外消毒灯

TempDs18b20Yu

数值

可读写

温度阈值 TempDs18b20Yu

ShuiWeiYu

数值

可读写

水位阈值 ShuiWeiYu

ModeSwitch

布尔

可写

设备总开关

flag_DishWasher_State

枚举

只读

洗涤流程当前状态

XiTong_ModeSwitch

枚举

可写

系统工作模式

DishWasher_ModeSwitch

枚举

可写

洗涤程序(预洗/主洗/漂洗/风干/消毒)

8.3网络对时

ESP-01S 联网后可从云端获取标准时间。主控在 gizwitsNTPTask() 中把云端时间写入 RTC。为防止对时造成时间跳变影响流程计时,代码中设置了单次最大修正量 RTC_MAX_STEP = 5 秒:若新旧时间差超过 5 秒,则分多次逐步修正。这样既保证了长期走时准确,又不会让正在计时的洗涤流程突然「跳秒」。

9安全与异常处理设计

表 2-6异常处理策略

异常

检测方式

系统响应

用户可见反馈

水温超限

TempX10 ≥ 750(75.0℃)

立即断加热器、开风扇,进入 FAULT

屏幕显示「故障」,蜂鸣器连鸣

加热超时

HEAT 状态超过 100s 未达温

断加热,进入 FAULT

同上

缺水

WaterLevel < EMPTY_LEVEL

禁止开加热器与电机,先补水

水位显示偏低,加热器不动作

进水超时

FILL 状态超过 30s 未到位

关补水泵,进入 FAULT

显示故障

排水超时

DRAIN 状态超过 30s 未到位

关排水泵,进入 FAULT

显示故障

WiFi 断线

协议层心跳超时

本地模式继续运行,仅停止上报

App 显示离线,屏幕正常

按键抖动

20ms 二次采样

丢弃无效边沿

无异常

10调试经验与设计复盘

显存覆盖问题:最初以为是字库提取错误,逐一比对字模后才发现是页内寻址导致的行间覆盖。这提醒我们:显示异常的根因可能不在字库,而在寻址模型。修复方式有两种,本项目选择保留原驱动行为并在文档中如实说明,因为在 128×64 的屏上,行间距调整会连带影响所有页面的排版。

按键映射错位:键码与引脚不是顺序对应,排查时曾误以为是硬件虚焊。最终通过逐键打印键码确认了映射关系,并在按键表中显式写明,避免后来者再踩坑。

非阻塞改造:早期版本用 delay 实现阶段等待,结果按键无响应、超温保护失效。改为计时比较后问题全部消失,这也成为本项目最重要的一条设计约束。

继电器误动作:最初未加续流二极管,继电器断开瞬间偶发复位。补上 1N4007 后彻底解决。这类问题在实验室常被忽略,但在实际使用中会反复出现。

时间跳变:开启网络对时后,流程计时偶尔提前结束。加入 RTC_MAX_STEP 限幅后恢复正常。

资料详情(以智能门锁为例)

相关学习资料