one-wire的底层驱动比赛会提供
简单理解:
规则:一个复位信号必须大于960us
主设备(单片机)拉低总线超过480us,紧接着释放总线(拉高)也就是来个上升沿,等待15us-60us后,再拉低总线60us-240us发送一个存在脉冲。
简单理解:
规则:读写一个位,要在60us到120us内完成,位与位之间,读写间隔1us
写0再写1:主机将拉低总线,快速释放总线,准备要写入的数据(写0-拉低总线),这些操作要在15us内完成,然后维持至少60us;然后再释放总线1us,继续写1,拉低总线,快速释放总线,准备 要写入的数据(写1-拉高总线),同样这些操作要在15us内完成,再维持60us,然后释放总线超过1us;
读0再读1:主机拉低总线,快速释放总线,这个操作也是要在15us内完成,然后检测总线上的电平被DS18B20拉高了还是低了即可;
可以看到18b20通过P14口挂载在单总线上的!
打开手册可以看到:
根据自己理解翻和译,提取重要信息如下
DS18B20数字温度传感器提供9-Bit到12-Bit的摄氏温度测量精度和一个用户可编程的非易失性且具有过温和低温触发报警的报警功能。
DS18B20采用的1-Wire通信即仅采用一个数据线(以及地)与微控制器进行通信。该传感器的温度检测范围-55℃至+125℃。此外,DS18B20可以直接由数据线供电而不需要外部电源供电。
每片DS18B20都有一个独一无二的64位序列号,这个系列号是烧在内部ROM里面的,所以一个1-Wire总线上可连接多个DS18B20设备。
· 独特的1-Wire总线接口仅需要一个管脚来通信。(DQ引脚)
· 每个设备的内部ROM上都烧写了一个独一无二的64位序列号(板子上面就一个DS18B20 所以 一般直接跳过ROM指令,不进行配对)
· 内部温度采集精度可以由用户自定义为9-Bits至12-Bits(这里一般不去设置)
· 温度转换时间在转换精度为12-Bits时达到最大值750ms(写代码时候要注意)
用来存储数字温度转换结果
温度数据以一个16位标志扩展二进制补码数的形式存储在温度寄存器中(见Figure2)
说人话:用来储存测得的温度的,高5位作为符号位,其余位做数据位
高字节5位为符号标志位(S)温度的正负极性:正数则S=0,负数则S=1。(一般比赛都是正温度)
如果DS18B20被定义为12位的转换精度,温度寄存器中的所有位都将包含有效数据。
若为11位转换精度,则bit 0为未定义的。
若为10位转换精度,则bit 1和bit 0为未定义的。
若为9位转换精度,则bit 2、bit 1和bit 0为未定义的。
下表格为在12位转换精度下温度输出数据与相对应温度之间的关系表。
(比赛用不到了解即可)
用来储存过温和低温的对比参照数值
过温和低温(TH和TL)温度报警寄存器是非易失性的(EEPROM),所以其可以在设备断电的情况下保存。
符号标志位(S)温度的正负极性:正数则S=0,负数则S=1。其余位为数据位
过温和低温(TH和TL)温度报警寄存器是一个8位的寄存器,所以在于其比较时,2个字节的温度寄存器的4位至11位才是有效的数据。
如果温度转换数据小于或等于TL及大于或等于TH,DS18B20内部的报警标志位将会被置位。该标志位在每次温度转换之后都会更新,因此,如报警控制消失,该标志位在温度转换之后将会关闭。
说人话:俩寄存器,用看存放过温和低温阈值温度数据的,也就是TH和TL分别放着对比的过温和低温数值,每次测到的2个字节的温度的第4-12位数据都来跟它比较,进行报警监测
用来配置测温数据的精度的寄存器
说明:9、10、11、12位精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率。
上电默认为:12位转换精度
这里也可以看(Figure2图)每一位对应的权数
**比如:BIT0位2的负4次方,如果数据位可以达到12位精度,分辨率就是1/16 = 0.0625℃
同理 :
11位 精度就是1/8 = 0.125;
10位 精度就是1/4 = 0.25;
9位 精度就是1/2 = 0.5;
用户通过改变R0和R1的值来配置DS18B20的分辨率。上电默认为R0=1及R1=1(12位分辨率)。需要注意的是,转换时间与分辨率之间是有制约关系的。Bit 7和Bit 0至Bit 4作为内部使用而保留使用,不可被写入。
温度分辨率配置以及转化时间表:
访问DS18B20的事件序列如下所示:
第一步:初始化
第二步:ROM命令(紧跟任何数据交换请求)
第三步:DS18B20功能命令(紧跟任何数据交换请求)
每次对DS18B20的访问都必须遵循这样的步骤来进行,如果这些步骤中的任何一个丢失或者没有执行,则DS18B20将不会响应。
除了ROM搜索命令[F0h]和报警搜索命令[ECh]之外。当执行完这些命令之后,主设备必须回到上述步骤中的第一步,也就是必须再次初始化。
搜索ROM[F0h]
读取ROM[33h]
匹配ROM[55h]
跳过ROM[CCh]
警报搜索[ECh]
温度转换[44h]
写入暂存寄存器[4Eh]
读取暂存寄存器[BEh]
拷贝暂存寄存器[48h]
召回EEPROM[B8h]
读取供电模式[B4h]
根据上面的通讯规则(执行命令后必须重新初始化)和指令(ROM和DS18B20指令):
步骤 | 响应的操作 |
---|---|
初始化 | init_ds18b20(); |
跳过ROM指令 | Write_DS18B20(0xcc); |
启动温度转化指令 | Write_DS18B20(0x44); |
初始化 | init_ds18b20(); |
跳过ROM | Write_DS18B20(0xcc); |
读取暂存寄存器指令 | Write_DS18B20(0xbe); |
读温度低字节 | low = Read_DS18B20(); |
读温度高字节 | high = Read_DS18B20(); |
转化温度 | 看所需精度 |
说明:前面提到12位精度,需要750ms,按道理需要加上延时,但经过测试连续读取也是没问题的,因为即使这次温度没转化好,读取到的也是上一次的数值。
当然也可以避免这样操作:在每次读取完就开启温度转化,等下次到来温度肯定转化好了,再读取就没问题了
这里以12位精度为例:
float ReadTemperature(void)
{
float temp = 0.0;
u8 high = 0;
u8 low = 0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
temp = ((high<<8)|low)*0.0625;
return temp;
}
(九)One-Wire总线-DS18B20
----- 如有错误欢迎大家批评指正!!!