目录
一、器件介绍
DS18B20是一款高精度单总线温度测量芯片,温度测量范围-55℃到+125℃。相比于了LM35和PT100等温度传感器使用更方便,硬件更简单。用户可自主选择电源供电模式和寄生供电模式。单总线接口允许多个设备挂在同一总线,该特性使得DS18B20非常便于不是分布型温度采集系统。
每一个DS18B20器件都有一个唯一的64位编码。在一些要求具有唯一设备ID的应用中,我们可以采用该编码作为设备的唯一ID用于对相同的设备进行区别。
DS18B20框架图
PS:特别注意图中的4.7k电阻,硬件中一定要将DQ引脚通过4.7k电阻上拉到VDD。
DS18B20两种供电模式(注意4.7k上拉电阻)
二、主要指令介绍
DS18B20的指令分为ROM操作指令和功能指令,具体指令见DS18B20数据手册,在此主要对本文涉及到的指令进行见到介绍。
2.1、ROM操作指令
Read ROM[33h]
这个指令允许总线主机读到 DS18B20 的 64 位 ROM 编码。只有在总线上存在单只 DS18B20 的时候才能使用这个指令。如果总线上有不止一个从机,当所有从机试图同时响应时就会发生数据冲突。
Skip ROM[CCh]
主机通过该指令同时寻址总线上所有设备而无需发送任何 ROM 编码。例如,主机可以 令总线上所有 DS18B20 同时执行温度转换,只需 发布 Skip ROM 指令跟随一个 Convert T [44h]指令。需要注意Read Scratchpad [BEh] 指令只能 在单一从设备挂在总线上时才能跟随 Skip ROM 指令。这种情况下,通过允许主机无需发送 64 位设备ROM 编码而读取从设备,可以节约时间。如果总线上有超过一个从设备,一个 Skip ROM指令跟随一个 Read Scratchpad 指令会导致数据冲突,因为多个设备会试图同时传送数据。
2.2、功能指令
CONVERT T[44h]
该指令启动一次温度转换,转换之后,采集的热数据存储在暂存器中的 前2 字节中,然后DS18B20 返回低功耗空闲状态。如果设备使用于寄生电源模式下,本指令发布后最多10us之内,主机必须在整个温度转换期间(tCONV)启动单总线的强上拉,如给 DS18B20 供电章节所述。如果 DS18B20 由外部电源供电,主机可以在 Convert T 指令后发布读时隙,然后DS18B20会回复0或者1表示温度转换正在进行中或者已完成。在寄生电源模式这个通知技术不能应用,因为总线在整个转换过程中被强上拉到高电平。
READ SCRATCHPAD [BEh]
该指令允许主机读取暂存器中的内容。数据传输始于字节 0 的最低位并延续遍历暂存器直到第9个字节(字节 8-循环冗余验证码)被读取。如果只需要暂存器中的部分数据,主机可以随时发布一个复位信号终止读取。
三、器件操作时序
访问DS18B20的传输序列如下:
步骤1:初始化
步骤2:ROM指令(跟随任意必须的数据交换)
步骤3:功能指令(跟随任意必须的数据交换)
PS:每次访问DS18B20都必须确保这个顺序,任何步骤缺失或者顺序不对都会导致器件不响应。四、程序介绍
3.1、器件初始化
通过单总线的所有执行都是从一个初始化序列开始,初始化序列包括一个由总线控制器发出的复位脉冲和跟随其后由从机发出的存在脉冲。 存在脉冲让总线主机知道从设备在总线上且已经准备好运行。
初始化时序
器件初始化代码:// Sends reset pulse
unsigned char ds18b20_reset(void){
unsigned char presence;
gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
noInterrupts();
gpio_set_level(DS_GPIO, 0);
ets_delay_us(480);
gpio_set_level(DS_GPIO, 1);
gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);
ets_delay_us(70);
presence = (gpio_get_level(DS_GPIO) == 0);
ets_delay_us(410);
interrupts();
return presence;
}
3.2、读取器件ID编码
正如前面所提到的,读取器件ID指令是33h。
64位编码结构
话不多说,直接上程序。
// Returns serial id from sensor
/*
8bit CRC 48bit serial id 8bit product number
MSB LSB MSB LSB MSB LSB
*/
uint64_t ds18b20_get_id(void){
if(init==1){
unsigned char check;
uint64_t ser_id=0;
uint8_t serial_id[8];
check=ds18b20_RST_PULSE();//DS18B20初始化
if(check==1)
{
ds18b20_send_byte(0x33);//Read ROM指令
serial_id[0]=ds18b20_read_byte();
serial_id[1]=ds18b20_read_byte();
serial_id[2]=ds18b20_read_byte();
serial_id[3]=ds18b20_read_byte();
serial_id[4]=ds18b20_read_byte();
serial_id[5]=ds18b20_read_byte();
serial_id[6]=ds18b20_read_byte();
serial_id[7]=ds18b20_read_byte();
//转换为64位
ser_id=(serial_id[7]*256)+serial_id[6];
ser_id=(ser_id*256)+serial_id[5];
ser_id=(ser_id*256)+serial_id[4];
ser_id=(ser_id*256)+serial_id[3];
ser_id=(ser_id*256)+serial_id[2];
ser_id=(ser_id*256)+serial_id[1];
ser_id=(ser_id*256)+serial_id[0];
return ser_id;
}
else{return 0;}
}
else{return 0;}
}
3.3、读取温度值
读取温度值之前我们先看一下DS18B20存储器的结构
DS18B20存储映射
由图可知我们想要获取温度只需要对暂存器的第一和第二字节进行读取就可以了。
// Returns temperature from sensor
float ds18b20_get_temp(void) {
if(init==1){
unsigned char check;
char temp1=0, temp2=0;
check=ds18b20_RST_PULSE();//DS18B20初始化
if(check==1)
{
ds18b20_send_byte(0xCC);//ROM指令 --总线寻址
ds18b20_send_byte(0x44);//DS18B20功能指令 --温度转换
vTaskDelay(750 / portTICK_RATE_MS);
check=ds18b20_RST_PULSE();
ds18b20_send_byte(0xCC);//ROM指令 --总线寻址
ds18b20_send_byte(0xBE);//DS18B20功能指令 --读取暂存器
temp1=ds18b20_read_byte();//暂存器第一字节
temp2=ds18b20_read_byte();//暂存器第二字节
check=ds18b20_RST_PULSE();//后边数据没用直接初始化(复位)
float temp=0;
temp=(float)(temp1+(temp2*256))/16;
return temp;
}
else{return 0;}
}
else{return 0;}
}
主程序
#define DS18B20_PIN GPIO_NUM_4
static const char *TEM = "DS18B20_Demo";
static void DS18B20_Task(void *pvParameters) {
uint8_t ret = 0;
float temp = 0;
uint64_t ser_id;
ret = ds18b20_init(DS18B20_PIN);
ESP_LOGI(TEM,"Init_DS18B20: %d\r\n",ret);
while (1) {
//获取DS18B20ID号
ser_id = ds18b20_get_id();
ESP_LOGI(TEM,"serial_id=%llx\n",ser_id);//显示器件ID
// printf("serial_id=%llx\r\n",ser_id);//输出64位16进制DS18B20器件ID
//采集温度值
temp = ds18b20_get_temp();
ESP_LOGI(TEM,"temperature=%f\n",temp);//显示温度
// printf("temperature=%f\r\n",temp);//显示温度
vTaskDelay(100 / portTICK_RATE_MS);
}
}
void app_main() {
ESP_ERROR_CHECK(nvs_flash_init());
xTaskCreate(&DS18B20_Task, //pvTaskCode
"DS18B20_Task",//pcName
2048,//usStackDepth
NULL,//pvParameters
4,//uxPriority
NULL//pxCreatedTask
);
}
五、运行结果
I (6973) DS18B20_Demo: temperature=19.187500
I (7080) DS18B20_Demo: serial_id=e7062010d7450e28
附:程序源码https://download.csdn.net/download/Gary_Dengxh/35919477