普中STM32-PZ6806L开发板(HAL库函数实现-访问多个温度传感器DS18B20)

简介

我们知道多个DS18B20的DQ线是可以被挂在一起的, 也就是一根线上可以访问不同的DS18B20而不会造成数据错乱, 怎么做到的,其实数据手册都有说到, 就是靠64-bit ROM code 进行识别, 也可以理解成Serial Number进行识别, 因为主要差异还是在Serial Number上面;

电路图

两个DS18B20连接到一起
在这里插入图片描述

实现步骤

创建项目

基于 上一篇 普中STM32-PZ6806L开发板(HAL库函数实现-温度传感器DS18B20)

添加用户代码

获取DS18B20的Serial Number信息, 然后记录下来, 用于向指定DS18B20获取温度值

typedef struct 
{
	uint8_t familyCode;
	uint8_t sns[6];
	uint8_t crc;
} SENSOR_DS18B20_SerialNumberInfo;


SENSOR_DS18B20_SerialNumberInfo SENSOR_DS18B20_GetSN(void)
{
	SENSOR_DS18B20_SerialNumberInfo info;
	uint8_t recvs[8] = { 0 };
	
	SENSOR_DS18B20_Reset ();
	HAL_Delay (1);
	SENSOR_DS18B20_Write (0x33);  // read rom
	HAL_Delay (1);
	
	// 1 byte -> family code
	// 2 ~ 7 byte -> serial number
 //  8 byte -> CRC8	
	recvs[0] = SENSOR_DS18B20_Read(); // family code
	info.familyCode = recvs[0];
	
	for (int i = 0; i < 6; ++i) // serial number
	{ 
		recvs[i+1] = SENSOR_DS18B20_Read();
		info.sns[i] = recvs[i+1];
	}
	recvs[7] = SENSOR_DS18B20_Read(); // CRC8
	info.crc = recvs[7];
	if (SENSOR_DS18B20_CRC8(recvs, 7) != recvs[7]) // CRC8 检查
	{
		info.familyCode = 0;
		memset(info.sns, 0, sizeof(info.sns)/sizeof(uint8_t));
		info.crc = 0; 
		return info; // CRC校验不一致
	}
	return info;
}

实现流程参考pdf
在这里插入图片描述
实现代码

/* 两个DS18B20设备 */
#include <stdio.h>
#include <string.h>

/* DS18B20, 提前读取出来的SN&familyCode&CRC码 */
SENSOR_DS18B20_SerialNumberInfo  ds18b20_infos[] = 
{
	{ 0x28, { 0x2E, 0x7C, 0x04, 0x05, 0x00, 0x00 }, 0xCC },
	{ 0x28, { 0x2F, 0x7D, 0x10, 0x02, 0x01, 0x00 }, 0xBE }
};

/* 引脚重新设置为输入 */
static void SENSOR_DS18B20_SetPinInput(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
/* 引脚重新设置为输出 */
static void SENSOR_DS18B20_SetPinOutput(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}

/*
	SENSOR_DS18B20_Reset :
	初始化,也是复位, 每次发送指令前的动作
		0 : 初始化失败
		1 : 初始化成功
*/
static uint8_t SENSOR_DS18B20_Reset(void)
{
	uint8_t res = 0;
	SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);   // 引脚输出模式
	HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0);  // 拉低引脚
	delay_us (480);   // 参考初始化时序图, 延时480us

	SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);    // set the pin as input
	delay_us (60);    // 15~60us等待DS18B20回复信息, 多等20us避免检测不到

	if ( !HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN) )
		res = 1;  // 检测到低电平,  DS18B20有响应
	else 
		res = 0;

	delay_us (420); // 等待DS18B20结束响应

	return res;
}

/* 写流程 */
void SENSOR_DS18B20_Write(uint8_t data)
{
	/*
		按位写, 根据时序图, 按照写的 高电平的时序 和 低电平的时序进行延时
	*/
	for (int i = 0; i < 8; ++i)
	{

		if ((data & (1<<i))!=0) // 写1
		{
			SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);  
			HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
			delay_us (2);  // 低电平保持时间

			SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);  // 输入
			delay_us (60);  // 等待
		}
		else // 写0
		{
			SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);
			HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
			delay_us (60);  // 等待60us

			SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN); // 输入
		}
	}
}
/* 读流程 */
uint8_t SENSOR_DS18B20_Read (void)
{
	uint8_t value = 0;
	SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);
	for (int i=0;i<8;i++)
	{
		SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);

		HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
		delay_us(2);  // 拉低电平等待时间

		SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);
		if (HAL_GPIO_ReadPin (DS18B20_PORT, DS18B20_PIN))  
		{
			value |= 1<<i;  
		}
		delay_us (60);  // DS18B20数据响应时间
	}
	return value;
}

/* 计算CRC码 */
uint8_t SENSOR_DS18B20_CRC8(uint8_t *dats, uint8_t len) 
{
    uint8_t i, dat, crc, fb, st_byt;
    st_byt = 0;
    crc = 0;
    do {
      dat = dats[st_byt];
      for (i = 0; i < 8; i++) 
			{  
					fb = crc ^ dat;
					fb &= 1;
					crc >>= 1;
					dat >>= 1;
					if (fb == 1) 
						crc ^= 0x8c; 
       }
      st_byt++;
    } while (st_byt < len); 
    return crc;
}

/* 获取Serial Number&CRC&family Code */
SENSOR_DS18B20_SerialNumberInfo SENSOR_DS18B20_GetSN(void)
{
	SENSOR_DS18B20_SerialNumberInfo info;
	uint8_t recvs[8] = { 0 };
	
	SENSOR_DS18B20_Reset ();
	HAL_Delay (1);
	SENSOR_DS18B20_Write (0x33);  // read rom
	HAL_Delay (1);
	
	// 1 byte -> family code
	// 2 ~ 7 byte -> serial number
 //  8 byte -> CRC8	
	recvs[0] = SENSOR_DS18B20_Read(); // family code
	info.familyCode = recvs[0];
	
	for (int i = 0; i < 6; ++i) // serial number
	{ 
		recvs[i+1] = SENSOR_DS18B20_Read();
		info.sns[i] = recvs[i+1];
	}
	recvs[7] = SENSOR_DS18B20_Read(); // CRC8
	info.crc = recvs[7];
	if (SENSOR_DS18B20_CRC8(recvs, 7) != recvs[7]) // CRC8 检查
	{
		info.familyCode = 0;
		memset(info.sns, 0, sizeof(info.sns)/sizeof(uint8_t));
		info.crc = 0; 
		return info; // CRC校验不一致
	}
	return info;
}

/* 写Serial Number&CRC&family Code */
void SENSOR_DS18B20_WriteID(uint8_t index) 
{
	uint8_t id_data[8];
	id_data[0] = ds18b20_infos[index].familyCode;
	id_data[7] = ds18b20_infos[index].crc;
	for ( int i = 1; i < 7; ++i )
	{
		id_data[i] = ds18b20_infos[index].sns[i-1];
	}
	
	SENSOR_DS18B20_Reset (); 
	SENSOR_DS18B20_Write (0x55);  // skip ROM; //Match ROM [55h]
	for ( int i = 0; i < 8; i++ )
	{
		SENSOR_DS18B20_Write(id_data[i]);
	}
}

/* 等待电平被拉高 */
void SENSOR_DS18B20_WaitForHigh(uint32_t time) 
{
	SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);
	delay_us(time);
	while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9) == 0);
	SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);
}

/* 将读取值转化成温度值 */
float SENSOR_DS18B20_ValueToTemperature(uint8_t lsb, uint8_t msb)
{
	uint16_t temp = 0;
	temp = (msb << 8) + lsb;
	
	if((temp&0xf800)==0xf800) // 符号位判定是否负数
	{
		temp=(~temp)+1; // 补码转原码
		return temp*(-0.0625); //12bit 增量值
	}
	else
	{
		return temp*0.0625;	//12bit 增量值
	}
}


/* 通过serial number数据获取温度 */
float SENSOR_DS18B20_GetTemperatureByID(uint8_t ds18b20_index)
{
	uint8_t recv_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // 9 Bytes
	uint8_t ds18b20_num = sizeof(ds18b20_infos) / sizeof(SENSOR_DS18B20_SerialNumberInfo);
	uint16_t temp = 0;
	if ( ds18b20_index >= ds18b20_num )
		return 0; // 不存在此设备
	
	SENSOR_DS18B20_Reset ();
	HAL_Delay (1);
	SENSOR_DS18B20_WriteID(ds18b20_index);
	SENSOR_DS18B20_Write(0x44);//Convert Temperature [44h]
	
	SENSOR_DS18B20_WaitForHigh(20);
	SENSOR_DS18B20_Reset ();
	SENSOR_DS18B20_WriteID(ds18b20_index);
	SENSOR_DS18B20_Write(0xBE);//Read Scratchpad [BEh]
	
	
	for (uint8_t i = 0; i < 9; i++)
	{
		recv_data[i] = SENSOR_DS18B20_Read();
	}
	
	return SENSOR_DS18B20_ValueToTemperature(recv_data[0], recv_data[1]);
}

代码

无需下载, 代码上面基本都提供了

Note:
支持你的DS18B20, 你需要修改, 改成你的DS18B20的信息
SENSOR_DS18B20_SerialNumberInfo ds18b20_infos[] =
{
{ 0x28, { 0x2E, 0x7C, 0x04, 0x05, 0x00, 0x00 }, 0xCC },
{ 0x28, { 0x2F, 0x7D, 0x10, 0x02, 0x01, 0x00 }, 0xBE }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/291513.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日好题:acwing:(走迷宫bfs的运用)好久没更新啦

走迷宫&#xff1a; 给定一个 nm 的二维整数数组&#xff0c;用来表示一个迷宫&#xff0c;数组中只包含 0 或 1&#xff0c;其中 0 表示可以走的路&#xff0c;1 表示不可通过的墙壁。 最初&#xff0c;有一个人位于左上角 (1,1)处&#xff0c;已知该人每次可以向上、下、左…

修改选择框el-select样式,显示及下拉样式

修改选择框el-select样式,显示及下拉样式 .el-input__inner {background: rgba(25, 126, 195, 0.2);border: none;color: #fff; }.el-select-dropdown {background: rgba(19, 73, 104, 0.79);border: 2px solid #48e3ff;border-radius: 0; }.el-popper .popper__arrow {display…

华硕ASUS RT-AC1200 pandavan老毛子 128M DDR固件

原版硬件只支持64M DDR2&#xff0c;更换了128M内存&#xff0c;结果找不到对应的固件&#xff0c;而且全部都是英文版的 所以自己编译了中文版的pandavan老毛子&#xff0c;下载位置可能资源审核中&#xff1a;

MT9201 1.2MHz,3V~24V输入高效增压白色LED驱动器 丝印B9HB

描述 MT9201是一个升压转换器&#xff0c;设计用于从单电池锂离子电池驱动多达7系列白色led。MT9201使用电流模式&#xff0c;固定频率结构来调节LED电流&#xff0c;它通过外部电流感测电阻器来测量。其低200mV反馈电压降低了功率损耗&#xff0c;提高了效率。MT9201包括欠电压…

富文本BraftEditor引起的bug

1、BraftEditor踩坑1 #基于之前写的一篇BraftEditor的使用# 1. 问题起源&#xff1a; 打开编辑弹窗--> 下面页面所示--> 当进行分类选择时候&#xff0c;就会报错&#xff0c;并且这个报错还不是一直都有&#xff0c;6次选择出现一次报错吧 2. 解决&#xff1a; 2.1 起…

MySQL概述

M y S Q L 概述 \huge{MySQL概述} MySQL概述 MySQL学习笔记 引入 什么是数据库&#xff1f; D \color{red}D Data B \color{red}B Base&#xff08;DB&#xff09;&#xff0c;存储和管理数据的仓库。 使用的各种电子产品的网页&#xff0c;页面中的数据都是动态的&#xf…

python pillow(PIL)库使用介绍

Python 图像库向 Python 解释器添加了图像处理功能。 该库提供了广泛的文件格式支持、高效的内部表示和相当强大的图像处理功能。 核心图像库旨在快速访问以几种基本像素格式存储的数据。它应该为通用图像处理工具提供坚实的基础。 概述 Python 图像库将图像处理功能添加到…

MSE Serverless 正式商用,构建低成本高弹性的微服务架构

作者&#xff1a;问思 微服务架构充分提升了研发效率&#xff0c;解决了复杂业务系统的快速迭代问题。但随着业务及技术演进&#xff0c;各种微服务组件也愈发复杂。如何实现更敏捷的开发&#xff0c;降低微服务开发运维成本&#xff0c;做到全链路的弹性&#xff0c;保障整个…

Windows找不到文件‘chrome‘,请确定文件名是否正确后,再试一次。

本文主要记录遇到vscode运行HTML文件提示&#xff1a; Windows找不到文件‘chrome‘&#xff0c;请确定文件名是否正确后&#xff0c;再试一次。问题的解决办法。 目录 一、打开设置 二 、搜索Live Server Config &#xff08;1&#xff09;安装Live Server插件 &#xff0…

「数据结构」八大排序1

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;初阶数据结构 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 文章目录 &#x1f349;插入排序&#x1f34c;直接插入排序&#x1f95d;复杂度及稳定性 &#x1f34c;希尔排序&#x1f95d;预…

亚信安慧AntDB携核心业务系统数据库升级改造方案亮相“2023年国有企业应用场景发布会”

近日&#xff0c;亚信安慧AntDB数据库携核心业务系统数据库升级改造方案亮相“2023年国有企业应用场景发布会”。本次国有企业应用场景发布会由北京市国资委主办、中关村发展集团承办、中关村软件园公司协办&#xff0c;以“融通创新 智引未来”为主题&#xff0c;聚焦智慧城市…

虚拟机添加显示屏

1、关闭虚拟机&#xff0c;虚拟机在为关机的情况下&#xff0c;虚拟机设置->显示器->监视器 都是灰色的&#xff0c;不能设置&#xff1b; 2、虚拟机设置->显示器->监视器 “监视器数量” 设置为2 “拉伸模式” 不要勾选 点确定 3、点击 查看->循环使用多个…

解决SyntaxError: future feature annotations is not defined,可适用其他包

方法&#xff1a;对报错的包进行降级 pip install tikzplotlib0.9.8site-packages后面是使用pip install安装的包&#xff0c;根据这个找到报错的包 想法来源&#xff1a; 环境是python3.6&#xff0c;完全按照作者要求进行环境配置&#xff0c;但仍报错。 我在网上找的解决…

【Java基础篇】常见的字符编码、以及它们的区别

常见的字符编码、以及它们的区别 ✔️ 解析✔️扩展知识仓✔️Unicode和UTF-8有啥关系?✔️有了UTF-8&#xff0c;为什么要出现GBK✔️为什么会出现乱码 ✔️ 解析 就像电报只能发出 ”滴” 和 ”答” 声一样&#xff0c;计算机只认识 0 和 1 两种字符&#xff0c;但是&#x…

Sourcetree安装和配置

先了解Sourcetree是用来做什么的 简单说就是一个有可视化界面的Gti 用途&#xff1a; &#xff08;1&#xff09;克隆(clone)&#xff1a;从远程仓库URL加载创建一个与远程仓库一样的本地仓库 提交(commit)&#xff1a;将暂存文件上传到本地仓库&#xff08;我们在Finder中对本…

目标管理(案例)

介绍 本篇Codelab将介绍如何使用State、Prop、Link、Watch、Provide、Consume管理页面级变量的状态&#xff0c;实现对页面数据的增加、删除、修改。要求完成以下功能&#xff1a; 实现一个自定义弹窗&#xff0c;完成添加子目标的功能。实现一个可编辑列表&#xff0c;可点击指…

docker-compose Install spug 3

前言 Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台,整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布部署、在线任务计划、配置中心、监控、报警等一系列功能。 创建一键安装spug 脚本 自动化脚本兼容(ubuntu,RedHat系列及复刻系列,…

SpringBoot 接口对枚举类型的入参以及出参的转换处理

目录 1、在项目中使用枚举类型2、不做任何处理的演示效果2.1、接口出参2.2、接口入参 3、用枚举的code作为参数和返回值3.1 代码案例3.1.1、定义枚举基础接口BaseEnum&#xff0c;每个枚举都实现该接口3.1.2、性别Sex枚举并实现接口BaseEnum3.1.3、定义BaseEnum枚举接口序列化3…

P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题

网址如下&#xff1a;P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 水了道题 学了求最小公倍数和最大公因数的新方法 我对辗转相除法这个东西有所耳闻&#xff0c;但是从来没有用过 所以我只会枚举法求这两个东西 而…

切换node.js不同版本

切换node.js不同版本 因新项目用到vite4创建项目&#xff0c;输入命令后报错&#xff0c;经查询得知是node版本过低导致&#xff0c;所以需要升级node版本&#xff0c;但是又有老的项目需要维护&#xff0c;因此需要多个版本的node使用需求。 流程&#xff1a; 卸载原有的node…