1. 项目概述
这个多点测温系统是我去年为一个农业大棚项目设计的温度监控方案。当时农户需要在5个不同位置同时监测温度,要求误差不超过±0.5℃,而且需要实时显示所有测点的数据。经过多次实测验证,这个基于51单片机和DS18B20的方案完全满足了需求,整套硬件成本不到50元,比市面上的成品温度监控系统便宜了80%以上。
DS18B20是Dallas半导体(现被Maxim收购)推出的单总线数字温度传感器,最大特点就是只需要一根数据线就能实现供电和通信。在多点测温场景下,每个DS18B20都有唯一的64位ROM编码,单片机可以通过这些编码区分不同传感器,实现真正的"一线多机"通信。
2. 硬件设计解析
2.1 核心器件选型
主控选用STC89C52RC,这是宏晶科技推出的增强型51单片机,相比传统8051有8K Flash存储空间和512字节RAM,完全够用。选择它的主要原因是:
- 价格便宜(约5元/片)
- 支持5V供电,与DS18B20电压匹配
- 有足够的IO口驱动显示模块
DS18B20选用TO-92封装(看起来像普通三极管),防水型的价格约8元/个。特别注意要买正品,市面上有些山寨货的测温精度会差很多。实测正品在-10℃~85℃范围内误差确实能控制在±0.5℃以内。
2.2 电路设计要点
单总线拓扑结构要注意三点:
- 总线需接4.7KΩ上拉电阻
- 传感器VDD引脚直接接电源(寄生供电模式不稳定)
- 总线长度不超过20米(超过需加驱动)
具体连接方式:
- 所有DS18B20的DQ引脚并联
- 每个VDD接5V电源
- 每个GND接地
- 总线通过4.7KΩ电阻上拉到5V
重要提示:焊接DS18B20时一定要控制好温度,超过300℃可能损坏传感器。我建议使用恒温烙铁,温度设置在260℃左右,焊接时间不超过3秒。
3. 软件实现详解
3.1 单总线通信协议
DS18B20的通信时序要求非常严格,必须精确控制微秒级延时。以初始化时序为例:
c复制void DS18B20_Reset(void)
{
DQ = 1; // 先拉高
Delay_us(8); // 延时8us
DQ = 0; // 主机拉低480us~960us
Delay_us(500); // 实测480us最稳定
DQ = 1; // 释放总线
Delay_us(60); // 等待15~60us
while(DQ); // 等待DS18B20拉低
Delay_us(240); // 等待存在脉冲结束
}
读取一位数据的典型流程:
- 主机拉低总线至少1us
- 在15us内读取总线状态
- 保持总计60us的时序周期
3.2 多点测温实现
关键是要通过ROM匹配选择特定传感器。操作步骤:
- 发送0x55(匹配ROM命令)
- 发送64位ROM编码(8字节)
- 发送0x44(开始转换)
- 延时750ms(12位精度所需时间)
- 再次匹配ROM
- 发送0xBE(读取暂存器)
ROM搜索算法比较复杂,这里给出简化版实现:
c复制void SearchROM(unsigned char *ROM)
{
unsigned char k = 0;
unsigned char last_zero = 0;
Reset();
WriteByte(0xF0); // 搜索ROM命令
do {
bit1 = ReadBit();
bit2 = ReadBit();
if(bit1 && bit2) break; // 搜索结束
if(bit1 == bit2) { // 出现分歧
if(k < last_zero) {
// 取之前记录的分支
} else {
last_zero = k; // 记录新的分歧点
}
}
// 根据策略选择0或1
WriteBit(bit_select);
ROM[k/8] |= bit_select << (k%8);
k++;
} while(k < 64);
}
4. 温度数据显示方案
4.1 LCD1602显示实现
使用四线驱动方式节省IO口:
c复制void LCD_WriteCmd(unsigned char cmd)
{
RS = 0;
RW = 0;
EN = 1;
DataPort = cmd;
Delay_ms(5);
EN = 0;
}
void DisplayTemp(float temp)
{
char str[16];
sprintf(str, "T1:%5.1fC", temp);
LCD_WriteString(0, 0, str); // 第一行显示
}
4.2 多路数据轮询显示
我设计了三屏轮换显示方案:
- 第一屏:5个传感器的实时温度
- 第二屏:当前最高/最低温度
- 第三屏:温度变化曲线
通过定时器中断每3秒切换一屏:
c复制void Timer0_ISR() interrupt 1
{
static unsigned char screen = 0;
TH0 = 0x3C; // 重装50ms定时
TL0 = 0xB0;
if(++count >= 60) { // 3秒到
count = 0;
screen = (screen + 1) % 3;
UpdateDisplay(screen);
}
}
5. 系统优化与问题排查
5.1 测温精度提升技巧
- 电源去耦:每个DS18B20的VDD引脚加0.1μF陶瓷电容
- 总线干扰抑制:长距离传输时加磁珠滤波
- 软件滤波:采用滑动平均算法
c复制float MovingAverage(float new_val)
{
static float buffer[5];
static unsigned char index = 0;
float sum = 0;
buffer[index] = new_val;
index = (index + 1) % 5;
for(unsigned char i=0; i<5; i++) {
sum += buffer[i];
}
return sum / 5;
}
5.2 常见故障排查
问题1:检测不到任何传感器
- 检查上拉电阻是否接好
- 测量总线电压(正常应为5V)
- 确认时序延时准确(用示波器观察)
问题2:某个传感器数据异常
- 单独测试该传感器
- 检查ROM编码是否冲突
- 查看传感器供电是否稳定
问题3:温度跳变大
- 检查电源纹波(应小于100mV)
- 尝试降低转换精度(9位)
- 增加软件滤波
6. 项目扩展方向
这个基础框架还可以进一步扩展:
- 增加无线传输模块(如ESP8266)实现远程监控
- 添加SD卡存储温度历史数据
- 结合继电器实现温度自动控制
- 改用OLED显示屏提升可视角度
我在实际部署中发现,将DS18B20用热缩管封装后浸入硅脂,再插入金属护套中,既能保证测温响应速度,又能有效防护潮湿环境。这种安装方式在大棚中使用一年后,传感器完好率仍然保持100%。