1. 项目概述
这个基于STM32的温度风扇控制系统是一个典型的嵌入式应用案例,它通过DS18B20数字温度传感器采集环境温度,并根据用户设定的阈值自动控制风扇启停。系统还配备了OLED显示屏用于实时数据显示,以及按键用于调整温度阈值。整个系统可以在Proteus仿真环境中运行,非常适合初学者学习STM32的外设控制和传感器应用。
我在实际开发这类温控系统时发现,DS18B20虽然精度不错,但在实际布线时需要注意信号线的长度和干扰问题。而STM32的GPIO配置也需要特别注意上下拉电阻的设置,否则可能导致按键检测不准确或传感器通信失败。
2. 硬件设计详解
2.1 核心组件选型
STM32微控制器:作为系统核心,我推荐使用STM32F103C8T6这款性价比极高的芯片。它有足够的GPIO和外设资源,价格亲民,社区支持完善。在实际项目中,我测试过它在72MHz主频下运行稳定,完全能满足这个温控系统的需求。
DS18B20温度传感器:这款单总线数字温度传感器有几个显著优势:
- 测量范围-55°C到+125°C,精度±0.5°C
- 单总线接口节省IO资源
- 每个器件有唯一64位序列号,支持多设备并联
- 不需要额外ADC,直接输出数字信号
注意:DS18B20对时序要求严格,在STM32上实现单总线协议时,建议使用硬件定时器来保证时序精度。
OLED显示屏:选择0.96寸I2C接口的SSD1306驱动OLED,原因如下:
- I2C接口只需2根线(SCL/SDA)
- 自发光显示,无需背光
- 高对比度,可视角度大
- 功耗低,适合嵌入式应用
2.2 电路设计要点
温度传感器接口:
code复制DS18B20引脚说明:
1. GND - 接电源地
2. DQ - 数据线,接STM32的PA0(需4.7K上拉电阻)
3. VDD - 接3.3V电源
按键电路设计:
采用独立按键设计,每个按键一端接地,另一端接STM32的GPIO(配置为上拉输入)。这种设计简单可靠,软件消抖容易实现。我通常会在按键两端并联一个0.1μF电容来进一步消除抖动干扰。
风扇驱动电路:
由于STM32的IO驱动能力有限,需要使用晶体管或MOSFET来驱动风扇。一个典型的N-MOSFET驱动电路如下:
code复制STM32 GPIO -> 1K电阻 -> MOSFET栅极
MOSFET漏极接风扇正极
风扇负极接地
MOSFET源极接地
记得在风扇两端反向并联一个续流二极管,防止关断时的反向电动势损坏MOSFET。
3. 软件实现解析
3.1 开发环境搭建
推荐使用Keil MDK作为开发环境,配合STM32CubeMX进行外设初始化。具体步骤如下:
- 安装Keil MDK和STM32CubeMX
- 在CubeMX中创建新项目,选择对应STM32型号
- 配置时钟树(建议使用外部8MHz晶振,PLL倍频到72MHz)
- 配置GPIO:
- DS18B20数据线:推挽输出/浮空输入
- 按键引脚:上拉输入
- I2C引脚:复用开漏输出
- 生成代码并导入Keil工程
3.2 核心代码实现
DS18B20驱动实现:
单总线协议的关键时序函数:
c复制// 复位脉冲
void DS18B20_Reset(void) {
SET_DQ_OUT();
DQ_LOW();
delay_us(480);
SET_DQ_IN();
delay_us(60);
uint8_t presence = !DQ_READ();
delay_us(420);
return presence;
}
// 写一个bit
void DS18B20_WriteBit(uint8_t bit) {
SET_DQ_OUT();
DQ_LOW();
delay_us(bit ? 1 : 60);
if(bit) SET_DQ_IN();
delay_us(bit ? 60 : 1);
}
// 读一个bit
uint8_t DS18B20_ReadBit(void) {
uint8_t bit = 0;
SET_DQ_OUT();
DQ_LOW();
delay_us(1);
SET_DQ_IN();
delay_us(14);
bit = DQ_READ();
delay_us(45);
return bit;
}
温度读取函数:
c复制float DS18B20_GetTemp(void) {
if(!DS18B20_Reset()) return -999; // 设备未响应
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0x44); // 启动温度转换
while(!DS18B20_ReadBit()); // 等待转换完成
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0xBE); // 读取暂存器
uint8_t tempL = DS18B20_ReadByte();
uint8_t tempH = DS18B20_ReadByte();
int16_t temp = (tempH << 8) | tempL;
return temp * 0.0625; // 转换为摄氏度
}
3.3 主程序逻辑
主循环的处理流程如下:
c复制while(1) {
// 1. 读取温度
float temp = DS18B20_GetTemp();
// 2. 处理按键输入
if(KEY1_PRESSED()) high_threshold += 0.5;
if(KEY2_PRESSED()) high_threshold -= 0.5;
if(KEY3_PRESSED()) low_threshold += 0.5;
if(KEY4_PRESSED()) low_threshold -= 0.5;
// 3. 更新显示
OLED_ShowTemp(temp);
OLED_ShowThresholds(high_threshold, low_threshold);
// 4. 控制逻辑
if(temp > high_threshold) {
FAN_ON();
LED_ON();
BUZZER_ALARM();
}
else if(temp < low_threshold) {
FAN_OFF();
LED_OFF();
BUZZER_ALARM();
}
else {
FAN_OFF();
LED_OFF();
BUZZER_OFF();
}
delay_ms(200); // 适当延时
}
4. Proteus仿真要点
4.1 仿真电路搭建
在Proteus中搭建仿真电路时,需要注意以下几点:
- STM32模型选择:使用STM32F103C6或C8模型,它们资源足够且仿真支持良好
- DS18B20设置:在元件属性中设置初始温度值,或启用动态温度变化模拟
- 虚拟终端:可以添加一个虚拟终端监控调试输出
- 电源配置:确保所有元件供电电压一致(通常3.3V)
4.2 常见仿真问题解决
问题1:DS18B20不响应
- 检查上拉电阻是否添加(4.7K)
- 确认单总线时序符合要求
- 检查Proteus中DS18B20的模型参数设置
问题2:OLED不显示
- 确认I2C地址设置正确(通常0x78或0x7A)
- 检查I2C引脚配置(开漏输出)
- 确保初始化序列完整发送
问题3:按键无反应
- 检查GPIO模式是否为上拉输入
- 添加软件消抖处理
- 确认Proteus中按键模型连接正确
5. 实际应用优化建议
5.1 硬件优化
- 电源滤波:在STM32和DS18B20的电源引脚附近添加0.1μF去耦电容
- ESD保护:在DS18B20的数据线上添加TVS二极管防止静电损坏
- 风扇控制:使用PWM控制风扇转速,实现更精细的温度调节
- 备用电池:添加CR2032电池为STM32的RTC和备份寄存器供电
5.2 软件优化
温度采样滤波:
c复制#define FILTER_LEN 5
float temp_history[FILTER_LEN];
uint8_t filter_index = 0;
float Get_Filtered_Temp(void) {
float sum = 0;
temp_history[filter_index] = DS18B20_GetTemp();
filter_index = (filter_index + 1) % FILTER_LEN;
for(int i=0; i<FILTER_LEN; i++) {
sum += temp_history[i];
}
return sum / FILTER_LEN;
}
按键长按支持:
c复制void KEY_Process(void) {
static uint32_t press_time[4] = {0};
for(int i=0; i<4; i++) {
if(KEY_PRESSED(i)) {
if(press_time[i] == 0) {
press_time[i] = HAL_GetTick();
}
else if(HAL_GetTick() - press_time[i] > 1000) {
// 长按处理
Threshold_QuickAdjust(i);
press_time[i] = HAL_GetTick() - 900; // 防止连续触发
}
}
else {
if(press_time[i] != 0 && HAL_GetTick() - press_time[i] < 1000) {
// 短按处理
Threshold_StepAdjust(i);
}
press_time[i] = 0;
}
}
}
6. 项目扩展思路
- 无线监控:添加ESP8266模块,通过WiFi将温度数据上传到云平台
- 多区域监测:使用多个DS18B20,利用其单总线特性实现多点温度监测
- 历史记录:添加SPI Flash存储温度历史数据,支持曲线显示
- 智能控制:实现PID算法控制风扇转速,提高温度稳定性
- 低功耗设计:使用STM32的低功耗模式,配合外部中断唤醒
我在实际项目中尝试过添加蓝牙模块(HC-05)实现手机监控,发现这对于调试和参数设置非常方便。通过简单的AT指令配置,就可以建立串口透传,在手机APP上实时查看温度数据和调整阈值。