1. DS18B20温度传感器与51单片机汇编编程概述
DS18B20是一款广泛使用的数字温度传感器,采用单总线(1-Wire)协议与微控制器通信。相比传统的模拟温度传感器,它具有精度高(±0.5℃)、测量范围广(-55℃~+125℃)和接口简单的特点。在51单片机系统中,使用汇编语言直接操作DS18B20可以最大限度地提高代码执行效率,特别适合对时序要求严格的嵌入式应用场景。
使用51单片机汇编语言操作DS18B20的核心难点在于精确控制单总线协议的时序。单总线协议要求主机(单片机)和从机(DS18B20)之间的通信必须严格遵守特定的时间参数,包括复位脉冲、应答脉冲、读写时隙等。这些时序在高级语言中可能被封装隐藏,但在汇编层面需要开发者手动实现每个微秒级的操作。
提示:DS18B20的单总线协议对时序要求极为严格,误差超过±15%就可能导致通信失败。这也是为什么在嵌入式开发中,汇编语言在驱动这类精密传感器时仍具有不可替代的优势。
2. 硬件连接与初始化配置
2.1 电路连接方案
典型的DS18B20与51单片机连接电路非常简单,只需要三根线:
- VDD:接3.3V或5V电源
- GND:接地
- DQ:数据线,接单片机任意I/O口(示例中使用P3.7)
在实际应用中,通常会为DQ线增加一个4.7kΩ的上拉电阻,确保总线在空闲时保持高电平。这个电阻的阻值不能过大或过小,4.7kΩ是经过验证的最佳值,既能保证信号质量,又不会消耗过多电流。
2.2 51单片机初始化设置
示例代码中,单片机初始化部分主要配置了两个关键外设:
- 定时器T1:设置为模式2(8位自动重装),用于产生串口通信的波特率
- 串口:配置为模式1(8位UART),波特率9600,用于输出温度数据
assembly复制MOV TMOD,#21H ; T1模式2,T0模式1
MOV TH1,#0FDH ; 波特率9600
MOV SCON,#50H ; 串口模式1
SETB TR1 ; 启动T1
这段初始化代码体现了51单片机编程的一个典型模式:通过设置特殊功能寄存器(SFR)来配置外设。TMOD寄存器的高4位控制T1,低4位控制T0。21H的配置表示T1工作在模式2(自动重装),T0工作在模式1(16位定时器)。
3. DS18B20通信协议实现细节
3.1 复位与初始化序列
DS18B20的每次通信都必须以复位脉冲开始,这是单总线设备的标准握手过程。复位序列包括:
- 主机拉低总线480-960μs
- 主机释放总线(变为输入模式)
- 等待DS18B20的应答脉冲(60-240μs低电平)
- 总线恢复高电平
assembly复制RESET:
CLR P3.7 ; 拉低总线
MOV B,#48 ; 延时480μs
LCALL DELAY
SETB P3.7 ; 释放总线
RET
这里的延时480μs是通过DELAY子程序实现的,B寄存器传递参数48表示循环48次,每次约10μs。实际应用中,这个延时需要根据单片机时钟频率精确计算,误差必须控制在协议允许范围内。
3.2 读写时序实现
DS18B20的读写操作基于严格的时隙(timeslot)控制:
写时隙:
- 写0:拉低总线至少60μs,然后释放
- 写1:拉低总线1-15μs,然后释放并保持高电平至时隙结束
assembly复制WRITE0:
CLR P3.7 ; 拉低总线
MOV B,#6 ; 延时60μs
LCALL DELAY
SETB P3.7 ; 释放总线
RET
WRITE1:
CLR P3.7 ; 拉低总线
NOP ; 短暂延时约2μs
NOP
SETB P3.7 ; 释放总线
MOV B,#6 ; 保持高电平
LCALL DELAY
RET
读时隙:
- 主机拉低总线1-15μs
- 释放总线并采样
- 整个读时隙至少60μs
assembly复制READ_BIT:
CLR P3.7 ; 拉低总线
NOP ; 短暂延时约2μs
NOP
SETB P3.7 ; 释放总线
NOP ; 等待传感器响应
NOP
MOV C,P3.7 ; 读取总线状态
MOV B,#6 ; 完成时隙
LCALL DELAY
RET
注意:在实际调试中,读写时隙的精确度直接影响通信成功率。建议使用逻辑分析仪或示波器观察总线波形,确保各时间参数符合DS18B20数据手册的要求。
4. 温度采集流程解析
4.1 完整温度读取流程
示例代码中的温度采集遵循标准DS18B20操作流程:
- 初始化传感器(复位)
- 发送Skip ROM命令(CCH)
- 启动温度转换(44H)
- 等待转换完成(750ms)
- 再次初始化传感器
- 发送Skip ROM命令
- 发送读取暂存器命令(BEH)
- 读取温度数据(2字节)
assembly复制MLOOP:
LCALL INIT ; 初始化
LCALL SKIP_ROM ; 跳过ROM匹配
LCALL CONVERT_T ; 启动温度转换
LCALL DELAY_750ms ; 等待转换
LCALL INIT ; 重新初始化
LCALL SKIP_ROM
LCALL READ_PAD ; 读取暂存器
LCALL READ_BYTE ; 读取温度低字节
MOV SBUF,A ; 串口输出
LCALL READ_BYTE ; 读取温度高字节
MOV SBUF,A
LCALL DELAY_750ms
JMP MLOOP ; 循环采集
4.2 温度数据格式处理
DS18B20返回的温度数据为16位二进制补码形式:
- 低字节:LSB,包含温度的小数部分
- 高字节:MSB,包含温度的整数部分和符号位
温度值计算方法:
- 将两个字节合并为16位有符号整数
- 正温度:直接乘以0.0625(分辨率)
- 负温度:取补码后再乘以0.0625
例如,读取到0x0191表示:
- 二进制:0000000110010001
- 十进制:25.0625℃
而0xFF6F表示:
- 二进制补码:1111111101101111 → -0000000010010001
- 十进制:-9.0625℃
5. 关键子程序详解
5.1 延时函数实现
精确延时是单总线协议实现的关键。示例中提供了两个延时函数:
- DELAY:参数化延时,B寄存器指定10μs的倍数
- DELAY_750ms:固定750ms延时,用于温度转换等待
assembly复制DELAY: ; 10μs×B
MOV R1,B
LP:
MOV R0,#10 ; 内层循环
LP1:
DJNZ R0,LP1 ; 约1μs
DJNZ R1,LP ; 外层循环
RET
DELAY_750ms: ; 使用T0定时器
MOV R0,#75 ; 75×10ms
DLOOP2:
MOV TH0,#0D8H ; 定时10ms初值
MOV TL0,#0F0H
SETB TR0 ; 启动T0
DLOOP3:
JB F0,DLOOP3 ; 等待中断
SETB F0
DJNZ R0,DLOOP2
RET
5.2 定时器中断处理
DELAY_750ms函数依赖T0中断来标记10ms时间到:
assembly复制INT_T0:
CLR TR0 ; 停止T0
CLR TF0 ; 清除溢出标志
CLR F0 ; 清除标志位
RETI
这种软件标志位(F0)配合硬件定时器的方式,是51单片机实现长延时的经典方法。相比纯软件延时,它能更精确地控制时间,同时允许CPU在等待期间处理其他任务。
6. 实际应用中的问题与解决方案
6.1 常见通信故障排查
-
无应答信号:
- 检查硬件连接,确保DQ线有4.7kΩ上拉电阻
- 测量电源电压,DS18B20要求2.8V-5.5V
- 确认复位脉冲宽度在480-960μs范围内
-
数据读取错误:
- 检查读写时隙时序,特别是释放总线后的采样时间
- 确保两次操作之间有足够恢复时间
- 在强干扰环境中,可适当降低通信速率
-
温度值异常:
- 检查电源稳定性,电压波动会影响A/D转换
- 确保温度转换等待时间足够(12位分辨率需750ms)
- 验证CRC校验(示例代码中未实现)
6.2 优化建议
-
CRC校验:DS18B20支持8位CRC校验,可增强通信可靠性。暂存器的第8字节就是前8字节的CRC值。
-
多点测温:当总线上有多个DS18B20时,需要使用Match ROM命令(55H)进行地址匹配,而不是Skip ROM。
-
电源模式:DS18B20支持寄生电源模式(VDD接地),但此时总线在温度转换期间必须保持高电平以供电。
-
分辨率设置:通过配置寄存器可以设置9-12位的分辨率,权衡转换时间和精度。
assembly复制; 设置12位分辨率(默认)
MOV A,#7FH ; 配置寄存器值
LCALL WRITE_BYTE
7. 代码优化与扩展思路
7.1 汇编代码优化技巧
- 循环展开:READ_BYTE子程序可以优化为循环结构,减少代码量:
assembly复制READ_BYTE:
MOV R2,#8 ; 8位计数器
READ_LOOP:
LCALL READ_BIT
RRC A ; 移入进位位
DJNZ R2,READ_LOOP
RET
-
延时参数化:将DELAY_750ms改为可变延时,通过参数指定时间长度。
-
中断优化:在主循环中加入休眠模式,降低功耗。
7.2 功能扩展方向
-
多点温度监测:通过ROM搜索算法实现多DS18B20自动识别。
-
温度报警:利用DS18B20内置的温度报警功能,设置上下限阈值。
-
数据记录:结合EEPROM存储历史温度数据。
-
上位机通信:完善串口协议,与PC软件进行数据交互。
在资源受限的51单片机系统中,这些扩展功能需要仔细权衡代码大小和执行效率。汇编语言虽然开发效率较低,但能提供最优的性能和最小的内存占用,特别适合大批量生产的低成本嵌入式应用。