一、DS18B20简介
DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
- 测温范围: -55°C 到+125°C
- 通信接口: 1-Wire (单 总线)
- 其它特征:可形成总线结构、内置温度报警功能、可寄生供电
DS18B20器件框图
图中:
1. 64-BT ROM:作为器件地址。用于总线通信的寻址。每个DS18B02都有一个ID号,用来寻址,相当于一个大门,当只有一个单总线设备时,可以选择跳过这个大门;
2. SCRATHPAD,属于RAM, (暂存器)公用于总线的数据交互
3. EEPROM用于保存温度触发阚值和配置参数
4. MEMORY CONTROL LOGIC 内存控制逻辑,相当于管家,操作底下的暂存器;
5. TEMPERATURE SENSOR 是温度传感器,直接将数据处理好放在暂存器中;
6. 最后两个都是设置阈值的,用于报警;
7. 第四个是配置寄存器,设置分辨率,默认最高分辨率0.0625,可以设置为0.5的分辨率,使得运算的更快一些;
8. 第五个是校验寄存器;
下图为DS18B20内部存储器结构
无法通过写数据直接给EEPROM写数据,只能写入到暂存器中,通过发送指令,再让暂存器中的数据复制到EEPROM。
二、单总线介绍
- 单总线(1-Wire BUS) 是由Dallas公司开发的-种通用数据总线一根通信线: DQ
- 异步、半双工
- 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
设备的DQ均要配置成开漏输出模式
DQ添加一个上拉电阻,阻值一般为4.7KQ左右
若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
1. 初始化
主机将总线拉低至少480us,然后释放总线,等待15~60us后, 存在的从机会拉低总线60~ 240us以响应主机,之后从机将释放总线
2.发送一位数据
主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~ 15us, 然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
3.接收一位数据
主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
4. 发送一个字节
5.接收一个字节
6.DS18B20操作流程
- 初始化:从机复位,主机判断从机是否响应
- ROM操作:ROM指令+本指令需要的读写操作
- 功能操作:功能指令+本指令需要的读写操作,相当于RAM操作对暂存器的操作
- MATCH ROM[55h] 匹配ROM,相当于设备的地址
- SKIP ROM[CCh] 跳过ROM,只有一个设备在总线上,因此可以直接跳过ROM(大门),进行通信
- CONVERT T[44h] 温度传递指令,发送该指令,DS18B20中的温度传感器就将数据传送到暂存器当中
- WRITE SCRATCHPAD[4Eh] 写暂存器指令,该指令是将EEPROM中的数据写到暂存器当中
- READ SCRATCHPAD[BEh] 读暂存器指令,该指令是将暂存器当中的数据都读出来,但实际操作时我们只需要前两个温度的字节
- COPY SCRATCHPAD[48h] 复制暂存器,将ROM中的数据写入到EEPROM中,如果想要实现掉电不丢失,就先把数据写入到ROM中,再通过调用该指令,写入到EEPROM中
- RECALL E2[B8h] 覆盖暂存器指令,该指令是将EEPROM中的数据覆盖掉暂存器中的数据
7.DS18B20数据帧
8.DS18B20数据存储格式
其中低四位表示小数,高五位表示符号,中间是整数部分
9.温度操作
/**
* @brief DS18B20开始温度变换
* @param 无
* @retval 无
*/
void ds18b20_convert_temp(void)
{
one_wire_init();
one_wire_send_byte(DS18B20_SKIP_ROM);
one_wire_send_yte(DS18B20_CONVERT_T);
}
/**
* @brief DS18B20读取温度
* @param 无
* @retval 温度数值
*/
float ds18b20_read_temp(void)
{
unsigned char temp_lsb, temp_msb;
int temp_i;
float temp_f;
one_wire_init();
one_wire_send_byte(DS18B20_SKIP_ROM);
one_wire_send_byte(DS18B20_READ_SCRATCHPAD);
temp_lsb = one_wire_receive_byte();
temp_msb = one_wire_receive_byte();
temp_i = (temp_msb << 8) | temp_lsb;
temp_f = temp_i / 16.0; //因为低四位表示的是小数部分,因此 temp_i 直接读出来并不是实际的值,
//要把小数部分摘出来,除以16相当于把低四位给滤出来
return temp_f;
}