一、系统概述
基于STC89C52RC单片机(11.0592MHz晶振),通过DS18B20数字温度传感器实现环境温度实时采集,结合LCD1602液晶显示模块输出温度值(支持正负温度显示,精度±0.5℃),适用于温室监控、家电温度检测等场景。系统采用单总线通信协议,仅需1个IO口连接传感器,硬件简单,软件模块化设计。
二、硬件设计
2.1 核心组件
| 模块 | 型号/参数 | 功能说明 |
|---|---|---|
| 主控 | STC89C52RC(8位,11.0592MHz) | 温度采集、数据处理、LCD驱动 |
| 温度传感器 | DS18B20(单总线,数字输出) | 检测环境温度(-55~+125℃,精度±0.5℃) |
| 显示模块 | LCD1602(16×2字符型液晶) | 显示温度值(格式:Temp: XX.X℃) |
| 电源 | 5V DC电源(或USB供电) | 为单片机和传感器供电 |
2.2 硬件连接
| 模块 | 引脚(STC89C52RC) | 说明 |
|---|---|---|
| DS18B20 | P3.7(DQ) | 单总线数据引脚(需4.7kΩ上拉电阻) |
| LCD1602 | RS→P2.0,RW→P2.1,E→P2.2 | 控制引脚 |
| D0~D7→P0口 | 数据总线(8位并行) | |
| 电源 | VCC→5V,GND→GND | 共地连接 |
三、软件设计(Keil C51)
3.1 开发环境
IDE:Keil μVision5(C51编译器)
晶振:11.0592MHz(确保延时精度与串口兼容性)
通信协议:DS18B20单总线协议(1-Wire)
3.2 核心代码实现
3.2.1 头文件与引脚定义
#include<reg52.h>#include<intrins.h>// ==================== 引脚定义 ====================#defineDQP3_7// DS18B20数据引脚(单总线)#defineLCD_RSP2_0// LCD1602 RS#defineLCD_RWP2_1// LCD1602 RW#defineLCD_EP2_2// LCD1602 E#defineLCD_DBP0// LCD1602数据总线(D0~D7)// ==================== 全局变量 ====================unsignedchartemp_int=0;// 温度整数部分unsignedchartemp_frac=0;// 温度小数部分(0.1℃精度)bit temp_sign=0;// 温度符号(0=正,1=负)3.2.2 延时函数(微秒/毫秒级,11.0592MHz晶振)
// 微秒延时(误差±1us,@11.0592MHz,1机器周期≈0.907us)voidDelayUs(unsignedintus){while(us--){_nop_();_nop_();_nop_();_nop_();// 4个_nop_≈3.6us,需调整循环次数_nop_();_nop_();_nop_();_nop_();}}// 毫秒延时(@11.0592MHz,1ms≈1100机器周期)voidDelayMs(unsignedintms){unsignedinti,j;for(i=0;i<ms;i++)for(j=0;j<110;j++);// 110次循环≈1ms}3.2.3 DS18B20单总线驱动
// DS18B20初始化(检测设备是否存在)bitDS18B20_Init(){bit ack;DQ=1;DelayUs(2);// 总线拉高DQ=0;DelayUs(500);// 复位脉冲(480~960us)DQ=1;DelayUs(60);// 释放总线,等待应答ack=DQ;// 读取应答信号(0=存在,1=不存在)DelayUs(420);// 等待初始化完成return!ack;// 返回1表示设备存在}// 向DS18B20写一个字节voidDS18B20_WriteByte(unsignedchardat){unsignedchari;for(i=0;i<8;i++){DQ=0;_nop_();// 拉低总线(写时隙开始)DQ=dat&0x01;// 输出最低位DelayUs(60);// 保持60us(写0时持续60us,写1时拉高后释放)DQ=1;_nop_();// 释放总线dat>>=1;// 准备下一位}}// 从DS18B20读一个字节unsignedcharDS18B20_ReadByte(){unsignedchari,dat=0;for(i=0;i<8;i++){DQ=0;_nop_();// 拉低总线(读时隙开始)dat>>=1;DQ=1;_nop_();// 释放总线if(DQ)dat|=0x80;// 读取数据位(高电平为1)DelayUs(60);// 保持60us}returndat;}3.2.4 温度采集与转换
// 读取温度值(返回0成功,1失败)bitDS18B20_ReadTemp(){unsignedchartemp_l,temp_h;if(!DS18B20_Init())return1;// 初始化失败DS18B20_WriteByte(0xCC);// 跳过ROM命令(单设备)DS18B20_WriteByte(0x44);// 启动温度转换(12位精度,需750ms)DelayMs(750);// 等待转换完成if(!DS18B20_Init())return1;// 重新初始化DS18B20_WriteByte(0xCC);// 跳过ROMDS18B20_WriteByte(0xBE);// 读取温度寄存器(共2字节)temp_l=DS18B20_ReadByte();// 低8位(小数部分+低4位整数)temp_h=DS18B20_ReadByte();// 高8位(高4位整数+符号位)// 解析温度值(12位精度:高5位符号位,中间7位整数,低4位小数)if(temp_h&0x80){// 负数(符号位为1)temp_sign=1;temp_h=~temp_h;// 取反temp_l=~temp_l+1;// 补码转换if(temp_l==0)temp_h++;// 进位}else{temp_sign=0;}// 计算整数和小数部分(0.0625℃/LSB,保留1位小数)temp_int=(temp_h<<4)|(temp_l>>4);// 整数部分(高4位+低4位)temp_frac=(temp_l&0x0F)*625/1000;// 小数部分(0.0625 * 1000=62.5,取0.1℃精度)return0;}3.2.5 LCD1602显示驱动
// LCD写命令voidLCD_WriteCmd(unsignedcharcmd){LCD_RS=0;LCD_RW=0;LCD_DB=cmd;DelayUs(5);LCD_E=1;DelayUs(5);LCD_E=0;}// LCD写数据voidLCD_WriteData(unsignedchardat){LCD_RS=1;LCD_RW=0;LCD_DB=dat;DelayUs(5);LCD_E=1;DelayUs(5);LCD_E=0;}// LCD初始化voidLCD_Init(){LCD_WriteCmd(0x38);// 8位数据,2行显示,5×7点阵LCD_WriteCmd(0x0C);// 开显示,关光标LCD_WriteCmd(0x06);// 光标右移,不滚动LCD_WriteCmd(0x01);// 清屏DelayMs(2);}// 显示温度值(格式:Temp: XX.X℃ 或 -XX.X℃)voidLCD_DisplayTemp(){LCD_WriteCmd(0x80);// 第一行首地址LCD_WriteData('T');LCD_WriteData('e');LCD_WriteData('m');LCD_WriteData('p');LCD_WriteData(':');LCD_WriteData(' ');if(temp_sign){// 负数LCD_WriteData('-');if(temp_int<10)LCD_WriteData('0');// 补零(如-5.5℃显示为-05.5℃)LCD_WriteData(temp_int/10+'0');LCD_WriteData(temp_int%10+'0');}else{// 正数if(temp_int<10)LCD_WriteData(' ');// 对齐(如 5.5℃显示为 5.5℃)else{LCD_WriteData(temp_int/10+'0');LCD_WriteData(temp_int%10+'0');}}// 显示小数部分LCD_WriteData('.');LCD_WriteData(temp_frac+'0');// 0.1℃精度(0~9对应0.0~0.9℃)LCD_WriteData(0xDF);// ℃符号(LCD字库中的特殊字符,需自定义或查表)LCD_WriteData('C');}3.2.6 主函数
voidmain(){LCD_Init();// 初始化LCDDelayMs(100);// 等待LCD稳定while(1){if(DS18B20_ReadTemp()==0){// 读取温度成功LCD_DisplayTemp();// 显示温度}else{// 读取失败(显示错误)LCD_WriteCmd(0x80);LCD_WriteData('E');LCD_WriteData('r');LCD_WriteData('r');}DelayMs(1000);// 1秒刷新一次}}参考代码 51单片机实时温度源码www.youwenfan.com/contentcst/182665.html
四、关键问题与解决方案
4.1 单总线时序错误
问题:DS18B20对时序要求严格,延时误差导致通信失败。
解决:
用示波器校准
DelayUs函数(11.0592MHz下,1us≈1.085机器周期,需调整循环次数);确保
DS18B20_Init中复位脉冲>480us,应答检测>60us。
4.2 温度值跳变
问题:环境干扰或电源波动导致读数异常。
解决:
软件添加滑动平均滤波(连续3次采样取平均);
电源端并联100μF电解电容+0.1μF瓷片电容滤波。
4.3 LCD显示乱码
问题:LCD初始化时序错误或数据总线接触不良。
解决:
检查
LCD_Init中命令顺序(0x38→0x0C→0x06→0x01);确保P0口加上拉电阻(10kΩ排阻),避免高阻态。
五、测试与验证
硬件连接:按2.2节连接DS18B20(P3.7)和LCD1602(P0+P2.0~P2.2),确保上拉电阻正确焊接。
功能测试:用手触摸DS18B20,观察LCD显示温度是否上升(如从25.0℃升至30.5℃)。
精度验证:对比标准温度计,误差<±0.5℃(室温下)。
六、总结
基于51单片机和DS18B20实现了实时温度监测,核心是单总线通信时序和温度数据解析。通过LCD1602直观显示,可扩展为温度报警(超阈值蜂鸣器响)、串口上传(PC端记录)等功能,满足低成本温度监测需求。