STM32实战:基于STM32F103的智能饮水机温度控制

文章目录

一、前言

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 核心知识点

  1. PID温度控制:比例-积分-微分控制算法实现精准温控
  2. DS18B20单总线:单总线协议和温度读取
  3. 可控硅调功:过零检测和相位控制实现功率调节
  4. TFT图形界面:SPI通信和图形绘制
  5. 安全保护机制:多层级安全检测和保护

6.2 扩展方向

  • 语音识别:语音控制出水
  • APP远程控制:手机APP查看状态和控制
  • 水质检测:添加TDS传感器检测水质
  • 节能算法:学习用户习惯,智能预约加热

6.3 学习资源

相关推荐
EVERSPIN2 小时前
MCU单片机FOC汽车水泵方案
单片机·嵌入式硬件·mcu·汽车·mcu单片机
yongui478342 小时前
STM32 上实现 SPI 自发自收(Loopback)
stm32·单片机·嵌入式硬件
弘毅 失败的 mian2 小时前
STM32 时钟详解
经验分享·笔记·stm32·单片机·嵌入式硬件·嵌入式
VBsemi-专注于MOSFET研发定制2 小时前
面向AI管道检测机器人的功率MOSFET选型分析——以高集成度、高可靠电源与驱动系统为例
人工智能·单片机·机器人
jghhh012 小时前
STM32 控制 3 个步进电机方案
stm32·单片机·嵌入式硬件
Wave8453 小时前
STM32 串口通信 (UART) 全栈底层复习指南
stm32·单片机·嵌入式硬件
ILYT NCTR3 小时前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
LCMICRO-133108477463 小时前
长芯微LCMDC8685完全P2P替代ADS8685,16位模数转换器(ADC)
单片机·嵌入式硬件·fpga开发·硬件工程·dsp开发·模数转换器adc
进击的小头3 小时前
第16篇:嵌入式工业通信外设:CAN_CAN FD总线接口原理与组网应用
单片机·嵌入式硬件