STM32-HAL库 驱动DS18B20温度传感器 -- 2024.10.8

news2024/11/24 5:24:59

目录

一、教程简介

二、驱动理论讲解

三、CubeMX生成底层代码

四、Keil5编写代码

五、实验结果


一、教程简介

        本教程面向初学者,只介绍DS18B20的常用功能,但也能满足大部分的运用需求。跟着本教程操作,可在10分钟内解决DS18b20通信难题。

二、驱动理论讲解

        DS18b20支持多传感器共用一个引脚,但本教程只教使用一个温湿度传感器。使用DS18b20可分为下面两个步骤进行

(一)初始化:

        1、将引脚初始化为推挽输出、上拉。

        2、发送复位脉冲:引脚输出大于480us的低电平复位信号(建议600us),延时600us之后,需将引脚拉高并延时15us。

        3、检测存在脉冲:将引脚设置为上拉输入,并检测低电平到来的时间,若超过100us还没检测到低电平,则初始化失败。检测到低电平后开始计算时间,若低超过240us还没检测到高电平,则初始化失败。

(二)获取温度:

        1、配置单DS18b20模式:重复初始化操作后发送命令:0xCC

        2、发送温度转换命令:发送0x44

        3、配置单DS18b20模式:重复初始化操作后发送命令:0xCC

        4、发送读取命令:发送0xBE

        5、接收两个字节的温度数据

三、CubeMX生成底层代码

1、芯片选择:这里选用STM32F103C8t6

 2、配置Debug模式

3、 配置外部高速时钟

4、 配置时钟速率

5、 配置DS18b20引脚

6、配置串口

7、输出工程文件

四、Keil5编写代码

1、ds18b20.c 代码

/* 包含头文件 ----------------------------------------------------------------*/
#include "ds18b20.h"

/**
  * 函数功能: DS18B20 初始化函数
  * 返 回 值: 1为初始化失败,0为初始化成功
  */
uint8_t DS18B20_Init(void)
{
  DS18B20_Mode_Out_PP();            //推挽输出模式
        
  DS18B20_Dout_HIGH();  						//输出高电平
        
  DS18B20_Rst();        						//输出复位脉冲
  
  return DS18B20_Presence ();  			//返回响应情况
}


/**
  * 函数功能: 使DS18B20-DATA引脚变为上拉输入模式
  */
static void DS18B20_Mode_IPU(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 串口外设功能GPIO配置 */
  GPIO_InitStruct.Pin   = DS18b20_Pin;
  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);
        
}

/**
  * 函数功能: 使DS18B20-DATA引脚变为推挽输出模式
  */
static void DS18B20_Mode_Out_PP(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 串口外设功能GPIO配置 */
  GPIO_InitStruct.Pin = DS18b20_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);          
}

/**
  * 函数功能: 主机给从机发送复位脉冲
  */
static void DS18B20_Rst(void)
{
   DS18B20_Mode_Out_PP(); /* 主机设置为推挽输出 */
   DS18B20_Dout_LOW();    /* 主机输出低电平 */
   DS18B20_Delay(750);    /* 主机至少产生480us的低电平复位信号 */
   DS18B20_Dout_HIGH();   /* 主机在产生复位信号后,需将总线拉高 */
   DS18B20_Delay(15);     /* 从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲 */
}

/**
  * 函数功能: 检测从机给主机返回的存在脉冲
  * 返 回 值: 0:成功,1:失败
  */

static uint8_t DS18B20_Presence(void)
{
   uint8_t pulse_time = 0;
   /* 主机设置为上拉输入 */
   DS18B20_Mode_IPU();
   
   /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 
    * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
    */
   while( DS18B20_Data_IN() && pulse_time<100 )
   {
      pulse_time++;
      DS18B20_Delay(1);
   }        
   /* 经过100us后,存在脉冲都还没有到来*/
   if( pulse_time >=100 )
      return 1;
   else
      pulse_time = 0;
   
   /* 存在脉冲到来,且存在的时间不能超过240us */
   while( !DS18B20_Data_IN() && pulse_time<240 )
   {
       pulse_time++;
       DS18B20_Delay(1);
   }        
   if( pulse_time >=240 )
       return 1;
   else
       return 0;
}

/**
  * 函数功能: 从DS18B20读取一个bit
  * 返 回 值: 读取到的数据
  */
static uint8_t DS18B20_ReadBit(void)
{
   uint8_t dat;
   
   /* 读0和读1的时间至少要大于60us */        
   DS18B20_Mode_Out_PP();
   /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
   DS18B20_Dout_LOW();
   DS18B20_Delay(10);
   
   /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
   DS18B20_Mode_IPU();
   //Delay_us(2);
   
   if( DS18B20_Data_IN() == SET )
           dat = 1;
   else
           dat = 0;
   
   /* 这个延时参数请参考时序图 */
   DS18B20_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;
}

/**
  * 函数功能: 写一个字节到DS18B20,低位先行
  * 输入参数: dat:待写入数据
  */
static void DS18B20_WriteByte(uint8_t dat)
{
   uint8_t i, testb;
   DS18B20_Mode_Out_PP();
   for( i=0; i<8; i++ )
   {
      testb = dat&0x01;
      dat = dat>>1;                
      /* 写0和写1的时间至少要大于60us */
      if (testb)
      {                        
         DS18B20_Dout_LOW();
         /* 1us < 这个延时 < 15us */
         DS18B20_Delay(8);
         
         DS18B20_Dout_HIGH();
         DS18B20_Delay(58);
      }           
      else
      {                   
         DS18B20_Dout_LOW();
         /* 60us < Tx 0 < 120us */
         DS18B20_Delay(70);
         
         DS18B20_Dout_HIGH();                
         /* 1us < Trec(恢复时间) < 无穷大*/
         DS18B20_Delay(2);
      }
   }
}

/**
  * 函数功能: 跳过匹配 DS18B20 ROM
  */
static void DS18B20_SkipRom ( void )
{
   DS18B20_Rst();                   
   DS18B20_Presence();                 
   DS18B20_WriteByte(0XCC);                /* 跳过 ROM */        
}

/**
  * 函数功能: 获取 DS18B20 温度值 
  * 返 回 值: 浮点型温度值
  */
float DS18B20_GetTemp_SkipRom ( void )
{
   uint8_t tpmsb, tplsb;
   short s_tem;
   float f_tem;
   
   DS18B20_SkipRom ();
   DS18B20_WriteByte(0X44);                                /* 开始转换 */
   
   DS18B20_SkipRom ();
	 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;        
   else
     f_tem = s_tem * 0.0625;
   
   return f_tem;         
}

/**
  * 微妙延时函数
  * 全系列通用,只需要将宏定义CPU_FREQUENCY_MHZ根据时钟主频修改即可。
  * 系统滴答定时器是HAL库初始化的,且必须有HAL库初始化。
  */
#define CPU_FREQUENCY_MHZ   (int)(HAL_RCC_GetHCLKFreq()/1000000)		// 自动获取STM32时钟主频
void DS18B20_Delay(__IO uint32_t delay)  
{
   int last, curr, val;
   int temp;

   while (delay != 0)
   {
      temp = delay > 900 ? 900 : delay;
      last = SysTick->VAL;
      curr = last - CPU_FREQUENCY_MHZ * temp;
      if (curr >= 0)
      {
         do
         {
             val = SysTick->VAL;
         }
         while ((val < last) && (val >= curr));
      }
      else
      {
         curr += CPU_FREQUENCY_MHZ * 1000;
         do
         {
             val = SysTick->VAL;
         }
         while ((val <= last) || (val > curr));
      }
      delay -= temp;
    }
}

2、ds18b20.h 代码

#ifndef __DS18B20_H
#define __DS18B20_H

/* 包含头文件 ----------------------------------------------------------------*/
#include "main.h"

/* 引脚操作函数宏定义 --------------------------------------------------------*/
#define DS18B20_Dout_LOW()               HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_RESET) 
#define DS18B20_Dout_HIGH()              HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_SET)
#define DS18B20_Data_IN()                HAL_GPIO_ReadPin(DS18b20_GPIO_Port,DS18b20_Pin)

/* 函数声明 ------------------------------------------------------------------*/
void 		DS18B20_Rst(void);
void 		DS18B20_SkipRom(void);
void 		DS18B20_Mode_IPU(void);
void 		DS18B20_Mode_Out_PP(void);
void 		DS18B20_WriteByte(uint8_t dat);
void 		DS18B20_Delay(__IO uint32_t delay);
float   DS18B20_GetTemp_SkipRom(void);
uint8_t DS18B20_Init(void);
uint8_t DS18B20_ReadBit(void);
uint8_t DS18B20_Presence(void);
uint8_t DS18B20_ReadByte(void);

#endif 

3、main.c 参考调用代码

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ds18b20.h"
#include "stdio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
char  Tx_Buf[30] = {0};
float Temp = 0;
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	while(DS18B20_Init())
	{
		HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化失败\r\n",19,100);
		HAL_Delay(1000);
	}
	HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化成功\r\n",19,100);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		Temp = DS18B20_GetTemp_SkipRom();
		sprintf(Tx_Buf,"温度:%0.3f \r\n",Temp);
		HAL_UART_Transmit(&huart1,(uint8_t*)Tx_Buf,15,100);
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

五、实验结果

        通过本驱动使用DS18b20测量出来的环境温度,与米家温湿度计测量的结果仅仅相差0.012摄氏度,测量精度非常可观。

 六、特别说明

  • 同学们在操作的过程中遇到的问题可在评论区留言,我看到后会第一时间回复。
  • 想看其他传感器的教程也可在评论区留言,我会按照大家的需求来修改教程内容。
  • 若您觉得本教程对您有所帮助,请点赞、收藏,这是我持续更新的最大动力,感谢您!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows认证

本地环境用户信息存储在%systemroot%/system32/SAM 域环境用户信息存储在ntds.dit 本地认证 windows系统下哈希结构&#xff1a;username:RID:LM-HASH:NT-HASH LM哈希 算法&#xff1a; 转大写&#xff0c;转二进制&#xff0c;补0补足14字节 二分获得两段字串&#xff…

算法:238.除自身以外数组的乘积

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;前缀和&#xff09; 这道题非常类似 724. 寻找数组的中心下标 在前一篇博客讲解了该题目 传送门:算法&#xff1a;724.寻找数组的中心下标 这道题目的区别在于&#xff0c;这道题是预处理前缀积和后缀积 另外&#x…

了解网页 blob 链接

blob 链接 自从 HTML5 提供了 video 标签&#xff0c;在网页中播放视频变得非常简单&#xff0c;只要在代码中插入一个 video 标签&#xff0c;再将 video 标签的 src 属性设置为视频的链接就可以了。由于 src 指向的是视频文件真实的地址&#xff0c;所以当我们通过浏览器的调…

如何绘制短剧产业链图谱?短剧产业前景如何?

绘制短剧产业链图谱是一个涉及多个环节的复杂过程。我们首先需要确定产业链的主要环节&#xff0c;包括内容创作、制作、发行、宣传和观众。每个环节都由不同的参与者组成&#xff0c;如编剧、导演、演员、制作公司、版权销售商、在线平台、电视台、广告公司和消费者等&#xf…

《CTF 特训营》:网络安全竞赛的进阶指南

在网络安全领域日益受到重视的今天&#xff0c;CTF&#xff08;Capture The Flag&#xff09;竞赛作为一种检验和提升网络安全技能的方式&#xff0c;受到了越来越多爱好者的关注。而《CTF 特训营》这本书&#xff0c;无疑是一本帮助读者深入了解 CTF 竞赛的优秀读物。 一、书籍…

Linux shell编程学习笔记86:sensors命令——硬件体温计

0 引言 同事们使用的Windows系统电脑&#xff0c;经常莫名其妙地装上了鲁大师&#xff0c;鲁大师的一项功能是显示系统cpu等硬件的温度。 在Linux系统中&#xff0c;sensors命令可以提供类似的功能。 1 sensors命令 的安装和配置 1.1 sensors命令 的安装 要使用sensors命…

INS淡绿色风格人像街拍Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色介绍 INS 淡绿色风格人像街拍通过 Lightroom 调色可以营造出清新、自然、时尚的视觉效果。这种风格以淡绿色为主色调&#xff0c;给人一种宁静、舒适的感觉。 预设信息 调色风格&#xff1a;INS风格预设适合类型&#xff1a;人像&#xff0c;街拍&#xff0c;自拍&#…

动态规划算法题目练习——62.不同路径

1.题目解析 题目来源&#xff1a;62.不同路径——力扣 测试用例 2.算法原理 1.状态表示 这时由于避免越界初始化所以将左上角置为虚拟位置&#xff0c;创建一个二维dp表用来存储到当前为止的所有路径 2.状态转移方程 以dp[i,j]为例&#xff0c;起点到该位置的路径是起点到其上…

信息安全工程师(40)防火墙技术应用

一、防火墙的基本概念 防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量&#xff0c;以保护网络免受未经授权的访问和攻击。它可以是装配多张网卡的通用计算机&#xff0c;也可能是通用的物理设备。防火墙通过在网络之间设置访问控制策略&#xff0c;对进出的通信流…

JAVA开源项目 新生报到网站 计算机毕业设计

本文项目编号 T 002 &#xff0c;文末自助获取源码 \color{red}{T002&#xff0c;文末自助获取源码} T002&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 提…

【C语言】指针练习题

一、指针指向问题 int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));return 0; } 结果为&#xff1a;2&#xff0c;5。&a是整个数组&#xff08;&a 1&#xff09;被强转为&#xff08;int*&am…

mujoco版本问题以及ERROR: Failed building wheel for mujoco-py

问题&#xff1a; ERROR: Failed building wheel for mujoco-py Failed to build mujoco-py ERROR: Could not build wheels for mujoco-py, which is required to install pyproject.toml-based projects 起因&#xff1a; 一开始我使用这个命令安装pip install mujoco_py&…

跨境卖家品牌出海要注意哪些方面

随着目前互联网的发展&#xff0c;市场由线下扩张到全国&#xff0c;再扩张到了全球&#xff0c;但是海外市场和国内并不相同跨境卖家品牌想要出海&#xff0c;需要注意多个方面&#xff0c;以确保能够在国际市场上成功立足并发展。以下是一些关键点&#xff1a; 首先想得拥有…

2-116 基于matlab的主成分分析(PCA)及累积总和(CUSUM)算法故障监测

基于matlab的主成分分析&#xff08;PCA&#xff09;及累积总和&#xff08;CUSUM&#xff09;算法故障监测&#xff0c;针对传统的多元统计分析方法对生产过程中微小故障检测不灵敏的问题&#xff0c;使用基于主元分析的累积和的微小故障检测方法进行故障监测&#xff0c;通过…

微信卸载后聊天记录全部消失,重新安装后有方法恢复吗?

微信作为我们日常沟通的重要工具&#xff0c;其聊天记录往往承载着许多珍贵的回忆和重要的信息。然而&#xff0c;在日常使用手机的过程中&#xff0c;我们时常会出于清理内存、解决软件故障或尝试新版本等原因&#xff0c;选择卸载并重新安装微信app。然而&#xff0c;这一简单…

国家公务员考试倒计时页面介绍

代码复刻 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>国家公务员考试倒计时</title><…

malloc(0)

malloc(0) 在操作系统底层的实现涉及内存分配管理的多个方面。下面是对 malloc(0) 的实现原理的详细解释&#xff1a; 1. 内存分配管理 操作系统通过内存管理子系统来处理内存分配请求&#xff0c;包括 malloc 函数。内存分配通常使用以下几种策略&#xff1a; 堆管理&#…

OpenFegin

文章目录 一、OpenFegin是什么&#xff1f;二、基本使用三、超时重试机制4.自定义超时重传机制五、底层实现 一、OpenFegin是什么&#xff1f; OpenFeign的全称为Spring Cloud OpenFeign(下文简称OpenFeign),是Spring Cloud团队开发的一款基于 Feign的框架&#xff0c;声明式W…

Overleaf 无法显示图片

问题描述 在Overleaf中的代码为&#xff1a; \begin{figure}\centering\includegraphics[width0.98\linewidth]{figures/test.png}\caption{This is a test.}\label{fig:test} \end{figure}但无法正常显示图片&#xff1a; 解决方案 修改编译模式为正常Normal而非快速Fast …

Python 工具库每日推荐【python-docx】

文章目录 引言Python 文档处理库的重要性今日推荐:Python-docx 工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:自动生成个性化证书案例分析高级特性样式应用表格操作扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScript 设计模…