18B20概述
-
18B20是一种常用的数字温度传感器,广泛应用于环境监测、工业控制、家居自动化和设备温度监控等领域。
-
18B20引脚:8B20采用1-wire总线进行通信,数据的输入输出仅靠一个DQ引脚完成。
-
工作原理:
1-Wire通信协议
- 1-Wire协议是一种半双工、串行通信协议,主要用于与各种低成本传感器和存储设备进行数据交换。同I2C协议类似,1-Wire也采用主从架构,一个主设备可以连接多个从设备。
-
由于1-wire总线也要求各设备以开漏(Open-Drain)模式接入,因此DQ信号线也要使用上拉电阻。(只有低电平和高阻态两种状态)。
-
另外,在1-Wire总线中,每个从设备都有一个唯一的64位地址,用于设备识别和通信,这64位地址是由制造商在生产设备时烧录进去的,不可更改。
初始化
- 1-Wire规定,每次通信主设备都要先发送一个复位脉冲,从设备接收到该脉冲后,会进行复位(例如:从低功耗状态恢复到正常通信状态),然后回复一个存在脉冲,主设备可根据该存在脉冲获知从设备的健康状态。
写操作
读操作
18B20通信
18B20规定,主设备与其的每次通信,都要遵循以下流程:
- 初始化:主设备发送复位脉冲,从设备回复存在脉冲。
- 发送ROM命令:
- 每个18B20都有一个唯一个的64位序列号,该序列号存储于其内部的一个64位的ROM中。
- 搜索ROM命令[0xF0]:识别和列出所有连接在总线上的18B20设备。
- 读取ROM命令[0x33]:在单设备连接时,主机可以使用此命令直接读取设备的ROM代码。
- 匹配ROM命令[0x55]:该命令后边会跟随一个特定的64位ROM代码,用以选择总线上特定的设备进行通信。
- 跳过ROM命令[0xCC]:在单设备环境中,跳过ROM步骤,直接与设备通信。
- 发送功能命令:功能命令用于控制18B20的具体操作,向前文提到的测温命令、读取温度命令等均属于功能命令。
- 温度转换[44h]:该命令的作用是启动温度测量并将温度数据转换为数字格式。接收到该命令后,18B20会读取其内部的温度传感元件,将测量到的温度值转换为数字信号,并存储在内部的暂存器中,以便后续读取。完成上述操作后,18B20会自动恢复到低功耗状态。
- 读取暂存寄存器[BFh]:该命令用于读取18B20暂存器中存储的值。该命令会返回暂存器中的全部数据,共9个字节,温度值保存在前两个字节,所以一般情况下,只需接收前两个字节即可。
- 18B20测温的精度是可选的,有12位(bit0-bit11)、11(bit1-bit11)位、10位(bit2-bit11)和9位(bit3-bit11)可选,默认12位
- 上述两个字节中保存的是温度值的补码。
- 上述命令或者数据的读写操作均为低位优先。
原理图:
代码实现
// Dri_1Wire.h
#ifndef __DRI_1WIRE_H__
#define __DRI_1WIRE_H__
#include "Com_Util.h"
/**
* @brief 初始化
*
* @return bit
*/
bit Dri_1Wire_Init();
/**
* @brief 写入函数
*
* @param byte 写入字节
*/
void Dri_1Wire_WriteByte(u8 byte);
/**
* @brief 读取字节函数
*
* @return u8 返回读取到的字节数据
*/
u8 Dri_1Wire_ReadByte();
#endif /* __DRI_1WIRE_H__ */
// Dri_1Wire.c
#include "Dri_1Wire.h"
#include <STC89C5xRC.H>
#define DQ P44
bit Dri_1Wire_Init()
{
bit result;
DQ = 0;
Com_Util_Delay480us();
DQ = 1;
Com_Util_Delay60us();
result = ~DQ;
Com_Util_Delay420us();
return result;
}
void Dri_1Wire_WriteByte(u8 byte)
{
u8 i;
for (i = 0; i < 8; i++) {
DQ = 0;
DQ = byte & 0x01;
byte >>= 1;
Com_Util_Delay60us();
DQ = 1;
}
}
u8 Dri_1Wire_ReadByte()
{
u8 byte = 0x00;
u8 i;
for (i = 0; i < 8; i++) {
DQ = 0;
DQ = 1;
Com_Util_Delay10us();
byte >>= 1;
if (DQ == 1) {
byte |= 0x80;
}
Com_Util_Delay50us();
}
return byte;
}
// DS18B20.h
#ifndef __INT_DS18B20_H__
#define __INT_DS18B20_H__
/**
* @brief 读取温度
*
* @return char 返回当前温度值
*/
char Int_DS18B20_GetTemperature();
#endif /* __INT_DS18B20_H__ */
// DS18B20.C
#include "Int_DS18B20.h"
#include "Dri_1Wire.h"
char Int_DS18B20_GetTemperature()
{
u8 ls_byte;
u8 ms_byte;
Dri_1Wire_Init();
// 跳过ROM命令
Dri_1Wire_WriteByte(0xCC);
// 温度转换
Dri_1Wire_WriteByte(0x44);
Dri_1Wire_Init();
Dri_1Wire_WriteByte(0xCC);
// 读取暂存寄存器
Dri_1Wire_WriteByte(0xBE);
ls_byte = Dri_1Wire_ReadByte();
ms_byte = Dri_1Wire_ReadByte();
return (ls_byte >> 4) | (ms_byte << 4);
}
// main.c
#include "Int_OLED.h"
#include "Int_DS18B20.h"
#include "Com_Util.h"
void main()
{
Int_OLED_Init();
Int_OLED_Clear();
while (1) {
Int_OLED_ShowNum(0, 0, Int_DS18B20_GetTemperature());
Com_Util_Delay1ms(500);
}
}
DS1302时钟
DS1302是一个低功耗、实时时钟(RTC)芯片:
DS1302概述
- 引脚功能:
- 工作原理
通讯协议
读操作
写操作
常用寄存器:
注意:DS1302内部有一个写保护寄存器,在向DS1302写入数据前需要先关闭写保护,写完再开启写保护。
需求:将时间信息和温度信息实时地显示在OLED上。
原理图: