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

前言

涵盖之前文章:

  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

结果

在这里插入图片描述

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

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

相关文章

多线程(JavaEE初阶系列6)

目录 前言&#xff1a; 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语&#xff1a; 前言&#xff1a; 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下&#xff0c;那么这节中小编将分享一下多线程中的线程池。给大家讲解一…

CNN卷积详解

转载自&#xff1a;https://blog.csdn.net/yilulvxing/article/details/107452153 仅用于自己学习过程中经典文章讲解的记录&#xff0c;防止原文失效。 1&#xff1a;单通道卷积 以单通道卷积为例&#xff0c;输入为&#xff08;1,5,5&#xff09;&#xff0c;分别表示1个通道…

安防视频监控平台EasyCVR修改参数提示database or disk is full的原因排查

EasyDarwin开源流媒体视频EasyCVR安防监控平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、智能分析等能力。视频监控综合管理平台EasyCVR具备视频汇聚融合能力&#xff0c;平台基于云边端一体化架构&#xff0c;具有强大…

JDK各版本重要变革

各版本更新详情 JDK8(LTS)--2014/3 语法层面 lambda表达式(重要特色之一) 一种特殊的匿名内部类,语法更加简洁允许把函数作为一个方法的参数,将代码象数据一样传递&#xff0c;即将函数作为方法参数传递基本语法: <函数式接口> <变量名> (参数...) -> { 方法…

做虾皮你必须懂的五大流量运营逻辑!

一、竞品流量来源 商家排名一般有四个维度&#xff0c;弟一个维度是消量弟一&#xff0c;弟二个维度是销售额弟一&#xff0c;第三个维度是流量弟一&#xff0c;第四个维度利润弟一。只要我们找出来自我排名即可&#xff0c;然后打开生意参谋&#xff0c;到竞品分析添加成竞品…

【188】Java8利用AVL树实现Map

AVL树又被叫做平衡二叉搜索树、平衡二叉树。AVL是其发明者的首字母缩写。 这篇文章中&#xff0c;AVLTreeMap 类集成了 java.util.Map 接口&#xff0c;并利用 AVL 树结构实现了 Map 接口的所有方法。本文还给出了测试代码。 为什么要发明AVL树&#xff1f; 当我按照从小到大…

移动端商品分类左右联动

代码&#xff1a; <template><view class"u-wrap"><view class"u-menu-wrap"><scroll-view scroll-y scroll-with-animation class"u-tab-view menu-scroll-view" :scroll-top"scrollTop":scroll-into-view&quo…

uniapp uni-combox 下拉提示无匹配项(完美解决--附加源码解决方案及思路)

问题描述 匆匆忙忙又到了周一啦&#xff0c;一大早就来了一个头疼的问题&#xff0c;把我难得团团转&#xff0c;呜呜呜~ 下面我用代码的方式展示出来&#xff0c;看下你的代码是否与我的不同。 解决方案 <uni-forms-item label"名称" name"drugName&quo…

销存管理系统ssm进销存仓库销售java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 销存管理系统ssm 系统有1权限&#xff1a;管理员 二…

ClickHouse(六):Clickhouse数据类型-1

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…

flannel的三种常见模式分析

概述 大家接触flannel这种网络模式大多数可能都是从k8s中知道的&#xff0c;初始使用很少去深入了解它&#xff0c;毕竟使用它其实是很简单的。但是有时候会出现奇奇怪怪的网络问题&#xff0c;这个时候就需要我们更深入了解一下flannel这种网络模式。 Flannel是CoreOS开源的&…

学习C#编写上位机的基础知识和入门步骤:

00001. 掌握C#编程语言基础和.NET框架的使用。 00002. 学习WinForm窗体应用程序开发技术&#xff0c;包括控件的使用和事件驱动编程。 00003. 熟悉基本的数据结构和算法知识&#xff0c;如链表、栈、队列等。 00004. 理解串口通信协议和通信方法&#xff0c;用于与底层硬件设…

后端整理(集合框架、IO流、多线程)

1. 集合框架 Java集合类主要有两个根接口Collection和Map派生出来 Collection派生两个子接口 List List代表了有序可重复集合&#xff0c;可以直接根据元素的索引进行访问Set Set代表无序不可重复集合&#xff0c;只能根据元素本身进行访问 Map接口派生 Map代表的是存储key…

CS5265 USB-C to HDMI 4k@60Hz单转方案

CS5265AN是一款高性能Type-C/DP1.4至HDMI2.0b转换器芯片&#xff0c;集成了DP1.4兼容接收机和HDMI2.0b兼容发射机&#xff0c;还配备了CC控制器用于CC通信&#xff0c;实现DP Alt模式。DP接口包括4条主通道、辅助通道和HPD信号&#xff0c;接收器支持每通道最大5.4Gbps数据速率…

[自学记录05|百人计划]Early-Z和Z-Prepass

其实这篇我是不想写的&#xff0c;因为网上资料真的非常非常多很多人都写过&#xff0c;但是我后来想了想&#xff0c;做笔记不就是这样吗&#xff0c;所以就写吧~。前置知识&#xff1a;深度测试Z-Buffer[计算机图形学]可见性与遮挡,Z-Buffer(前瞻预习/复习回顾)__Yhisken的博…

小主机折腾记16

7月折腾了 1.2500s&#xff0c;2550k&#xff0c;e3 1225的性能测试 结果如下图 总结如下&#xff1a; a.2500s e3 1225 2390t 差别不大 b.1333频率相对1066频率内存提升12%左右 c.为什么少了2550k&#xff0c;因为装上去风扇尬转&#xff0c;没画面&#xff0c;我猜是因为…

2023年第四届“华数杯”数学建模思路 - 复盘:光照强度计算的优化模型

文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米&#xff0c;宽为12米&#xff0…

百度地图点标记加调用

先看效果 PHP代码 <?phpnamespace kds_addons\edata\controller;use think\addons\Controller; use think\Db;class Maps extends Controller {// 经纬度计算面积function calculate_area($points){$totalArea 0;$numPoints count($points);if ($numPoints > 2) {f…

第六章:SpringMVC上

第六章&#xff1a;SpringMVC上 6.1&#xff1a;SpringMVC简介 什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分。 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据。 一类称为实体类Bean&…

JavaEE初阶之网络初识

一、网络发展史 1.1独立模式 独立模式:计算机之间相互独立; 1.2网络互连 随着时代的发展,越来越需要计算机之间互相通信,共享软件和数据,即以多个计算机协同工作来完成业务,就有了网络互连。网络互连:将多台计算机连接在一起,完成数据共享。 数据共享本质是网络数据…