IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32——一线协议之DS18B20温度采样 -> 正文阅读

[嵌入式]STM32——一线协议之DS18B20温度采样

一、DS18B20传感器介绍

在这里插入图片描述
每个DS18B20出厂的时候都烧录了一个唯一的64为产品序列号在ROM中。ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个传感器。

1、DS18B20一线协议

所有的单总线器件都要求用严格的信号时序,以保证数据的完整性。DS18B20共有6种信号类型:复位脉冲、应答脉冲、写0/1、读0/1。所有的这些信号除了应答信号。都由主机发出同步信号,并且所有发送的命令和数据都是字节的低位在前(LSB)。

(1)复位脉冲和应答脉冲

单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15 ~ 60us,并进入接收模式(Rx)。接着DS18B20模块拉低总线60 ~ 240us,以产生低电平应答脉冲,若产生了低电平应答脉冲,再延时240us。
在这里插入图片描述

(2)写时序

写时序包括写0时序和写1时序。所有写时序至少要60us,且在两次独立的写时序之间至少要1us的恢复时间,两种写时序均起始于拉低总线。

写0时序:主机输出低电平,延时60us,然后释放总线2us;
写1时序:主机输出低电平,延时2us,然后再释放总线,延时60us。

从机在总线拉低30us后,读取电平。若为低电平,表示写0,若为高电平,表示写1。

在这里插入图片描述

(2)读时序

单总线器件仅在主机发出读时序时,才向主机传数据,主机发出读数据命令后,必须马上产生读时序,一遍从机能够传输数据。所有的读时序至少需要60us,且两次独立的读时序之间至少需要1us的恢复时间。

当总线控制器把数据线从高电平拉到低电平时,读时序开始,数据线必须至少保持1us,然后总线被释放。DS18B20通过拉高或拉低总线来传输“1”或“0”。当逻辑“0”结束后,总线被释放,通过上拉电阻回到上升状态,从DS18B20输出的数据在读时序的下降沿出现后15us内有效6.因此,总线控制器在读时序开始后必须停止把I/O口驱动为低电平,以读取I/O状态。

在这里插入图片描述

2.DS18B20工作流程

先进行温度转换,再进行温度读取;
温度转换:初始化 -> 跳过ROM -> 温度转换
温度读取:初始化 -> 跳过ROM -> 读寄存器 -> 读低八位 -> 读高八位

(1)初始化

单总线上的所有通信都是以初始化序列开始,主机发出初始化信号后等待从设备的应答信号,以确认从设备是否能正常工作。

(2)ROM操作命令

总线主机检测到DS18B20存在之后,便可以发出ROM操作命令,这些命令如下。但是我们一般不关心ROM中的16位产品序列号,通常会发送0xCC跳过ROM的相关操作。
在这里插入图片描述

(3)存储器操作命令

接下来发送相应的高速暂存存储器命令,命令表如下。其中0x44命令通知DS18B20传感器开始进行温度变换(温度采样),而0xBE命令则将开始读出DS18B20的采样值。
在这里插入图片描述

(4)数据处理

DS18B20的高速暂存存储器由9个字节组成。当执行温度转换命令(0x44)后,经转换的温度以二字节补码形式存于高速暂存存储器的前两个字节。
在这里插入图片描述
如果我们只关心温度值的话,则只需读前两个字节就可以了。其中Byte[0]为温度值得低字节,而Byte[1]为温度值得高字节。这16位数据的格式如下:
在这里插入图片描述
其中BIT[3:0]为温度值的小数部分,而BIT[10:4]为温度值的整数部分,BIT[15:11]为符号位,如果为0表示温度为正值,如果为-1则表示温度为负值。

二、DS18B20温度采样实现

1、硬件连接

DS18B20传感器工作电压为3~5.5V,本人将DS18B20的I/O口接到开发板的GPIO管脚PA5上,其实任意一个GPIO管脚都可以的,只需修改一下代码即可(后面说)。

2、代码实现

ds18b20.h

/*
 * ds18b20.h
 *
 *  Created on: 2022年6月28日
 *      Author: 28980
 */

#ifndef INC_DS18B20_H_
#define INC_DS18B20_H_
#include "main.h"

uint8_t DS18B20_Reset(void);//初始化复位及应答

void DS18B20_Writte_Byte(uint8_t byte);//写一个字节

uint8_t DS18B20_Read_Bit(void);//读一个位

uint8_t DS18B20_Read_Byte(void);//读一个字节

uint8_t DS18B20_SampleData(float *temperature);//温度采样

#endif /* INC_DS18B20_H_ */

ds18b20.c

/*
 * ds18b20.c
 *
 *  Created on: 2022年6月28日
 *      Author: 28980
 */


#include "ds18b20.h"

typedef struct w1_gpio_S
{
	GPIO_TypeDef	*group;
	uint16_t		pin;
}w1_gpio_s;

static w1_gpio_s W1DS =
{
	.group = GPIOA,
	.pin = GPIO_PIN_5,
};

#define W1DS_Input()	\
{\
	GPIO_InitTypeDef GPIO_InitStruct = {0};\
 	GPIO_InitStruct.Pin = W1DS.pin;\
 	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;\
 	GPIO_InitStruct.Pull = GPIO_PULLUP;\
 	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;\
 	HAL_GPIO_Init(W1DS.group, &GPIO_InitStruct);\
}


#define W1DS_Output()	\
{\
	GPIO_InitTypeDef GPIO_InitStruct = {0};\
 	GPIO_InitStruct.Pin = W1DS.pin;\
 	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;\
 	GPIO_InitStruct.Pull = GPIO_NOPULL;\
 	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;\
 	HAL_GPIO_Init(W1DS.group, &GPIO_InitStruct);\
}

#define W1DS_Write(x)	HAL_GPIO_WritePin(W1DS.group, W1DS.pin,\
		(x==1)?GPIO_PIN_SET : GPIO_PIN_RESET)

#define W1DQ_Read()	HAL_GPIO_ReadPin(W1DS.group, W1DS.pin)

uint8_t DS18B20_Reset(void)
{
	uint8_t retry = 0;
	uint8_t rv;

	W1DS_Output();
	W1DS_Write(1);
	delay_us(2);

	W1DS_Write(0);
	delay_us(480);

	W1DS_Write(1);
	delay_us(60);

	W1DS_Input();
	while(W1DQ_Read() && retry < 240)
	{
		retry++;
		delay_us(1);
	}

	if(retry >= 240)
	{
		rv = 1;
	}

	delay_us(240);

	W1DS_Output();
	W1DS_Write(1);
	delay_us(240);

	return rv;

}


void DS18B20_Writte_Byte(uint8_t byte)
{
	uint8_t i;

	W1DS_Output();

	for(i = 0; i< 8; i++)
	{
		if(byte & 0x01)
		{
			W1DS_Write(0);
			delay_us(2);

			W1DS_Write(1);
			delay_us(60);
		}
		else
		{
			W1DS_Write(0);
			delay_us(80);

			W1DS_Write(1);
			delay_us(2);
		}

		byte >>= 1;
		delay_us(2);
	}
}


uint8_t DS18B20_Read_Bit(void)
{
	uint8_t rv = 0;

	W1DS_Output();
	W1DS_Write(0);
	delay_us(2);
	W1DS_Write(1);
	delay_us(2);

	W1DS_Input();

	if(W1DQ_Read())
	{
		rv = 1;
	}

	delay_us(60);
	W1DS_Output();
	W1DS_Write(1);

	return rv;
}


uint8_t DS18B20_Read_Byte(void)
{
	uint8_t bit;
	uint8_t i, Byte = 0;

	for(i = 0; i < 8; i++)
	{
		bit = DS18B20_Read_Bit();
		printf("read bit:%d\r\n", bit);
		if(bit)
		{
			Byte |= (1 << i);
		}
		delay_us(2);
	}
	printf("Byte:%d\r\n", Byte);
	return Byte;
}

uint8_t DS18B20_Start_Convet(void)
{
	if(DS18B20_Reset())
	{
		printf("Initialization failed!\r\n");
		return -1;
	}

	DS18B20_Writte_Byte(0xCC);

	DS18B20_Writte_Byte(0x44);

	return 0;
}

uint8_t DS18B20_SampleData(float *temperature)
{
	uint8_t Byte[2];
	uint8_t sign;
	uint16_t temp;

	if(!temperature)
		return -1;

	if(DS18B20_Start_Convet())
	{
			printf("Convet Temperature failed!\r\n");
			return -2;
	}

	if(DS18B20_Reset())
	{
		printf("Initialization failed!\r\n");
		return -3;
	}

	DS18B20_Writte_Byte(0xCC);
	DS18B20_Writte_Byte(0xBE);

	Byte[0] = DS18B20_Read_Byte();
	Byte[1] = DS18B20_Read_Byte();

	printf("Byte[0]:%d\r\n", Byte[0]);
	printf("Byte[1]:%d\r\n", Byte[1]);

	if(Byte[1] > 7)
	{
		sign = 0;
		temp = ~(Byte[1]<<8 | Byte[0]) + 1;
	}
	else
	{
		sign = 1;
		temp = Byte[1]<<8 | Byte[0];
	}


	*temperature = (temp>>4) + (temp & 0x0F) * 0.0625;
	if(!sign)
	{
		*temperature = - *temperature;
	}

	return 0;
}

main.c

while(1)
{
	  if(DS18B20_SampleData(&temperature) < 0)
	  {
		  printf("ERROR:DS18B20 Sample Data failure\r\n");
	  }
	  else
	  {
		  printf("DS18B20 Sample Temperature:%.3f\r\n", temperature);
	  }
	  HAL_Delay(3000);
}

个人总结

在写之前借鉴了一下别人的代码,然后自己看datasheet自己写了代码,出现了不少错,其中有一个隐藏而致命的,让我找了很久,就是写一个字节最后的移位这,byte >>= 1;和读一个字节Byte |= (1 << i);这,少写了一个等号,也算是一个小坑吧,另外在写驱动的时候,一定先看懂数据手册的时序图,和一些对存储器的操作。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:07:47  更:2022-07-04 23:09:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/22 6:54:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码