51单片机-使用单总线通信协议驱动DS18B20模块教程
本章概述思维导图
51单片机驱动DS18B20模块
DS18B20简介
DS18B20是一款由 Maxim Integrated(原 Dallas Semiconductor)公司推出的单总线接口数字温度传感器,采用单总线通信协议,具有高精度、低功耗、抗干扰能力强等特点,广泛应用于环境监测、工业控制、智能家居等领域。DS18B20实物图如下:
DS18B20引脚定义
GND(1脚):电源脚
DQ(2脚):单总线数据输入/输出
VDD(3脚):电源正极(3.0V至5.5V)
DS18B20核心特点
1、测温范围:-55℃~+125℃,覆盖绝大多数工业与民用场景;
2、测温精度在-10℃~+85℃范围内精度为±0.5℃,全量程范围内固有误差为±1℃。
3、适应供电电压:3.0V~5.5V,适应电压范围更宽。在寄生电源方式下可由数据线供电。
4、可编程的分辨率为9位~12位,对应温度变化的最小分辨率为0.5℃(9位)、0.25℃(10位)、0.125℃(11位)、0.0625℃(12位)、可实现高精度测温。
5、转换时间:
在9位分辨率时最多在93.75ms内把温度转换为数字;
在10位分辨率时最多在187.5ms内把温度转换为数字;
在11位分辨率时最多在375ms内把温度转换为数字;
在12位分辨率时最多在750ms内把温度转换为数字;
6、通信接口:单总线(1-Wire),仅需一根数据线(DQ)即可实现微处理器与DS18B20的双向通讯;
7、DS18B20在使用中不需要任何外围元件,全部传感器元件及转换电流集成在内部集成电路上
8、DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温。
9、测量结果直接输出数字温度信号,以单总线串行传输给CPU,同时可传输CRC校验码,具有极强的抗干扰纠错能力;
10、负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
DS18B20供电模式
1、外部电源模式
VDD引脚接3.0V至5.5V电源,GND接地。
优点:电源稳定,适合多传感器或长距离布线。
2、寄生电源模式
VDD与GND均接地,通过DQ线供电(需上拉电阻)
优点:减少连线,适合空间受限场景
注意:部分批次DS18B20可能不支持寄生电源模式,需额外电路辅助。
DS18B20内部结构简介
DS18B20 是一款高精度数字温度传感器,其内部结构复杂且功能强大,主要由 64位光刻ROM、温度传感器、非挥发性存储器(EEPROM)、高速暂存器(SRAM)、配置寄存器、CRC校验模块 等部分组成。以下是对其内部结构图和寄存器的详细讲解:
1、62位光刻ROM
作用:存储DS18B20的唯一序列号,用于在单总线上区分多个传感器。
组成:
前8位(10H):产品类型标号,表示这是DS18B20温度传感器。
中间48位:该DS18B20的唯一序列号,每个传感器都不相同。
后8位:前56位的循环冗余校验码(CRC),用于校验数据的正确性。
2、温度传感器
通常由热敏元件(如二极管、热电阻)和模拟放大电路组成。
模拟信号需经过模数转换器(ADC)转换为数字值,才能被微控制器读取。
在DS18B20中,温度传感器与Σ-Δ型ADC集成在一起,形成完整的模拟前端。
作用:完成对温度的测量,并将测量结果转换为数字信号。
3、非挥发性存储器(EEPROM)
作用:存储用户设置的报警温度阈值(高温触发器TH和低温触发器TL)和配置寄存器的值,即使掉电也不会丢失。
特点:
可电擦除可编程(EEPROM),支持多次写入和擦除。
存储的数据在DS18B20上电时会被自动复制到高速暂存器中。
4、配置寄存器
配置寄存器是一个8位寄存器(位于高速暂存器中,地址为字节4),包含可编程位(R1、 R0)和保留位。
作用:设置DS18B20的温度精度和转换时间
如图所示:配置寄存器格式
位0-4一直都是1,位7:TM是测试模式位,用于设置DS18B20在工作模式还是测试 模式,在DS18B20出厂时TM被设置为0。位7和位0-4都属于保留位,禁止写入。
位6和位5(R1和R0):用于设置温度精度和转换时间。如下图所示:
5、CRC校验模块
作用:生成和校验CRC码,确保数据传输的正确性。
特点:
采用CRC-8校验算法,多项式为X8+X5+X4+1。
在数据写入或读取时,DS18B20会自动计算CRC码,并与接收到的CRC码进行比较, 以校验数据的正确性。
6、高速暂存器(SRAM)
DS18B20的高速暂存器(SRAM)是一个关键的内部存储结构,它包含了9个字节的存 储空间,每个字节都有特定的功能。
作用:在温度转换和数据读写过程中临时存储数据。
以下是详细介绍:
字节0和字节1:这两个字节用于存储温度转换后的数据值,是只读寄存器。温度数据 以二进制补码形式存储,支持16位符号扩展,其中前5位为符号位(表 示温度的正负),后11位为温度的二进制数值。例如,+125℃的数字输 出为07D0H,-25.0625℃的数字输出为FE6FH。
字节2和字节3:这两个字节用于存储温度报警的上限值(TH)和下限值(TL)。这两个寄 存器均为8位,用户可以通过编程设置这两个值,以实现温度报警功能。 当温度测量结果低于TL或高于TH时,DS18B20会设置报警标志。
字节4:这是配置寄存器,用于设置DS18B20的温度测量分辨率。分辨率可设置为9位、10 位、11位或12位,对应的温度分辨率为0.5℃、0.25℃、0.125℃和0.0625℃。配 置寄存器的格式中,位5和位6用于设置分辨率,其余位在读操作时有固定值,在 写操作时可为任意值。
字节5、字节6和字节7:这三个字节为保留位,未被使用,通常用于内部温度转换和计算 的暂存单元。
字节8:这个字节用于存储CRC校验码,它是对前面8个字节进行校验的结果,用于确保数据的完整性。CRC校验码由CRC发生器产生,采用CRC-8校验算法。
DS18B20温度转换分析
当温度转换命令(44H)发布后,经转换所得的温度值以二字节补码形式存放在高速暂存器(SRAM)的第0和第1个字节。存储的两个字节,高字节的前5位是符号位S,如是负数则为11111,如是正数则为00000;,读取时低位在前,高位在后。数据格式如下:
示例图:
本章拿+125℃和-55℃举例
如果测得的温度大于0,高字节的前五位符号位为”0”,这要将测得的数字乘以0.0625(配置寄存器默认精度为12位)即可得到实际温度值;
公式:数据*0.0625;
BIN:0000 0111 1101 0000=HEX:07D0=2000;
2000*0.0625=+125℃;
如果测得的温度小于0,高字节的前五位符号位为”1”,这要将测得的数字先取反,在加1后在乘以即可0.0625(配置寄存器默认精度为12位)即可得到实际温度值;
公式:((~数据)+1)*0.0625;
取反操作BIN:1111 1100 1001 0000=~0000 0011 0110 1111
加1操作HEX:368+1=369
乘以0.0625操作:873*0.065=54.5625℃
因为是负温度所以要加上负号:-54.5625℃≈-55℃
DS18B20典型温度读取过程
DS18B20的典型温度读取过程为:复位(初始化)→发送SKIP ROM命令(0xCC)→发开始转换命令(0x44)→延时→复位(初始化)→发送SKIP ROM命令(0xCC)→发送读存储器命令(0xBE)→连续读出两个字节数据(即温度)→结束
单总线传输协议简介
单总线传输协议(1-Wire Protocol)是一种由美国达拉斯半导体公司(现属德州仪器)开发的低速串行通信协议,其核心特点是通过单根数据线实现主设备与多个从设备之间的双向通信,同时支持供电(寄生供电模式)。
核心特性
单线接口:仅需1根数据线(DQ)即可完成通信和供电(寄生供电模式下),极简的硬件设计。
半双工通信:数据在主从设备间分时双向传输,同一时刻仅一方发送。
低速传输:典型速率15.4kbps(标准模式),支持高速模式(如125kbps)。
多设备支持:通过唯一64位ID(ROM Code)区分多个从设备,实现单总线多节点连接。
寄生供电:从设备可从数据线获取能量(需主设备提供强上拉电阻),减少引脚占用。
物理层
总线拓扑:主设备通过开漏/开集驱动器连接总线,从设备通过三态门接入。
上拉电阻:总线空闲时通过上拉电阻保持高电平(典型值4.7kΩ)。
电平标准:兼容TTL/CMOS逻辑,高电平≥2.4V,低电平≤0.8V。
通讯时序
单总线通信时序围绕初始化、写时隙、读时隙三大核心机制展开,通过严格的时间窗口控制实现主从设备间的双向数据传输。以下从初始化、写时隙、读时隙三个方面详细讲解单总线通信时序:
一、初始化时序
初始化是单总线通讯的起始步骤,用于建立主从设备之间的连接。其时序要求如下:
1、主机拉低总线:主机将单总线拉低480~960微秒,以产生复位信号。
2、释放总线:主机释放总线,进入接收模式。此时,总线由上拉电阻拉至高电平。
3、从机应答:从机检测到总线的上升沿后,等待15~60微秒,然后拉低总线60~240 微秒,以产生应答信号。
4、主机接收应答:主机接收到从机的应答信号后,表明从机已准备就绪,初始化过程完成。
二、写时隙
写时隙用于主机向从机发送数据,包括写0和写1两种时隙。其时序要求如下:
1、写0时隙
主机拉低总线,并保持低电平至少60微秒(通常为60~120微秒)。
在此期间,从机在总线上采样电平状态。如果采样到低电平,则写入逻辑0。
2、写1时隙
主机拉低总线,并在15微秒内将总线拉高。
主机保持总线高电平至少60微秒。
在此期间,从机在总线上采样电平状态。如果采样到高电平,则写入逻辑1。
三、读时隙
读时隙用于主机从从机读取数据,同样包括读0和读1两种时隙(但时序要求相似,主要区别在于从机的响应)。其时序要求如下:
1、主机发起读时隙:
主机拉低总线至少1微秒,然后释放总线。
主机释放总线后,由上拉电阻将总线拉至高电平。
2、从机响应:
从机在检测到总线的上升沿后,开始发送数据。
如果从机要发送逻辑1,则保持总线为高电平。
如果从机要发送逻辑0,则拉低总线,并在15~60微秒的窗口内保持低电平。
从机在发送完数据后,释放总线,由上拉电阻将总线拉至高电平状态。
3、主机采样数据:
主机在释放总线后,必须在15微秒内采样总线电平状态,以获取从机发送的数据。
DS18B20硬件电路原理图分析
DS18B20硬件电路原理图分析:
从上图可观察出DS18B20的1脚接地、3脚接入VCC,形成电势差可使DS18B20工作。2脚DQ数据脚连接单片机的P3.7IO口上,本来为了让单总线默认为高电平,通常会在单总线上外接上拉电阻。因为单片机的P3.7脚外接了上拉电阻,所以在DS18B20数据线上可以省去上拉电阻。
DS18B20软件编程设计
本章我们实现采集DS18B20温度传感器数据,并在数码管显示采集到的温度的数据。
实现步骤如下:
第一步:实现单总线初始化时序
代码示例:
void DS18B20_RESET(void) //单总线初始化时序复位信号发送函数
{DS18B20_DQ=0; //主机拉低总线,以产生复位信号Delay_10us(70); //拉低延时700微秒DS18B20_DQ=1; //释放总线,由上拉电阻拉至高电平Delay_10us(2); //保持15微秒到60微秒区间
}u8 DS18B20_ACK(void) //单总线初始化时序应答信号接收函数
{u8 temp_time=0; //计数时间变量while(DS18B20_DQ && temp_time<20 ) //等待DS18B20发送应答信号为低电平,等待时间为200微秒{temp_time++;Delay_10us(1); //每次等待10微秒} if(temp_time>=20) //没有发送应答信号,返回1{return 1;}else temp_time=0; //发送应答信号,计数时间变量清零while((!DS18B20_DQ) && temp_time<20 ) //等待上拉电阻将DQ上拉为高电平,等待时间为200微秒{temp_time++;Delay_10us(1); //每次等待10微秒} if(temp_time>=20) //没有上拉,返回1{return 1;}return 0; //应答信号接收完成返回值为0
}u8 DS18B20_init(void) //DS18B20单总线初始化时序函数
{DS18B20_RESET(); //复位信号发送return DS18B20_ACK(); //返回值为1初始化失败,返回值为0初始化成功
}
代码讲解:
将初始化时序分成两个步骤实现:第一个步骤是单片机发送复位信号,第二个步骤是单片机检测DS18B20发送应答信号;
单片机发送复位信号:首先主机拉低总线,并延时480微秒~960微秒,以产生复位信号。在由上拉电阻拉至高电平15微秒~60微秒,释放总线。将步骤封装成初始化时序复位信号发送函数
单片机检测DS18B20发送应答信号:首先等到DS18B20发送应答信号拉低总线,等待时间为200微秒。没有检测到返回值为1,表明未发送应答信号。如发送应答信号,在等待上拉电阻将总线上拉释放,等待时间为200微秒。没检测到,返回值为1,表面释放总线失败。如检测到返回值为0;表面应答信号检测成功并且总线释放。
将两函数合并成单总线初始化时序函数;
第二步:实现单片机写入单总线一字节数据函数
代码示例:
void DS18B20_wriat_byte(u8 dat) //主机发送一字节数据给DS18B20函数
{u8 i=0,temp=0;for(i=0;i<8;i++){temp=dat&0x01; //将数据的最低位赋值给tempdat>>=1; //数据发送完成,准备发送一下位数据 if(temp){DS18B20_DQ=0; //主机拉低总线,并在15微秒内将总线拉高_nop_();_nop_(); //延时低电平2微秒DS18B20_DQ=1; //主机拉高总线发送数据1Delay_10us(6); //延时60微秒 }else {DS18B20_DQ=0; //主机拉低总线,发送数据0Delay_10us(6); //延时60微秒DS18B20_DQ=1; //上拉电阻拉高_nop_();_nop_(); //延时2微秒}}
}
代码讲解:
单总线发送一字节数据是一位一位串行发送,发送方向:低位→高位。判断每位是发送1还是发送0;
发送1:主机拉低总线,延迟2微秒。在15微秒内将总线拉高。主机保持总线高电平至少60微秒发送数据1,延时60微秒;
发送0:主机拉低总线至少60微秒发送数据0,延时60微秒,后由上拉电阻将总线拉高至少1微秒,延时2微秒;
循环8次判断,单片机发送1字节函数完成;
第三步:实现单片机读取单总线发送一位和一字节数据函数
代码示例:
u8 DS18B20_read_bit(void) //主机读取1位数据函数
{u8 dat=0;DS18B20_DQ=0; //主机拉低总线_nop_();_nop_(); //延时2微秒DS18B20_DQ=1; //释放总线_nop_();_nop_(); //延时2微秒if(DS18B20_DQ) dat=1; //读取到为高电平else dat=0; //读取到为低电平Delay_10us(5); //延时50微秒return dat;
}u8 DS18B20_read_byte(void) //主机读取一字节数据函数
{u8 i=0,temp=0,dat=0;for(i=0;i<8;i++) //循环8次读取{temp=DS18B20_read_bit();dat>>=1;dat|=(temp<<7); //dat=dat|(temp<<7)}return dat;
}
代码讲解:
单片机读取DS18B20发送1位数据:主机拉低总线保持最少1微秒,延时2微秒。主机释放总线拉高保持最少1微秒,延时2微秒;开始采样DS18B20发送的数据判断是1还是0,判断时间最少45微秒,延时时间50微秒,并返回数据值;
单片机读取DS15B20发送1字节数据:循环八次读取一位数据;放入在缓存区变量中,并返回;
第四步:读取DS18B20的2字节温度数据函数
代码示例:
float DS18B20_read_temp(void) //读取DS18B20字节温度函数
{u8 datl=0;u8 dath=0;u16 dat=0;float temp;DS18B20_init(); //第一步:初始化DS18B20_wriat_byte(0xcc); //第二步:发送SKIP ROM命令(0xcc)DS18B20_wriat_byte(0x44); //第三步:发开始转换命令(0x44)Delay_ms(1); //第四步:延时1毫秒DS18B20_init(); //第五步:初始化DS18B20_wriat_byte(0xcc); //第六步:发送SKIP ROM命令(0xcc)DS18B20_wriat_byte(0xBE); //第七步:发读存储器命令(0xBE)datl=DS18B20_read_byte(); //第八步:连续读取两个字节数据dath=DS18B20_read_byte(); dat=(dath<<8) + datl; if((dat&0xf800) == 0xf800) //第九步:转换温度{dat=(~dat)+1;temp=dat*(-0.0625);}else {temp=dat*0.0625;}return temp;
}
代码讲解:按照DS18B20典型温度读取过程步骤实现,实现完成后判断数据为负温度还是整温度,实现温度公式转换并将温度数据返回。
第六步:主函数实现功能整合
代码示例:
int main()
{u8 i=0;int temp=0;u8 temp_buff[5];DS18B20_init();while(1){ i++;if(i%200 == 0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间{temp=DS18B20_read_temp()*10;}if(temp<0) //负温度{temp=-temp;temp_buff[0]=0x40; //显示负号}else //不显示符号{temp_buff[0]=0x00;}temp_buff[1]=Display[temp/1000];temp_buff[2]=Display[temp/100%10];temp_buff[3]=Display[temp/10%10]|0x80; temp_buff[4]=Display[temp%10];DIGITALTUBE_EEPROM_Display2(temp_buff,4);}
}
制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!