本文主要是介绍8、单总线与DB18B20实现温度的测量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1、单总线(1-Wire)通信的基本概念
- 2、DS18B20温度传感器的介绍
- 1)ROM操作指令
- 2)功能性指令
- 3、DS18B20 的数据格式及转换
- 4、 DS18B20 的时序图
- 1)主机的两个写入操作
- 2)从机的两个应答操作(主机读0读1)
- 5、 DS18B20 的操作流程
- 6、参考代码
1、单总线(1-Wire)通信的基本概念
在串行通信系统中通常具备:
时钟信号线,数据信号线,控制信号线,设备电源线
- UART:VCC GND TXD(串口的发送引脚) RXD(串口的接收引脚)
- USART:VCC GND TXD RXD SCK(时钟信号)
- SPI:VCC GND CS(片选引脚) MOSI MISO SCK
- I2C:VCC GND SDA(串行数据线) SCK(串行时钟线)
优缺点:
- 总线的驱动能力较差,超过一定数量会不稳定
- 距离不长,1-Wire总线更适合中短距离低速
- 由于硬件集成一线比较简单,软件的复杂度上升
2、DS18B20温度传感器的介绍
- 1、外形
- 2、供电方式
寄生方式供电
外部供电方式(需要考虑压降)
- 3、内部电路
内部含有单元电源单元,ROM单元,存储器逻辑控制单元,温度转换单元,高速暂存器单元等
DS18B20只能去读而不能写,具备高温报警,-10°-40°
1)ROM操作指令
DS18B20设备中有关ROM操作的指令一共有5个,如下所示:
(读取和跳过用得比较多,其他的用得比较少)
2)功能性指令
除了ROM指令在之外,还有功能性的指令
(主要用的是温度转换和读暂存器)
3、DS18B20 的数据格式及转换
- 转换分配率问题
在配置寄存器中的位 6 和位 5 两个位来控制
- 温度值的存放问题
在高字节中的高 5 位是符号位,图中用 S 表示。如果温度值是正数,则 S 位均为 0,若为负数,则 S 位均为 1
- 问题1:符号位为什么要5个?
没有必要占用这么多位,其可测量的温度范围比较窄,为了数据好处理,所以用了5个符号位。
- 问题2:抛开符号位,其他的全部为只有11位?
将高位的5为结合成了一个符号位,也就是12位的分辨率指的是S位+其余的11位。
位0-位3部分是小数部分,位4-位19是整数部分,位11-位15是符号位。对于12位的转换分辨率,温度传感器的所以位都是有效的;对于11为的转换分辨率,位0是无效的;对于10为的分辨率,位0和位1是无效的;对于9位的分辨率,位2,位1,位0是无效的。
- 问题3:负数温度如何处理?
负数温度按照补码来操作,所以如果是-55°需要存储,其正确的答案不是0b1111101101110000也就是0xFB70,而是按照补码来显示为0b1111110010010000也就是0xFC90。(补码=反码+1,反码=源码取反)
- 问题4:温度如何转换为正确的摄氏温度?
实际温度 = 份数 * 最小的分辨率
温度数值转换格式的例子:
高温阈值和低温阈值的设置(少用)
当实际采样测量的温度值超过高温限值或者是低于低温阈值的时候,这时候DS18B20设备会发出报警信号。
4、 DS18B20 的时序图
DS18B20 设备采用了严格的 1-Wire 单总线通信协议来保证数据的完整性和有效性。第一是发送初始化时序,第二是发送 ROM 命令,第三是发送功能命令。
- 问题:如何写命令给从机,也就是如何让从机知道我们是写 1 还是写 0,才能将一个 1byte的数据发送过去?
对于一个字节的数据,有高低位之分,而数据的发送要先发低位,再发高位。注意好写 0 和写 1 的时间隙。在正确的时间隙中操作就是主机与从机之间正确通信的保障。
1)主机的两个写入操作
- 操作1:写1的时间隙
- 操作2:写0的时间隙
2)从机的两个应答操作(主机读0读1)
注意要注意好时间,主机的采样一定要是15微秒以内
5、 DS18B20 的操作流程
- 复位
首先我们必须对 ds18b20 芯片进行复位,复位就是由控制器(单片机)给 ds18b20 单
总线至少 480uS 的低电平信号。当 18B20 接到此复位信号后则会在 15~60uS 后回发一个芯
片的存在脉冲。 - 存在脉冲
在复位电平结束之后,控制器应该将数据单总线拉高,以便于在 15~60uS 后接收存在
脉冲,存在脉冲为一个 60~240uS 的低电平信号。至此,通信双方已经达成了基本的协议,
接下来将会是控制器与 18B20 间的数据通信。如果复位低电平的时间不足或是单总线的电
路断路都不会接到存在脉冲,在设计时要注意意外情况的处理。 - 控制器发送 ROM 指令
双方打完了招呼之后最要将进行交流了,ROM 指令共有 5 条,每一个工作周期只能发一
条,ROM 指令分别是读 ROM 数据、指定匹配芯片、跳跃 ROM、芯片搜索、报警芯片搜索。ROM
指令为 8 位长度,功能是对片内的 64 位光刻 ROM 进行操作。其主要目的是为了分辨一条总
线上挂接的多个器件并作处理。诚然,单总线上可以同时挂接多个器件,并通过每个器件
上所独有的 ID 号来区别,一般只挂接单个 18B20 芯片时可以跳过 ROM 指令(注意:此处指
的跳过 ROM 指令并非不发送 ROM 指令,而是用特有的一条“跳过指令”)。ROM 指令在下
文有详细的介绍。 - 控制器发送存储器操作指令
在 ROM 指令发送给 18B20 之后,紧接着(不间断)就是发送存储器操作指令了。操作
指令同样为 8 位,共 6 条,存储器操作指令分别是写 RAM 数据、读 RAM 数据、将 RAM 数据
复制到 EEPROM、温度转换、将 EEPROM 中的报警值复制到 RAM、工作方式切换。存储器操作
指令的功能是命令 18B20 作什么样的工作,是芯片控制的关键。 - 执行或数据读写
一个存储器操作指令结束后则将进行指令执行或数据的读写,这个操作要视存储器操
作指令而定。如执行温度转换指令则控制器(单片机)必须等待 18B20 执行其指令,一般
转换时间为 500uS。如执行数据读写指令则需要严格遵循 18B20 的读写时序来操作。
需要注意:
换存储器操作指令、等待 500uS 温度转换时间。紧接着执行第二个周期为复位、跳过
ROM 指令、执行读 RAM 的存储器操作指令、读数据(最多为 9 个字节,中途可停止,只读
简单温度值则读前 2 个字节即可)。其它的操作流程也大同小异,在此不多介绍。
6、参考代码
/****************************************************************/
//设备初始化时序产生函数DS18B20_reset(),无形参和返回值
/****************************************************************/
void DS18B20_reset(void)
{u8 x;DS18B20_DQ_DDR(1);DS18B20_DQ=1;delay(1700);DS18B20_DQ=0;delay(1700);DS18B20_DQ=1;delay(65);DS18B20_DQ_DDR(0);delay(65);x=PI_IDR_IDR4;printf("|[1].开始检测DS18B20......\r\n");while(x);printf("|[2].DS18B20检测成功\r\n");delay(1150);//控制器等待至少480us
}/****************************************************************/
//设备DQ引脚方向性配置函数DS18B20_DQ_DDR(),有形参ddr无返回值
/****************************************************************/
void DS18B20_DQ_DDR(u8 ddr)
{if(ddr==1) //配置为输出方式{PI_DDR_DDR4=1;PI_CR1_C14=1;PI_CR2_C24=0;}else //配置为输入方式{PI_DDR_DDR4=0;PI_CR1_C14=1;PI_CR2_C24=0;}
}/****************************************************************/
//设备初始化函数DS18B20_init(),无形参和返回值
/****************************************************************/
void DS18B20_init(void)
{DS18B20_reset();delay(1000);DS18B20_Wbyte(0xCC);//写ROM指令(跳过ROM)DS18B20_Wbyte(0x44);//写功能指令(温度转换)printf("|[3].启用温度转换\r\n");
}/****************************************************************/
//设备写一个字节函数DS18B20_Wbyte(),有形参xbyte无返回值
/****************************************************************/
void DS18B20_Wbyte(u8 xbyte)
{u8 i,x=0;DS18B20_DQ_DDR(1);for(i=0;i<8;i++) //8次循环实现逐位写入{x=xbyte & 0x01; //从最低位取值到最高位if(x) //写“1”{DS18B20_DQ=0;delay(30);DS18B20_DQ=1;delay(100);DS18B20_DQ=1;}else //写“0”{DS18B20_DQ=0;delay(30);DS18B20_DQ=0;delay(100);DS18B20_DQ=1;}xbyte=xbyte>>1; //右移一位实现逐位移出}
}/****************************************************************/
//设备读字节函数DS18B20_Rbyte(),无形参有返回值rbyte
/****************************************************************/
u8 DS18B20_Rbyte(void)
{u8 rbyte=0,i=0,tempbit=0;for(i=0;i<8;i++) //8次循环实现逐位拼合{tempbit=DS18B20_Rbit(); //读取单个位rbyte=rbyte>>1; //右移实现将高低位排列rbyte=rbyte|tempbit; //或运算移入数据}return rbyte;
}/****************************************************************/
//设备读取单个位函数DS18B20_Rbit(),无形参有返回值rbit
/****************************************************************/
u8 DS18B20_Rbit(void)
{u8 rbit=0,x=0;DS18B20_DQ_DDR(1);DS18B20_DQ=0;delay(30);DS18B20_DQ=1;DS18B20_DQ_DDR(0);delay(20);x=PI_IDR_IDR4;if(x)rbit=0x80;delay(150);return rbit;
}/****************************************************************/
//设备温度获取和转换函数DS18B20_get_Temperature(),无形参和返回值
/****************************************************************/
void DS18B20_get_Temperature(void)
{u8 msb_byte=0,lsb_byte=0; //msb是温度值高位,lsb是温度值低位DS18B20_reset(); //初始化时序delay(1000); //等待初始化稳定DS18B20_Wbyte(0xCC); //写ROM指令(跳过ROM)DS18B20_Wbyte(0xBE); //写功能指令(读暂存器)delay(1000); //等待配置稳定printf("|[4].开始温度读取操作\r\n");lsb_byte=DS18B20_Rbyte(); //读取第一个低位数据字节msb_byte=DS18B20_Rbyte(); //读取第二个高位数据字节Tem_u16=msb_byte; Tem_u16=Tem_u16<<8; Tem_u16=Tem_u16|lsb_byte; if(Tem_u16<=0x07FF) //温度值正负判断{flag=1; //温度值为正(最高能测到125摄氏度)Tem_f=Tem_u16*0.0625; //乘以0.0625最小分辨值得到12位温度实际值Tem_u16=(u16)(Tem_f+0.5);//4舍5入得到温度整数值}else{flag=0; //温度值为负(最低能测到-55摄氏度)Tem_u16=~(Tem_u16-1); //此时数据是补码形式//采用“补码-1”再按位取反的方法得到对应原码Tem_f=Tem_u16*0.0625;//乘以0.0625最小分辨值得到12位温度实际值Tem_u16=(u16)(Tem_f+0.5);//4舍5入得到温度整数值}
}
曾经做过一个单片机课设,实现DB18B20获取温度然后使用LCD1602显示,并且串口打印出来,有兴趣的可以下载代码
这篇关于8、单总线与DB18B20实现温度的测量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!