Clion开发Stm32之温湿度传感器(DS18B20)驱动编写和测试
前言
涵盖之前文章:
- Clion开发STM32之HAL库GPIO宏定义封装(最新版)
- Clion开发stm32之微妙延迟(采用nop指令实现)
- Clion开发STM32之日志模块(参考RT-Thread)
DSP18B20驱动文件
头文件
/*******************************************************************************Copyright (c) [scl]。保留所有权利。* 存储的温度是16 位的带符号扩展的二进制补码形式* 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位* |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|* 低字节 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |* |-----符号位:0->正 1->负-------|-----------整数-----------|* 高字节 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |* 温度 = 符号位 + 整数 + 小数*0.0625******************************************************************************/
#ifndef F1XX_TEMPLATE_MODULE_DS18B20_H
#define F1XX_TEMPLATE_MODULE_DS18B20_H#include "sys_core.h"/*** @memberof input_mode_set 输入模式配置* @memberof out_mode_set 输出模式配置* @memberof send_data 发送数据* @memberof us_delay 微秒延迟*/
typedef struct {void (*input_mode_set)(void);void (*out_mode_set)(void);void (*send_data)(uint32_t status);uint32_t (*read_data)(void);void (*us_delay)(uint32_t us);
} DS18B20_conf_t;void DS18B20_conf_set(DS18B20_conf_t *cnf);bool DS18B20_Driver_Init(void);void DS18B20_readId(uint8_t *ds18b20_id);float DS18B20_GetTemp_SkipRom(void);float DS18B20_GetTemp_MatchRom(const uint8_t *ds18b20_id);#endif //F1XX_TEMPLATE_MODULE_DS18B20_H
源文件
/*******************************************************************************Copyright (c) [scl]。保留所有权利。******************************************************************************/
#include "ds18b20/module-ds18b20.h"#define DBG_ENABLE
#define DBG_SECTION_NAME "ds18b20"
#define DBG_LEVEL DBG_LOG // DBG_LOG DBG_INFO DBG_WARNING DBG_ERROR#include "sys_dbg.h"static DS18B20_conf_t *conf_ptr = NULL;
#define DS18B20_DQ_0 conf_ptr->send_data(0)
#define DS18B20_DQ_1 conf_ptr->send_data(1)static void DS18B20_WriteByte(uint8_t dat);static uint8_t DS18B20_ReadByte(void);static bool DS18B20_Presence(void);void DS18B20_conf_set(DS18B20_conf_t *cnf) {conf_ptr = cnf;}static void DS18B20_Rst(void) {conf_ptr->out_mode_set();DS18B20_DQ_0;/* 主机至少产生480us的低电平复位信号 */conf_ptr->us_delay(750);/* 主机在产生复位信号后,需将总线拉高 */DS18B20_DQ_1;/*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/conf_ptr->us_delay(15);
}
/*** 驱动初始化* @return*/
bool DS18B20_Driver_Init(void) {if (conf_ptr == NULL) return false;conf_ptr->out_mode_set();DS18B20_DQ_1;DS18B20_Rst();return DS18B20_Presence();
}/*** @brief 在匹配 ROM 情况下获取 DS18B20 温度值* @param ds18b20_id :用于存放 DS18B20 序列号的数组的首地址*/
void DS18B20_readId(uint8_t *ds18b20_id) {if (conf_ptr == NULL) return;uint8_t uc;DS18B20_WriteByte(0x33); //读取序列号for (uc = 0; uc < 8; uc++)ds18b20_id[uc] = DS18B20_ReadByte();
}/***** @brief 在跳过匹配 ROM 情况下获取 DS18B20 温度值* @return*/
float DS18B20_GetTemp_SkipRom(void) {uint8_t tpmsb = 0, tplsb = 0;short s_tem = 0;float f_tem = 0;/* -------------跳过 ROM-START---------- */DS18B20_Rst();DS18B20_Presence();DS18B20_WriteByte(0XCC);/* -------------跳过 ROM-END---------- */DS18B20_WriteByte(0X44); /* 开始转换 *//* -------------跳过 ROM-START---------- */DS18B20_Rst();DS18B20_Presence();DS18B20_WriteByte(0XCC); /* 跳过 ROM *//* -------------跳过 ROM-END---------- */DS18B20_WriteByte(0XBE); /* 读温度值 */tplsb = DS18B20_ReadByte();tpmsb = DS18B20_ReadByte();s_tem = tpmsb << 8;s_tem = s_tem | tplsb;if (s_tem < 0) /* 负温度 */f_tem = (~s_tem + 1) * 0.0625;elsef_tem = s_tem * 0.0625;return f_tem;
}float DS18B20_GetTemp_MatchRom(const uint8_t *ds18b20_id) {uint8_t tpmsb, tplsb, i;short s_tem;float f_tem;/* -------------匹配 ROM-START---------- */DS18B20_Rst();DS18B20_Presence();DS18B20_WriteByte(0X55);/* -------------匹配 ROM-END---------- */DS18B20_Rst();DS18B20_Presence();DS18B20_WriteByte(0X55); /* 匹配 ROM */for (i = 0; i < 8; i++)DS18B20_WriteByte(ds18b20_id[i]);DS18B20_WriteByte(0X44); /* 开始转换 *//* -------------匹配 ROM-START---------- */DS18B20_Rst();DS18B20_Presence();DS18B20_WriteByte(0X55);/* -------------匹配 ROM-END---------- */for (i = 0; i < 8; i++)DS18B20_WriteByte(ds18b20_id[i]);DS18B20_WriteByte(0XBE); /* 读温度值 */tplsb = DS18B20_ReadByte();tpmsb = DS18B20_ReadByte();s_tem = tpmsb << 8;s_tem = s_tem | tplsb;if (s_tem < 0) /* 负温度 */f_tem = (~s_tem + 1) * 0.0625;elsef_tem = s_tem * 0.0625;return f_tem;}static void DS18B20_WriteByte(uint8_t dat) {uint8_t i, testb;conf_ptr->out_mode_set();for (i = 0; i < 8; i++) {testb = dat & 0x01;dat = dat >> 1;/* 写0和写1的时间至少要大于60us */if (testb) {DS18B20_DQ_0;/* 1us < 这个延时 < 15us */conf_ptr->us_delay(8);DS18B20_DQ_1;conf_ptr->us_delay(58);} else {DS18B20_DQ_0;/* 60us < Tx 0 < 120us */conf_ptr->us_delay(70);DS18B20_DQ_1;/* 1us < Trec(恢复时间) < 无穷大*/conf_ptr->us_delay(2);}}
}/** 从DS18B20读取一个bit*/
static uint8_t DS18B20_ReadBit(void) {uint8_t dat;/* 读0和读1的时间至少要大于60us */conf_ptr->out_mode_set();/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */DS18B20_DQ_0;conf_ptr->us_delay(10);/* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */conf_ptr->input_mode_set();//DHT11_DELAY_US(2);if (conf_ptr->read_data() == 1)dat = 1;elsedat = 0;/* 这个延时参数请参考时序图 */conf_ptr->us_delay(45);return dat;
}/** 从DS18B20读一个字节,低位先行*/
static uint8_t DS18B20_ReadByte(void) {uint8_t i, j, dat = 0;for (i = 0; i < 8; i++) {j = DS18B20_ReadBit();dat = (dat) | (j << i);}return dat;
}static bool DS18B20_Presence(void) {uint8_t pulse_time = 0;/* 主机设置为上拉输入 */conf_ptr->input_mode_set();/* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号* 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/while (conf_ptr->read_data() && pulse_time < 100) {pulse_time++;conf_ptr->us_delay(1);}/* 经过100us后,存在脉冲都还没有到来*/if (pulse_time >= 100)return 1;elsepulse_time = 0;/* 存在脉冲到来,且存在的时间不能超过240us */while (!conf_ptr->read_data() && pulse_time < 240) {pulse_time++;conf_ptr->us_delay(1);}if (pulse_time >= 240)return false;elsereturn true;
}
测试配置
/*******************************************************************************Copyright (c) [scl]。保留所有权利。******************************************************************************/
#include "app_conf.h"#define APP_CONF_ENABLE_DS18B20 (1)
#if APP_CONF_ENABLE_DS18B20#include "ds18b20/module-ds18b20.h"#define DBG_ENABLE
#define DBG_SECTION_NAME "DS18B20"
#define DBG_LEVEL DBG_LOG // DBG_LOG DBG_INFO DBG_WARNING DBG_ERROR#include "sys_dbg.h"/*-********************************************DS18B20变量定义******************************************-*/
static DS18B20_conf_t ds18b20_conf;
static stm_pin_define_t *ds18b20_pin_ptr = NULL;static void out_mode_set(void) { stm32_pin_define_mode_set(ds18b20_pin_ptr, pin_mode_output); }static void input_mode_set(void) { stm32_pin_define_mode_set(ds18b20_pin_ptr, pin_mode_input); }static void send_data(uint32_t status) { stm32_pin_define_set(ds18b20_pin_ptr, status); }static uint32_t read_data(void) { return stm32_pin_define_read(ds18b20_pin_ptr); }/*-********************************************DS18B20_pre_init******************************************-*/
static void DS18B20_pre_init() {ds18b20_pin_ptr = stm_get_pin(PE6);ds18b20_conf.us_delay = bsp_us_delay_nop;ds18b20_conf.out_mode_set = out_mode_set;ds18b20_conf.input_mode_set = input_mode_set;ds18b20_conf.send_data = send_data;ds18b20_conf.read_data = read_data;DS18B20_conf_set(&ds18b20_conf);
}sys_pre_init_export(DS18B20, DS18B20_pre_init);/*-********************************************DS18B20_init******************************************-*/
static void DS18B20_init() {while (!DS18B20_Driver_Init()) {};LOG_D("DS18B20_Driver_Init ok");}sys_init_export(DS18B20, DS18B20_init);/*-***********************************************DS18B20_after_init***************************************-*/
static void DS18B20_after_init() {uint8_t uc, ucDs18b20Id[8];DS18B20_readId(ucDs18b20Id); // 读取 DS18B20 的序列号os_ps("DS18B20_readId:");for (int i = 0; i < 8; ++i) {os_ps("%X", ucDs18b20Id[i]);}os_ps("\r\n");while (true) {float temp = DS18B20_GetTemp_MatchRom(ucDs18b20Id);LOG_D("TEMP is %0.3f", temp);HAL_Delay(1000);}
}sys_after_init_export(DS18B20, DS18B20_after_init);/*-**************************************DS18B20内部使用************************************************-*/#endif //APP_CONF_ENABLE_DS18B20
结果
相关文章:

Clion开发Stm32之温湿度传感器(DS18B20)驱动编写和测试
前言 涵盖之前文章: Clion开发STM32之HAL库GPIO宏定义封装(最新版)Clion开发stm32之微妙延迟(采用nop指令实现)Clion开发STM32之日志模块(参考RT-Thread) DSP18B20驱动文件 头文件 /*******************************************************************************Copy…...

文档管理NAS储存安全吗?
关键词:私有化、知识管理系统、文档管理、群晖NAS、协同编辑 随着企业不断发展扩大,企业的知识文档也逐渐增多,很多企业方便管理及考虑数据安全问题会将文件数据储存至NAS。 但将企业文档数据放在NAS上就足够安全的吗? 天翎文档管…...

用windeployqt.exe打包Qt代码
首先找到我们编译Qt代码的对应Qt版本的dll目录,该目录下有windeployqt.exe: D:\DevTools\Qt\5.9\msvc2017_64\bin 在这个目录下打开cmd程序。 然后把要打包的exe放到一个单独的目录下,比如: 然后在cmd中调用: winde…...

【Python机器学习】实验04(2) 机器学习应用实践--手动调参
文章目录 机器学习应用实践1.1 准备数据此处进行的调整为:要所有数据进行拆分 1.2 定义假设函数Sigmoid 函数 1.3 定义代价函数1.4 定义梯度下降算法gradient descent(梯度下降) 此处进行的调整为:采用train_x, train_y进行训练 1.5 绘制决策边界1.6 计算…...

【爬虫案例】用Python爬取iPhone14的电商平台评论
用python爬取某电商网站的iPhone14评论数据, 爬取目标: 核心代码如下: 爬取到的5分好评: 爬取到的3分中评: 爬取到的1分差评: 所以说,用python开发爬虫真的很方面! 您好&…...

01)docker学习 centos7离线安装docker
docker学习 centos7离线安装docker 在实操前可以先看下docker教程,https://www.runoob.com/docker/docker-tutorial.html , 不过教程上都是在线安装方式,很方便,离线安装肯定比如在线麻烦点。 一、什么是Docker 在学习docker时,在网上看到一篇博文讲得很好,自己总结一下…...
前端 - 实习两个星期总结
文章目录 吐槽总结新人建议项目学习到的 今天已经是菜鸟实习的第二个星期了,怎么说呢,反正就是进的一个不大不小的厂,做着不难不易的事,菜鸟现在主要做的就是适配!现在就来总结一下,不过这之前,…...

MySQL——主从复制
1.理解MySQL主从复制原理。 2.完成MySQL主从复制。 1.理解MySQL主从复制原理。 1)、MySQL支持的复制类型 (1)、基于语句( statement )的复制 在主服务器上执行SQL 语句,在从服务器上执行同样的语句。 My…...
报表下载工具
1.需求说明 我有一堆文件的Url地址, 现在需要按照企业,项目和报表类型分类下载到对应的文件夹中 2.相关实体类 企业文件夹定义 package com.vz.utils.report;import lombok.Data; import java.util.ArrayList; import java.util.List; import java.uti…...

树及其遍历
文章目录 树树定义专业术语树分类 二叉树分类存储连续存储(完全二叉树)链式存储一般树的存储森林的存储 线索二叉树哈夫曼树构造步骤 遍历先序遍历中序遍历后续遍历 链式二叉树遍历具体代码已知两种遍历序列求原始二叉树已知先序和中序求后序已知中序和后…...
Qt报错解决办法
anaconda环境安装qt报错解决办法 报错:thresholdGap: 20 pointsShape: 164142 qt.qpa.plugin: Could not find the Qt platform plugin “wayland” in “/home/tianhailong/anaconda3/envs/edge_algorithm/lib/python3.8/site-packages/cv2/qt/plugins” This app…...

Python(四十七)列表对象的创建
❤️ 专栏简介:本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中,我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 :本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…...

#systemverilog# 说说Systemverilog中《automatic》那些事儿
前面我们学习了有关systemverilog语言中有关《static》的一些知识,同static 关系比较好的哥们,那就是 《automatic》。今天,我们了解认识一下。 在systemveriog中,存在三种并发执行语句,分别是fork..join,fork...join_any和fork..join_none,其中只有fork...join_none不…...

C/C++ 动态内存分配与它的指针变量
一、什么是内存的动态分配 全局变量分配在内存中的静态存储区。局部变量(包括形参)分配在内存中的动态存储区,这个存储区是一个称为栈的区域。除此之外,C语言还允许建立内存动态分配区域,以存放一些临时用的数据&…...

UE5初学者快速入门教程
虚幻引擎是一系列游戏开发工具,能够将 2D 手机游戏制作为 AAA 游戏机游戏。虚幻引擎 5 用于开发下一代游戏,包括Senuas Saga: Hellblade 2、Redfall(来自 Arkane Austin 的合作射击游戏)、Dragon Quest XII: The Flames of Fate、…...
论文笔记--FEDERATED LEARNING: STRATEGIES FOR IMPROVING COMMUNICATION EFFICIENCY
论文笔记--FEDERATED LEARNING: STRATEGIES FOR IMPROVING COMMUNICATION EFFICIENCY 1. 文章简介2. 文章概括3 文章重点技术3.1 联邦学习(federated learning, FL)3.2 Structured updates3.3 Sketched Update 4. 文章亮点5. 原文传送门 1. 文章简介 标题:FEDERATE…...

STM32MP157驱动开发——按键驱动(异步通知)
文章目录 “异步通知 ”机制:信号的宏定义:信号注册 APP执行过程驱动编程做的事应用编程做的事异步通知方式的按键驱动程序(stm32mp157)button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “异步通知 ”机制: 信号的宏定义&#x…...

医疗器械维修工程师心得
彩虹医械维修技能班9月将开展本年第三期长期班,目前咨询人员也陆续多了起来,很多刚了解到医疗行业的,自身也没有多少相关的基础,在咨询时会问到没有基础能否学的会? 做了这行业的都知道,无论多么复杂的设备…...

Vue3 Radio单选切换展示不同内容
Vue3 Radio单选框切换展示不同内容 环境:vue3tsviteelement plus 技巧:v-if,v-show的使用 实现功能:点击单选框展示不同的输入框 效果实现前的代码: <template><div class"home"><el-row …...

FreeRTOS之二值信号量
什么是信号量? 信号量(Semaphore),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代 码段不被并发调用。 信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用&am…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...