从零到一:手把手教你用STM32和DS18B20打造智能温度监控系统
在物联网和智能家居快速发展的今天,温度监控系统已成为许多应用场景的基础需求。无论是温室大棚的精准控温,还是实验室的环境监测,一个稳定可靠的温度监控系统都能大幅提升工作效率和安全性。本文将带你从零开始,使用STM32单片机和DS18B20温度传感器,构建一个功能完善的智能温度监控系统。
1. 硬件选型与系统架构设计
1.1 核心组件选择
构建温度监控系统的第一步是选择合适的硬件组件。我们需要考虑以下几个关键因素:
主控芯片:STM32F103C8T6
- 32位ARM Cortex-M3内核,72MHz主频
- 64KB Flash,20KB SRAM
- 丰富的外设接口(USART、SPI、I2C等)
- 低功耗设计,3.3V工作电压
温度传感器:DS18B20
- 数字输出,精度±0.5°C(-10°C至+85°C)
- 测量范围:-55°C至+125°C
- 单总线接口,简化布线
- 可编程分辨率(9-12位)
显示模块:4位共阳数码管
- 高亮度,可视角度大
- 驱动简单,成本低廉
- 适合显示温度数值
1.2 系统架构设计
整个系统采用模块化设计,各功能模块通过主控芯片协调工作:
[电源模块] → [STM32主控] ←→ [DS18B20传感器] ↓ [数码管显示] ↓ [报警指示灯] ↓ [按键输入]系统工作流程:
- DS18B20采集环境温度数据
- STM32处理温度数据并显示
- 用户通过按键设置温度阈值
- 系统比较当前温度与阈值,触发报警
2. 硬件电路设计与实现
2.1 STM32最小系统搭建
STM32最小系统是项目的基础,包含以下关键电路:
电源电路:
// 使用AMS1117-3.3稳压芯片 // 输入:5V USB电源 // 输出:3.3V稳定电压复位电路:
// 10kΩ上拉电阻 + 100nF电容 // 提供上电复位和手动复位功能时钟电路:
// 8MHz外部晶振 + 两个22pF负载电容 // 32.768kHz RTC晶振(可选)调试接口:
// SWD四线调试接口 // VCC, GND, SWDIO, SWCLK2.2 DS18B20接口设计
DS18B20采用单总线协议,硬件连接非常简单:
DS18B20引脚说明: 1. GND - 接地 2. DQ - 数据线(接STM32 GPIO) 3. VDD - 电源(3.3V)推荐电路设计:
- 数据线接4.7kΩ上拉电阻
- 采用外部供电模式(非寄生供电)
- 数据线连接STM32任意GPIO(如PB5)
注意:长距离传输时,建议使用双绞线并增加屏蔽措施,以提高抗干扰能力。
2.3 数码管驱动电路
4位共阳数码管需要驱动电路提供足够电流:
数码管驱动方案: 1. 使用74HC595移位寄存器 - 节省IO口资源 - 支持级联扩展 2. 使用三极管阵列(如ULN2003) - 驱动能力强 - 电路简单推荐电路参数:
- 段选限流电阻:220Ω
- 位选三极管:S8050(NPN)
- 刷新频率:≥100Hz(避免闪烁)
3. 软件设计与实现
3.1 开发环境配置
使用Keil MDK进行开发,需要以下准备工作:
- 安装Keil MDK-ARM
- 安装STM32F1xx Device Family Pack
- 配置工程选项:
- Target: STM32F103C8
- Use MicroLIB: Enabled
- Optimize: Level 2 (-O2)
3.2 DS18B20驱动开发
DS18B20的通信基于严格的时序要求,以下是关键函数实现:
初始化函数:
uint8_t DS18B20_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; // 配置GPIO为开漏输出 GPIO_InitStruct.Pin = DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); // 复位脉冲 HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET); delay_us(480); HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); // 等待应答信号 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct); delay_us(60); uint8_t ret = HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN); delay_us(420); return (ret == 0); // 0表示初始化成功 }温度读取流程:
- 发送复位脉冲
- 发送跳过ROM命令(0xCC)
- 发送温度转换命令(0x44)
- 等待转换完成(750ms for 12-bit)
- 发送复位脉冲
- 发送跳过ROM命令(0xCC)
- 发送读取暂存器命令(0xBE)
- 读取两个字节的温度数据
3.3 数码管显示驱动
采用动态扫描方式驱动数码管,关键代码如下:
// 数码管段码表(共阳) const uint8_t SEGMENT_CODE[] = { 0xC0, // 0 0xF9, // 1 0xA4, // 2 0xB0, // 3 0x99, // 4 0x92, // 5 0x82, // 6 0xF8, // 7 0x80, // 8 0x90 // 9 }; void Display_Temperature(float temp) { uint8_t digits[4]; int16_t temp_int = (int16_t)(temp * 10); // 保留1位小数 // 温度分解 digits[0] = (temp_int / 100) % 10; // 十位 digits[1] = (temp_int / 10) % 10; // 个位 digits[2] = temp_int % 10; // 小数位 digits[3] = 10; // 空(不显示) // 动态扫描显示 for(uint8_t i = 0; i < 4; i++) { HAL_GPIO_WritePin(DIGIT_PORT, DIGIT_PINS[i], GPIO_PIN_RESET); HAL_GPIO_WritePin(SEGMENT_PORT, 0xFF, GPIO_PIN_SET); // 消隐 if(i == 2) { // 显示小数点 Send_Data(SEGMENT_CODE[digits[i]] & 0x7F); } else { Send_Data(SEGMENT_CODE[digits[i]]); } HAL_Delay(2); HAL_GPIO_WritePin(DIGIT_PORT, DIGIT_PINS[i], GPIO_PIN_SET); } }3.4 报警功能实现
温度报警功能通过比较当前温度与预设阈值实现:
void Check_Temperature_Alert(float current_temp) { static uint8_t alert_state = 0; static uint32_t last_toggle = 0; if(current_temp > temp_high_threshold || current_temp < temp_low_threshold) { // 报警状态 if(HAL_GetTick() - last_toggle > 500) { alert_state = !alert_state; HAL_GPIO_WritePin(LED_PORT, LED_PIN, alert_state ? GPIO_PIN_SET : GPIO_PIN_RESET); last_toggle = HAL_GetTick(); } } else { // 正常状态 HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); } }4. 系统优化与调试技巧
4.1 常见问题解决方案
DS18B20无响应:
- 检查硬件连接是否正确
- 确保上拉电阻(4.7kΩ)已连接
- 验证时序是否符合规格书要求
- 尝试降低通信速度
温度读数不稳定:
- 增加软件滤波算法(如滑动平均)
- 检查电源稳定性
- 避免传感器靠近热源
- 确保传感器与导线连接可靠
数码管显示暗淡或有鬼影:
- 调整限流电阻值(通常220Ω-1kΩ)
- 优化扫描频率(建议100-200Hz)
- 增加消隐时间
- 检查三极管驱动能力
4.2 系统优化建议
电源管理优化:
- 添加0.1μF去耦电容靠近芯片电源引脚
- 对于电池供电应用,启用STM32低功耗模式
- 在不读取温度时,将DS18B20置于待机模式
软件架构优化:
// 采用状态机设计模式 typedef enum { STATE_IDLE, STATE_START_CONVERSION, STATE_WAIT_CONVERSION, STATE_READ_TEMP, STATE_DISPLAY } SystemState; void System_Run(void) { static SystemState state = STATE_IDLE; static uint32_t timer = 0; switch(state) { case STATE_IDLE: if(HAL_GetTick() - timer > 1000) { state = STATE_START_CONVERSION; } break; case STATE_START_CONVERSION: DS18B20_StartConversion(); state = STATE_WAIT_CONVERSION; timer = HAL_GetTick(); break; // 其他状态处理... } }扩展功能考虑:
- 添加无线传输模块(如ESP8266)实现远程监控
- 增加数据记录功能,存储历史温度数据
- 实现多路温度监测(多个DS18B20并联)
- 开发上位机软件,可视化温度曲线
5. 项目进阶与扩展应用
5.1 多传感器网络实现
DS18B20支持单总线上挂载多个设备,每个传感器有唯一的64位ROM编码。实现多路温度监测的关键步骤:
- 搜索总线上的所有设备ROM编码
- 依次对每个设备发起温度转换
- 读取各设备的温度数据
示例代码片段:
void DS18B20_SearchRom(uint8_t *rom_codes, uint8_t *dev_count) { uint8_t last_discrepancy = 0; uint8_t rom_no[8]; *dev_count = 0; while(DS18B20_Search(&last_discrepancy, rom_no)) { memcpy(&rom_codes[*dev_count * 8], rom_no, 8); (*dev_count)++; if(*dev_count >= MAX_DEVICES) break; } }5.2 物联网集成方案
将温度监控系统接入物联网平台,实现远程监控:
硬件扩展:
- 添加ESP8266 WiFi模块
- 或使用STM32+SIM800C GSM方案
数据协议:
{ "device_id": "STM32_TEMP_001", "timestamp": "2023-07-20T14:30:00Z", "temperature": 25.6, "unit": "Celsius", "alert": false }云端集成:
- 阿里云IoT平台
- 腾讯云物联网开发平台
- 自建MQTT服务器
5.3 工业级应用改进
针对工业环境的需求改进设计:
可靠性增强:
- 增加信号隔离电路
- 采用屏蔽电缆
- 添加TVS二极管保护
功能扩展:
- 4-20mA电流环输出
- Modbus RTU通信协议
- 继电器输出控制
外壳与安装:
- IP65防护等级外壳
- DIN导轨安装设计
- 防爆认证(适用于危险环境)
6. 实战案例:温室监控系统
以一个实际的温室监控系统为例,展示本设计的应用:
系统配置:
- 主控:STM32F103C8T6
- 传感器:6个DS18B20(分布在温室不同位置)
- 显示:4.3寸TFT LCD
- 通信:LoRa无线模块
- 执行机构:通风扇、加热器、水泵
控制逻辑:
void Greenhouse_Control(void) { float avg_temp = Calculate_Average_Temperature(); if(avg_temp > target_temp + hysteresis) { Enable_Cooling_System(); Disable_Heating_System(); } else if(avg_temp < target_temp - hysteresis) { Disable_Cooling_System(); Enable_Heating_System(); } Check_Soil_Moisture(); if(soil_moisture < threshold) { Start_Irrigation(); } }数据可视化:
温室环境监测面板 ---------------- 当前温度:23.5°C 最高温度:28.1°C(位置A) 最低温度:20.3°C(位置C) 土壤湿度:65% 系统状态:正常 报警记录:无这个项目从最初的简单温度显示,逐步扩展为功能完善的温室监控系统,充分展示了STM32和DS18B20组合的灵活性和扩展能力。