DS18B02温度传感器与1-WIRE单总线通信(笔记)

📅 2026/7/24 18:08:36 👁️ 阅读次数 📝 编程学习
DS18B02温度传感器与1-WIRE单总线通信(笔记)

一、DS18B02

介绍:数字温度传感器,与模拟相比(热敏电阻,要通过ad芯片转化),功能强,硬件简单,易扩展,抗干扰性强;测温范围:-55C ~ +125C;通信接口:1-wire(单总线);其他特点:总线结构,内置温度报警功能,可寄生供电

引脚及应用电路(STC89C52):

二、单总线

介绍:1-wire BUS,一种通用数据总线,异步,半双工,只需要一根通信线DQ,省通信线

硬件规范:DQ开漏输出,添加上拉电阻,阻值4.7k左右,线与;若从机使用寄生供电,主机需配备强上拉输出电路

软件规范:

1. 初始化:主机将总线拉低至少480微秒,然后释放总线(电阻上拉弱上拉),等待15-60微秒后,存在的从机会拉低总线60-240微秒以响应主机,之后释放

#include <REGX52.H> sbit OneWire_DQ=P3^7; unsigned char OneWire_Init(void) { unsigned char i; unsigned char AckBit; OneWire_DQ=1; OneWire_DQ=0; i = 247;while (--i); //Delay 500us OneWire_DQ=1; i = 32;while (--i); //Delay 70us AckBit=OneWire_DQ; i = 247;while (--i); //Delay 500us return AckBit; }

2.发送一位:主机将总线拉低60-120微秒,然后释放总线,表示发送0,主机将总线拉低1-15微秒,然后释放总线,表示发送1,从机将会在30微秒后读取电频,整个时间片应大于60微秒

(总线恢复时间:1微秒,对51单片机来说很短,暂时不用管)

void OneWire_SendBit(unsigned char Bit) { unsigned char i; OneWire_DQ=0; i = 4;while (--i); //Delay 10us OneWire_DQ=Bit; i = 24;while (--i); //Delay 50us OneWire_DQ=1; }

3.接收一位:主机将总线拉低1-15微秒,然后释放总线,并在拉低后15微秒内读取总线电平(尽量贴近15微秒的末尾),读取为低电平则为接收0,为高电平为接收1,整个时间片应大于60微秒

unsigned char OneWire_ReceiveBit(void) { unsigned char i; unsigned char Bit; OneWire_DQ=0; i = 2;while (--i); //Delay 5us OneWire_DQ=1; i = 2;while (--i); //Delay 5us Bit=OneWire_DQ; i = 24;while (--i); //Delay 50us return Bit; }

4.发送/接收一个字节:也就是连续发送/接收八次字节

void OneWire_SendByte(unsigned char Byte) { unsigned char i; for(i=0;i<8;i++) { OneWire_SendBit(Byte&(0x01<<i)); } } unsigned char OneWire_ReceiveByte(void) { unsigned char i; unsigned char Byte=0x00; for(i=0;i<8;i++) { if(OneWire_ReceiveBit()){Byte|=(0x01<<i);} } return Byte; }

三、DS18B02操作流程和数据帧

初始化:从机复位,主机判断从机是否响应

ROM操作:ROM指令+本指令需要的读取操作

功能操作(RAM操作):功能指令+本指令需要的读取操作

1.温度变化:初始化,跳过ROM,开始温度变化

void DS18B20_ConvertT(void) { OneWire_Init(); OneWire_SendByte(DS18B20_SKIP_ROM); OneWire_SendByte(DS18B20_CONVERT_T); }

2.温度读取:初始化,跳过ROM,读暂存器,连续的读操作(温度转换参考最后的温度表)

float DS18B20_ReadT(void) { unsigned char TLSB,TMSB; int Temp; float T; OneWire_Init(); OneWire_SendByte(DS18B20_SKIP_ROM); OneWire_SendByte(DS18B20_READ_SCRATCHPAD); TLSB=OneWire_ReceiveByte(); TMSB=OneWire_ReceiveByte(); Temp=(TMSB<<8)|TLSB; //拼接温度 T=Temp/16.0; //除四位二进制转为小数 return T; }

3.主函数温度计算与显示:

void main() { LCD_Init(); LCD_ShowString(1,1,"T:"); LCD_ShowString(2,1,"TH:"); LCD_ShowString(2,9,"TL:"); LCD_ShowSignedNum(2,4,THigh,3); LCD_ShowSignedNum(2,12,TLow,3); while(1) { DS18B20_ConvertT(); //启动温度转换 T = DS18B20_ReadT(); //读取温度 if(T < 0) { LCD_ShowChar(1,3,'-'); T = -T; } else { LCD_ShowChar(1,3,'+'); //负数转为正数,直接在前加上负号 } LCD_ShowNum(1,4,T,3); //分割为整数和小数显示 LCD_ShowChar(1,7,'.'); LCD_ShowNum(1,8,(unsigned long)(T*10000)%10000,4); //取出小数部分 } }

4.读序问题:1-WIRE总线使用中断时,需要解决读序问题,因为调用中断会影响通信的延时过程,所以只能在协议通信时禁用中断,但这样操作也会对定时器造成干扰,而I2C有独立的时钟线,被中断也没事

附表(温度存储格式)