文章目录
-
- 一、前言
-
- [1.1 技术背景](#1.1 技术背景)
- [1.2 应用场景](#1.2 应用场景)
- [1.3 本文目标](#1.3 本文目标)
- 二、环境准备
-
- [2.1 硬件清单](#2.1 硬件清单)
- [2.2 硬件连接图](#2.2 硬件连接图)
- 三、核心实现
-
- [3.1 STM32CubeMX配置](#3.1 STM32CubeMX配置)
- [3.2 主程序实现](#3.2 主程序实现)
- [3.3 PID控制器实现](#3.3 PID控制器实现)
- 四、测试验证
-
- [4.1 温度控制测试](#4.1 温度控制测试)
- [4.2 安全功能测试](#4.2 安全功能测试)
- 五、故障排查
-
- [5.1 常见问题](#5.1 常见问题)
- 六、总结
-
- [6.1 核心知识点](#6.1 核心知识点)
- [6.2 扩展方向](#6.2 扩展方向)
- [6.3 学习资源](#6.3 学习资源)
一、前言
1.1 技术背景
饮水机是家庭和办公场所的常用电器,传统饮水机存在反复加热、能耗高、无法精确控温等问题。智能饮水机通过STM32微控制器实现精准温控、节能模式、安全保护等功能,为用户提供更健康、更便捷的饮水体验。
本项目将展示如何使用STM32F103实现一个功能完善的智能饮水机控制系统,支持多档温度设定、童锁保护、节能模式等实用功能。
1.2 应用场景
- 家庭使用:精确控制出水温度,适合冲泡奶粉、茶叶、咖啡等
- 办公场所:大容量供水,节能模式降低电费
- 母婴场景:45°C恒温,方便冲泡奶粉
- 茶饮场景:85°C泡茶,100°C开水
1.3 本文目标
通过本教程,你将学会:
- DS18B20数字温度传感器驱动
- PID温度控制算法实现
- 继电器和可控硅控制加热功率
- 水位检测与防干烧保护
- TFT彩屏图形界面开发
- 触摸按键与实体按键结合
- EEPROM数据存储
技术栈:
- 硬件平台:STM32F103C8T6
- 温度传感器:DS18B20(防水型)
- 显示屏:1.8寸SPI TFT彩屏 (ST7735)
- 加热控制:继电器 + 可控硅调功
- 水位检测:浮球开关 + 压力传感器
- 输入设备:触摸按键 + 旋转编码器
- 存储:AT24C02 EEPROM
- 通信:ESP8266 WiFi(可选,远程监控)
二、环境准备
2.1 硬件清单
| 器件名称 | 型号/规格 | 数量 | 说明 |
|---|---|---|---|
| 主控芯片 | STM32F103C8T6 | 1 | Blue Pill开发板 |
| 温度传感器 | DS18B20 | 2 | 防水型,1个加热罐,1个出水口 |
| TFT显示屏 | 1.8寸 SPI | 1 | ST7735驱动,128x160 |
| 继电器 | 5V单路 | 1 | 加热控制 |
| 可控硅 | BTA16-600B | 1 | 调功控制 |
| 光耦 | MOC3021 | 1 | 可控硅隔离驱动 |
| 水位传感器 | 浮球开关 | 2 | 高水位/低水位检测 |
| 蜂鸣器 | 有源5V | 1 | 提示音 |
| 按键 | 触摸按键 | 4 | 温度档位选择 |
| 编码器 | EC11 | 1 | 微调温度 |
| EEPROM | AT24C02 | 1 | I2C接口 |
2.2 硬件连接图
PA0
PA5/PA6/PA7
PA1/PA2
PA3/PA4
PB0-PB3
PB4/PB5/PB6
PB7/PB8
STM32F103C8T6
DS18B20温度传感器
ST7735 TFT屏
继电器/可控硅
水位传感器
触摸按键
旋转编码器
AT24C02 EEPROM
引脚连接表:
| STM32引脚 | 连接设备 | 功能说明 |
|---|---|---|
| PA0 | DS18B20 | 单总线温度数据 |
| PA1 | 继电器 | 加热控制 |
| PA2 | 光耦 | 可控硅触发 |
| PA3 | 浮球开关1 | 低水位检测 |
| PA4 | 浮球开关2 | 高水位检测 |
| PA5 | TFT SCK | SPI时钟 |
| PA6 | TFT MISO | SPI数据输入 |
| PA7 | TFT MOSI | SPI数据输出 |
| PB0 | TFT CS | 片选 |
| PB1 | TFT DC | 数据/命令 |
| PB2 | TFT RST | 复位 |
| PB3-PB6 | 触摸按键 | 温度档位 |
| PB7 | 编码器A | 旋转检测 |
| PB8 | 编码器B | 方向检测 |
| PB9 | 编码器按键 | 确认 |
| PB10 | EEPROM SDA | I2C数据 |
| PB11 | EEPROM SCL | I2C时钟 |
三、核心实现
3.1 STM32CubeMX配置
时钟配置:
- HSE Crystal/Ceramic Resonator
- System Clock: 72MHz
外设配置:
- TIM2:1ms定时器,PID控制周期
- TIM3:PWM输出,可控硅过零检测
- SPI1:PA5(SCK), PA6(MISO), PA7(MOSI),TFT通信
- I2C2:PB10(SDA), PB11(SCL),EEPROM通信
- GPIO :
- PA0:单总线(开漏输出)
- PA1:输出,继电器控制
- PA2:输出,可控硅触发
- PA3, PA4:输入,水位检测
- PB0-PB3:输入,触摸按键
- PB7-PB9:输入,编码器
- PB0, PB1, PB2:输出,TFT控制
- EXTI :
- 过零检测中断(用于可控硅调功)
3.2 主程序实现
📄 创建文件:
Core/Src/main.c
c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Smart Water Dispenser Temperature Control System
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "spi.h"
#include "i2c.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
#include "ds18b20.h"
#include "st7735.h"
#include "pid_controller.h"
#include "eeprom.h"
#include "encoder.h"
#include "ui_manager.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private defines -----------------------------------------------------------*/
#define PID_INTERVAL_MS 1000 // PID控制周期(ms)
#define DISPLAY_UPDATE_MS 500 // 显示更新周期(ms)
#define SAFETY_MAX_TEMP 105 // 最高安全温度(°C)
#define SAFETY_MIN_WATER 10 // 最低水位百分比
// 预设温度档位
#define TEMP_ROOM 25
#define TEMP_MILK 45
#define TEMP_TEA 85
#define TEMP_BOIL 100
/* Private typedef -----------------------------------------------------------*/
typedef enum {
STATE_STANDBY = 0, // 待机
STATE_HEATING, // 加热中
STATE_KEEP_WARM, // 保温
STATE_ERROR // 故障
} SystemState;
typedef enum {
ERROR_NONE = 0,
ERROR_NO_WATER, // 缺水
ERROR_OVER_TEMP, // 超温
ERROR_SENSOR_FAULT // 传感器故障
} ErrorCode;
/* Private variables ---------------------------------------------------------*/
volatile SystemState system_state = STATE_STANDBY;
volatile ErrorCode error_code = ERROR_NONE;
volatile float current_temp = 0.0;
volatile float target_temp = TEMP_ROOM;
volatile uint8_t water_level = 0; // 水位百分比
volatile uint8_t heating_power = 0; // 加热功率百分比
volatile uint8_t child_lock = 1; // 童锁状态
volatile uint32_t last_pid_time = 0;
volatile uint32_t last_display_time = 0;
// PID控制器
PID_Controller pid;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void Read_Sensors(void);
static void Control_Heating(void);
static void Update_Display(void);
static void Check_Safety(void);
static void Process_Input(void);
static void Set_Heating_Power(uint8_t power);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/**
* @brief 主函数入口
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_SPI1_Init();
MX_I2C2_Init();
/* USER CODE BEGIN 2 */
printf("\\r\\n===== Smart Water Dispenser =====\\r\\n");
// 初始化TFT显示屏
printf("Initializing TFT...\\r\\n");
ST7735_Init();
ST7735_FillScreen(BLACK);
ST7735_DrawString(10, 10, "Water Dispenser", WHITE, BLACK, 2);
ST7735_DrawString(10, 40, "Initializing...", WHITE, BLACK, 1);
HAL_Delay(1000);
// 初始化DS18B20
printf("Initializing DS18B20...\\r\\n");
if (DS18B20_Init() != HAL_OK)
{
printf("DS18B20 init failed!\\r\\n");
error_code = ERROR_SENSOR_FAULT;
system_state = STATE_ERROR;
}
else
{
printf("DS18B20 initialized\\r\\n");
}
// 初始化EEPROM并读取设置
printf("Initializing EEPROM...\\r\\n");
EEPROM_Init();
Load_Settings();
// 初始化PID控制器
PID_Init(&pid, 2.0, 0.5, 0.1); // Kp, Ki, Kd
PID_SetOutputLimits(&pid, 0, 100); // 输出限制 0-100%
// 初始化编码器
Encoder_Init();
// 初始化UI
UI_Init();
// 启动定时器
HAL_TIM_Base_Start_IT(&htim2);
printf("System ready\\r\\n");
ST7735_FillScreen(BLACK);
/* USER CODE END 2 */
/* Infinite loop */
while (1)
{
/* USER CODE BEGIN 3 */
// 读取传感器数据
Read_Sensors();
// 安全检查
Check_Safety();
// 加热控制
if (system_state != STATE_ERROR)
{
Control_Heating();
}
else
{
Set_Heating_Power(0); // 故障时停止加热
}
// 处理用户输入
Process_Input();
// 更新显示
if (HAL_GetTick() - last_display_time >= DISPLAY_UPDATE_MS)
{
last_display_time = HAL_GetTick();
Update_Display();
}
HAL_Delay(50);
}
/* USER CODE END 3 */
}
/**
* @brief 读取传感器数据
*/
static void Read_Sensors(void)
{
static uint32_t last_sensor_read = 0;
if (HAL_GetTick() - last_sensor_read < 1000)
{
return;
}
last_sensor_read = HAL_GetTick();
// 读取温度
float temp = DS18B20_ReadTemp();
if (temp > -55.0 && temp < 125.0) // 有效范围检查
{
current_temp = temp;
}
else
{
error_code = ERROR_SENSOR_FAULT;
}
// 读取水位
uint8_t low_level = HAL_GPIO_ReadPin(WATER_LOW_GPIO_Port, WATER_LOW_Pin);
uint8_t high_level = HAL_GPIO_ReadPin(WATER_HIGH_GPIO_Port, WATER_HIGH_Pin);
if (high_level == 0)
{
water_level = 100;
}
else if (low_level == 0)
{
water_level = 50;
}
else
{
water_level = 0;
}
}
/**
* @brief 控制加热
*/
static void Control_Heating(void)
{
if (HAL_GetTick() - last_pid_time < PID_INTERVAL_MS)
{
return;
}
last_pid_time = HAL_GetTick();
// 根据状态决定控制策略
switch (system_state)
{
case STATE_STANDBY:
Set_Heating_Power(0);
break;
case STATE_HEATING:
// PID控制加热到目标温度
PID_SetSetpoint(&pid, target_temp);
heating_power = (uint8_t)PID_Update(&pid, current_temp);
Set_Heating_Power(heating_power);
// 达到目标温度后转入保温状态
if (current_temp >= target_temp - 2)
{
system_state = STATE_KEEP_WARM;
printf("Target temperature reached\\r\\n");
}
break;
case STATE_KEEP_WARM:
// 保温控制,维持温度
PID_SetSetpoint(&pid, target_temp);
heating_power = (uint8_t)PID_Update(&pid, current_temp);
Set_Heating_Power(heating_power);
// 温度下降过多时重新加热
if (current_temp < target_temp - 5)
{
system_state = STATE_HEATING;
}
break;
default:
Set_Heating_Power(0);
break;
}
}
/**
* @brief 设置加热功率
* @param power: 功率百分比 (0-100)
*/
static void Set_Heating_Power(uint8_t power)
{
static uint8_t current_power = 0;
if (power == current_power)
{
return;
}
current_power = power;
if (power == 0)
{
// 关闭加热
HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_RESET);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0);
}
else if (power >= 100)
{
// 全功率加热(继电器模式)
HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0);
}
else
{
// 调功模式(可控硅)
HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_RESET);
uint16_t pwm_value = (power * 1000) / 100; // 转换为PWM值
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_value);
}
}
/**
* @brief 安全检查
*/
static void Check_Safety(void)
{
// 缺水保护
if (water_level == 0)
{
if (error_code != ERROR_NO_WATER)
{
error_code = ERROR_NO_WATER;
system_state = STATE_ERROR;
Set_Heating_Power(0);
printf("ERROR: No water!\\r\\n");
}
}
// 超温保护
else if (current_temp > SAFETY_MAX_TEMP)
{
if (error_code != ERROR_OVER_TEMP)
{
error_code = ERROR_OVER_TEMP;
system_state = STATE_ERROR;
Set_Heating_Power(0);
printf("ERROR: Over temperature!\\r\\n");
}
}
// 故障恢复检查
else if (error_code != ERROR_NONE && error_code != ERROR_SENSOR_FAULT)
{
error_code = ERROR_NONE;
system_state = STATE_STANDBY;
printf("Error cleared\\r\\n");
}
}
/**
* @brief 处理用户输入
*/
static void Process_Input(void)
{
// 检查触摸按键
if (HAL_GPIO_ReadPin(KEY_MILK_GPIO_Port, KEY_MILK_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(20); // 消抖
if (HAL_GPIO_ReadPin(KEY_MILK_GPIO_Port, KEY_MILK_Pin) == GPIO_PIN_RESET)
{
target_temp = TEMP_MILK;
system_state = STATE_HEATING;
printf("Set temperature: %dC (Milk)\\r\\n", target_temp);
while (HAL_GPIO_ReadPin(KEY_MILK_GPIO_Port, KEY_MILK_Pin) == GPIO_PIN_RESET);
}
}
if (HAL_GPIO_ReadPin(KEY_TEA_GPIO_Port, KEY_TEA_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(20);
if (HAL_GPIO_ReadPin(KEY_TEA_GPIO_Port, KEY_TEA_Pin) == GPIO_PIN_RESET)
{
target_temp = TEMP_TEA;
system_state = STATE_HEATING;
printf("Set temperature: %dC (Tea)\\r\\n", target_temp);
while (HAL_GPIO_ReadPin(KEY_TEA_GPIO_Port, KEY_TEA_Pin) == GPIO_PIN_RESET);
}
}
if (HAL_GPIO_ReadPin(KEY_BOIL_GPIO_Port, KEY_BOIL_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(20);
if (HAL_GPIO_ReadPin(KEY_BOIL_GPIO_Port, KEY_BOIL_Pin) == GPIO_PIN_RESET)
{
target_temp = TEMP_BOIL;
system_state = STATE_HEATING;
printf("Set temperature: %dC (Boil)\\r\\n", target_temp);
while (HAL_GPIO_ReadPin(KEY_BOIL_GPIO_Port, KEY_BOIL_Pin) == GPIO_PIN_RESET);
}
}
// 处理编码器输入(微调温度)
int16_t encoder_delta = Encoder_GetDelta();
if (encoder_delta != 0)
{
target_temp += encoder_delta;
if (target_temp < TEMP_ROOM) target_temp = TEMP_ROOM;
if (target_temp > TEMP_BOIL) target_temp = TEMP_BOIL;
system_state = STATE_HEATING;
printf("Adjust temperature: %.1fC\\r\\n", target_temp);
}
}
/**
* @brief 更新TFT显示
*/
static void Update_Display(void)
{
char buffer[32];
// 清除显示区域
ST7735_FillRect(0, 0, 128, 160, BLACK);
// 显示标题
ST7735_DrawString(10, 5, "Smart Dispenser", WHITE, BLACK, 1);
// 显示当前温度(大号字体)
sprintf(buffer, "%.1f", current_temp);
ST7735_DrawString(20, 30, buffer, YELLOW, BLACK, 3);
ST7735_DrawString(95, 35, "C", CYAN, BLACK, 2);
// 显示目标温度
sprintf(buffer, "Target: %dC", (int)target_temp);
ST7735_DrawString(10, 65, buffer, WHITE, BLACK, 1);
// 显示状态
const char* state_str;
uint16_t state_color;
switch (system_state)
{
case STATE_STANDBY:
state_str = "STANDBY";
state_color = GREEN;
break;
case STATE_HEATING:
state_str = "HEATING";
state_color = RED;
break;
case STATE_KEEP_WARM:
state_str = "KEEP WARM";
state_color = YELLOW;
break;
case STATE_ERROR:
state_str = "ERROR";
state_color = RED;
break;
default:
state_str = "UNKNOWN";
state_color = WHITE;
}
ST7735_DrawString(10, 80, state_str, state_color, BLACK, 1);
// 显示功率
sprintf(buffer, "Power: %d%%", heating_power);
ST7735_DrawString(10, 95, buffer, WHITE, BLACK, 1);
// 显示水位
sprintf(buffer, "Water: %d%%", water_level);
ST7735_DrawString(10, 110, buffer, CYAN, BLACK, 1);
// 显示童锁状态
if (child_lock)
{
ST7735_DrawString(10, 125, "LOCK", RED, BLACK, 1);
}
else
{
ST7735_DrawString(10, 125, "UNLOCK", GREEN, BLACK, 1);
}
// 显示错误信息
if (error_code != ERROR_NONE)
{
const char* error_str;
switch (error_code)
{
case ERROR_NO_WATER:
error_str = "NO WATER!";
break;
case ERROR_OVER_TEMP:
error_str = "OVERHEAT!";
break;
case ERROR_SENSOR_FAULT:
error_str = "SENSOR ERR!";
break;
default:
error_str = "ERROR";
}
ST7735_DrawString(10, 145, error_str, RED, BLACK, 1);
}
}
/**
* @brief 加载设置
*/
void Load_Settings(void)
{
// 从EEPROM读取保存的设置
uint8_t saved_temp;
EEPROM_Read(0x00, &saved_temp, 1);
if (saved_temp >= TEMP_ROOM && saved_temp <= TEMP_BOIL)
{
target_temp = saved_temp;
}
}
/**
* @brief 保存设置
*/
void Save_Settings(void)
{
uint8_t temp = (uint8_t)target_temp;
EEPROM_Write(0x00, &temp, 1);
}
/**
* @brief System Clock Configuration
*/
void SystemClock_Config(void)
{
// 系统时钟配置(由CubeMX生成)
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(100);
}
}
3.3 PID控制器实现
📄 创建文件:
Core/Inc/pid_controller.h
c
#ifndef __PID_CONTROLLER_H
#define __PID_CONTROLLER_H
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float setpoint; // 目标值
float integral; // 积分累计
float prev_error; // 上次误差
float output_min; // 输出最小值
float output_max; // 输出最大值
uint32_t last_time; // 上次计算时间
} PID_Controller;
void PID_Init(PID_Controller *pid, float kp, float ki, float kd);
void PID_SetSetpoint(PID_Controller *pid, float setpoint);
void PID_SetOutputLimits(PID_Controller *pid, float min, float max);
float PID_Update(PID_Controller *pid, float measurement);
void PID_Reset(PID_Controller *pid);
#endif /* __PID_CONTROLLER_H */
📄 创建文件:
Core/Src/pid_controller.c
c
#include "pid_controller.h"
/**
* @brief 初始化PID控制器
*/
void PID_Init(PID_Controller *pid, float kp, float ki, float kd)
{
pid->Kp = kp;
pid->Ki = ki;
pid->Kd = kd;
pid->setpoint = 0;
pid->integral = 0;
pid->prev_error = 0;
pid->output_min = 0;
pid->output_max = 100;
pid->last_time = 0;
}
/**
* @brief 设置目标值
*/
void PID_SetSetpoint(PID_Controller *pid, float setpoint)
{
pid->setpoint = setpoint;
}
/**
* @brief 设置输出限制
*/
void PID_SetOutputLimits(PID_Controller *pid, float min, float max)
{
pid->output_min = min;
pid->output_max = max;
}
/**
* @brief PID计算更新
* @param measurement: 当前测量值
* @retval 控制输出值
*/
float PID_Update(PID_Controller *pid, float measurement)
{
uint32_t now = HAL_GetTick();
float dt = (now - pid->last_time) / 1000.0; // 转换为秒
pid->last_time = now;
if (dt <= 0) dt = 1.0; // 防止除零
// 计算误差
float error = pid->setpoint - measurement;
// 比例项
float P = pid->Kp * error;
// 积分项(带抗饱和)
pid->integral += error * dt;
// 限制积分累计
float integral_limit = pid->output_max / pid->Ki;
if (pid->integral > integral_limit) pid->integral = integral_limit;
if (pid->integral < -integral_limit) pid->integral = -integral_limit;
float I = pid->Ki * pid->integral;
// 微分项
float derivative = (error - pid->prev_error) / dt;
float D = pid->Kd * derivative;
pid->prev_error = error;
// 计算输出
float output = P + I + D;
// 限制输出范围
if (output > pid->output_max) output = pid->output_max;
if (output < pid->output_min) output = pid->output_min;
return output;
}
/**
* @brief 重置PID控制器
*/
void PID_Reset(PID_Controller *pid)
{
pid->integral = 0;
pid->prev_error = 0;
pid->last_time = HAL_GetTick();
}
四、测试验证
4.1 温度控制测试
测试1:PID参数整定
c
void Test_PID(void)
{
PID_Controller pid;
PID_Init(&pid, 2.0, 0.5, 0.1);
PID_SetSetpoint(&pid, 85.0); // 目标85°C
printf("PID Test - Target: 85C\\r\\n");
for (int i = 0; i < 100; i++)
{
float temp = DS18B20_ReadTemp();
float output = PID_Update(&pid, temp);
printf("Temp: %.1fC, Output: %.1f%%\\r\\n", temp, output);
Set_Heating_Power((uint8_t)output);
HAL_Delay(1000);
}
}
测试2:温度档位测试
- 45°C档位:适合冲泡奶粉
- 85°C档位:适合泡茶
- 100°C档位:开水
4.2 安全功能测试
- 缺水保护:排空水箱,验证加热自动停止
- 超温保护:模拟超温情况,验证系统报警
- 童锁功能:测试童锁开启后按键是否失效
五、故障排查
5.1 常见问题
问题1:温度控制不稳定,波动大
原因分析:
- PID参数不合适
- 加热功率过大或过小
- 温度传感器响应慢
解决方案:
c
// 调整PID参数
void Tune_PID_Parameters(void)
{
// 先使用P控制找到合适的Kp
// 然后逐步增加Ki消除稳态误差
// 最后增加Kd改善动态响应
// 经验值(需要根据实际系统调整)
PID_Init(&pid, 1.5, 0.3, 0.05); // 保守参数
// PID_Init(&pid, 3.0, 0.8, 0.2); // 激进参数
}
问题2:DS18B20读取失败
解决方案:
- 检查上拉电阻(4.7kΩ)
- 检查数据线连接
- 添加重试机制
c
float DS18B20_ReadTemp_WithRetry(uint8_t max_retries)
{
for (uint8_t i = 0; i < max_retries; i++)
{
float temp = DS18B20_ReadTemp();
if (temp > -55.0 && temp < 125.0)
{
return temp;
}
HAL_Delay(100);
}
return -999; // 错误标记
}
六、总结
6.1 核心知识点
- PID温度控制:比例-积分-微分控制算法实现精准温控
- DS18B20单总线:单总线协议和温度读取
- 可控硅调功:过零检测和相位控制实现功率调节
- TFT图形界面:SPI通信和图形绘制
- 安全保护机制:多层级安全检测和保护
6.2 扩展方向
- 语音识别:语音控制出水
- APP远程控制:手机APP查看状态和控制
- 水质检测:添加TDS传感器检测水质
- 节能算法:学习用户习惯,智能预约加热