Clion开发Stm32之温湿度传感器(DS18B20)驱动编写和测试

news2024/11/16 7:26:03

前言

涵盖之前文章:

  1. Clion开发STM32之HAL库GPIO宏定义封装(最新版)
  2. Clion开发stm32之微妙延迟(采用nop指令实现)
  3. 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;
    else
        f_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;
    else
        f_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;
    else
        dat = 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;
    else
        pulse_time = 0;

    /* 存在脉冲到来,且存在的时间不能超过240us */
    while (!conf_ptr->read_data() && pulse_time < 240) {
        pulse_time++;
        conf_ptr->us_delay(1);
    }
    if (pulse_time >= 240)
        return false;
    else
        return 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

结果

在这里插入图片描述

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

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

相关文章

Kafka入门到起飞系列 - 副本机制,什么是副本因子呢?

我们一直在讲一个主题会有多个分区&#xff0c;这多个分区可以分布在一台服务器上&#xff0c;也可以分布在多台服务器上&#xff0c;还可以增加分区&#xff08;Kafka目前只支持分区&#xff09;&#xff0c;这是Kafka提供的一种横向扩展的手段 比如我们创建了一个主题&#x…

Scala项目找不到或无法加载主类

目录 1&#xff0c;出错背景2&#xff0c;分析与解决 1&#xff0c;出错背景 Scala项目无法创建scale和Java文件。项目没有报错&#xff0c;但执行时项目总是找不到项目下的类&#xff0c;报错信息如下所示&#xff1a; 错误: 找不到或无法加载主类 com.my.memTestCheck但该类…

第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面

文章目录 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面使用 HL7 架构结构页面查看文档类型列表查看消息结构查看段结构 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面 使用 HL7 架构结构页面 通过 HL7 架构页面&#xff0c;可以导入和查看 HL7 版本 2 架构规范。…

[PAT甲级] 1001 A+B Format [Python3]

题目描述&#xff1a; Calculate ab and output the sum in standard format -- that is, the digits must be separated into groups of three by commas (unless there are less than four digits). Input Specification: Each input file contains one test case. Each c…

【Hive实战】Hive的压缩池与锁

文章目录 Hive的压缩池池的分配策略自动分配手动分配隐式分配 池的等待超时Labeled worker pools 标记的工作线程&#xff08;自定义线程池&#xff09;Default pool 默认池Worker allocation 工作线程的分配 锁Turn Off ConcurrencyDebuggingConfigurationhive.support.concur…

超详细的74HC595应用指南(以stm32控制点阵屏为例子)

74HC595是一款常用的串行输入/并行输出&#xff08;Serial-in/Parallel-out&#xff09;移位寄存器芯片&#xff0c;在数字电子领域有着广泛的应用。它具有简单的接口和高效的扩展能力&#xff0c;成为了许多电子爱好者和工程师们的首选之一。本文将深入介绍74HC595芯片的功能、…

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识

019 - STM32学习笔记 - Fatfs文件系统&#xff08;一&#xff09; - FatFs文件系统初识 最近工作比较忙&#xff0c;没时间摸鱼学习&#xff0c;抽空学点就整理一点笔记。 1、文件系统 在之前学习Flash的时候&#xff0c;可以调用SPI_FLASH_BufferWrite函数&#xff0c;将数…

【Terraform学习】Terraform-AWS部署快速入门(快速入门)

Terraform-AWS部署快速入门 实验步骤 连接到 Terraform 环境 SSH 连接到Terraform 环境(名为MyEC2Instance的实例) 在 Amazon Web Services &#xff08;AWS&#xff09; 上预置 EC2 实例 用于描述 Terraform 中基础结构的文件集称为 Terraform 配置。您将编写一个配置来定义…

【视觉SLAM入门】5.1 非线性最小二乘理论 ------线搜索,信赖域,最速/牛顿下降法,高斯牛顿,LM等原理推导

"天之道也" 0. 引入1. 最速下降法2. 牛顿法3. (实用)G-N法4. (实用)L-M方法5. 总结 注意&#xff1a; 上一节得到的最小二乘问题&#xff0c;本节来讨论---- 求解非线性最小二乘问题 \color {red}求解非线性最小二乘问题 求解非线性最小二乘问题 0. 引入 求解这个简…

el-upload上传图片和视频,支持预览和删除

话不多说&#xff0c; 直接上代码&#xff1a; 视图层&#xff1a; <div class"contentDetail"><div class"contentItem"><div style"margin-top:5px;" class"label csAttachment">客服上传图片:</div><el…

【spring】spring bean的生命周期

spring bean的生命周期 文章目录 spring bean的生命周期简介一、bean的创建阶段二、bean的初始化阶段三、bean的销毁阶段四、spring bean的生命周期总述 简介 本文测试并且介绍了spring中bean的生命周期&#xff0c;如果只想知道结果可以跳到最后一部分直接查看。 一、bean的…

创建维基WIKI百科和建立百度百科有何不同?

很多企业有出口业务&#xff0c;想在互联网上开展全球性网络营销&#xff0c;维基百科往往被认为是开展海外营销的第一站。其作用相当于开展国内网络营销的百度百科&#xff0c;经常有些企业给小马识途营销顾问提供的词条内容就是百度百科的内容&#xff0c;可事实上两个平台的…

无人机影像配准并发布(共线方程)

无人机影像 DEM 计算四个角点坐标&#xff08;刚性变换&#xff09; 像空间坐标&#xff08;x,y,-f&#xff09; 像空间坐标畸变纠正 deltax,deltay 已知(x,y)&#xff0c;求解(X,Y, Z)或者(Lat,Lon) 这里的Z是DEM上获取的坐标和Zs为相机坐标的高程&#xff0c;如果均为已…

水文章——推荐一个视频播放器和一个图片查看器

视频播放器——PotPlayer http://www.potplayercn.com/ 图片查看器——JPEGVIEW https://www.bilibili.com/video/BV1ZY411P7fX/?spm_id_from333.337.search-card.all.click&vd_sourceab35b4ab4f3968642ce6c3f773f85138

PHP数组转对象和对象转数组

PHP数组转对象和对象转数组 <?php function array_to_object($arr){$obj new stdClass();foreach ($arr as $key > $val) {if (is_array($val) || is_object($val)) {$obj->$key array_to_object($val);} else {$obj->$key $val;}}return $obj; } function o…

pdf怎么转换成word 文档?这几种方法收藏一下

pdf怎么转换成word 文档&#xff1f;PDF和Word是我们平时工作和学习中最常用的两种文档格式。PDF文档格式通常用于电子书籍、合同、申请表等需要保持原样式的文档。而Word文档则通常用于编辑和修改。但是&#xff0c;有时我们需要将PDF文档转换为可编辑的Word文档&#xff0c;以…

【Docker】在Docker大火的背后,究竟隐藏着未来科技发展的哪些大趋势

这里写目录标题 在docker大火的背后是什么新科技的发展呢&#xff1f;1.容器化技术的普及2.云原生应用的兴起3.边缘计算的发展4.容器编排和管理平台的演进5.混合云和多云架构的普及 docker三大特性轻量化可移植性可扩展性 docker被谁抢了风头呢1.风头被Kubernetes (K8S)抢了2.缺…

日撸代码300行:第54天(基于 M-distance 的推荐)

代码来自闵老师”日撸 Java 三百行&#xff08;51-60天&#xff09;“&#xff0c;链接&#xff1a;日撸 Java 三百行&#xff08;51-60天&#xff0c;kNN 与 NB&#xff09;_闵帆的博客-CSDN博客 算法是基于M-distance的推荐&#xff0c;通过用户评分矩阵对用户进行电影推荐。…

如果你在选型低代码平台,可以从这5个角度去分析抉择

研究低代码平台已有3年&#xff0c;也算是个低代码资深用户了&#xff0c;很多企业面临低代码选型上的困难&#xff0c;选平台容易&#xff0c;换平台难。下面基于个人理解给大家做一份千字的注意事项&#xff01;希望对大家在选型低代码方面有一定帮助。最终&#xff0c;正确且…

[AWD靶场搭建]

文章目录 [AWD靶场搭建]前言AWD平台搭建靶机搭建Cadinal添加靶机 连接Asteroid大屏默认ssh账号密码参考 [AWD靶场搭建] 前言 觉得好玩搭建了一下AWD靶场&#xff0c;使用了vidar-team编写的 Cardinal AWD平台搭建 这里我是在kali搭建的&#xff0c;所以我下载了这个压缩包&…