STM32和DHT11使用显示温湿度度(代码理解)+单总线协议

news2024/11/24 17:42:16

基于STM32CT,利用DHT11采集温湿度数据,在OLED上显示。一定要阅读DHT11数据手册。

1、 DHT11温湿度传感器

引脚说明

1、VDD 供电3.3~5.5V DC
2、DATA 串行数据,单总线
3、NC 空脚
4、GND 接地,电源负极

硬件电路

微处理器与DHT11的连接典型应用电路如上图所示,DATA上拉后与微处理器的I/O端口相连。
1.典型应用电路中建议连接线长度短于5m时用4.7K上拉电阻,大于5m时根据实际情况降低上拉电
阻的阻值。
2. 使用3.3V电压供电时连接线尽量短,接线过长会导致传感器供电不足,造成测量偏差。
3. 每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取2次,但不建议连续多次
读取传感器,每次读取传感器间隔大于2秒即可获得准确的数据。

以上硬件部分来自于DHT11数据手册,为方便硬件部分DATA直接接STM32的IO口。
硬件部分接好线之后,需要知道单片机和 DHT11如何通信,即将数据传给单片机显示在OLED上。

2、单总线协议

DHT11与单片机之间通过简化的单总线协议通信

  • 单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。
  • 设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;
  • 单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从j结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。

重点理解下图的时序图就明白具体什么样,后续的代码也是基于这个图编写的协议。
在这里插入图片描述
上下两张图相同
在这里插入图片描述
过程分为主机(stm32)发送起始信号-从机(DHT11)发送响应信号-从机发送数据-从机发送结束信号

  • DHT11上电后,一直采集数据,DATA数据线由上拉电阻拉高(或者单片机IO口设置为高电平)一直保持高电平;此时 DHT11的 DATA 引脚处于输入状态,时刻检测外部信号。
  • 主机起始信号:单片机IO口为输出模式,输出低电平并保持一段时间,然后再回高电平也就是释放总线,另外IO口转为开漏输入模式。
  • 从机响应信号:DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束后,输出 一段时间的低电平作为应答信号,紧接着输出一段时间的高电平(也就是释放总线)通知单片机准备接收数据。
  • 输出40位数据: 湿度高8位 :湿度低8位: 温度高8位 : 温度低8位 : 校验位
    校验位 =湿度高8位 + 湿度低8位 +温度高8位 + 温度低8位 ,不正确则放弃重新接收数据。
    输出数据时:,位数据0的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据1的格式为: 54 微秒的低电平加68-74微秒的高电平。
  • 结束信号:数据输出完后,继续输出持续时间的低电平后转为输入状态,由于释放总线随之变为高电平。但DHT11内部重测环境温湿度数据,并记录数据,等待外部信号的到来。

该表来自DHT11数据手册,说明了起始信号、响应信号、发送数据0/1、结束信号中高低电平的持续时间,编写代码时也要参照这着表格和上面的时序图编写。
在这里插入图片描述

3、DHT11代码

DHT11.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
 
 
#define  DHT11_IO   GPIOB
#define  DHT11_Pin  GPIO_Pin_12
#define  DHT11_RCC  RCC_APB2Periph_GPIOB
  //设置IO输出
void DHT11_MOSI_Init(void)
{
    RCC_APB2PeriphClockCmd(DHT11_RCC,ENABLE);
 
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
    GPIO_InitStruct.GPIO_Pin=DHT11_Pin;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(DHT11_IO,&GPIO_InitStruct);
 
    GPIO_SetBits(DHT11_IO,DHT11_Pin);
 
}
  //设置IO为输入
void DHT11_MISO_Init(void)
{
    RCC_APB2PeriphClockCmd(DHT11_RCC,ENABLE);
 
    GPIO_InitTypeDef GPIO_InitStruct;
		//浮空输入,引脚电平来自外界
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
    GPIO_InitStruct.GPIO_Pin=DHT11_Pin;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(DHT11_IO,&GPIO_InitStruct);
 
}
 
 //单总线通信 开始
void DHT11_Start(void)
{
    DHT11_MOSI_Init();  //high
    GPIO_ResetBits(DHT11_IO,DHT11_Pin);//low 主机拉低总线18-30ms,然后释放
    Delay_ms(25);
    GPIO_SetBits(DHT11_IO,DHT11_Pin);  //high  释放
	
    Delay_us(13);  //保持高电平,等待从机响应     根据数据手册设置的主机释放总线的时间
    DHT11_MISO_Init();  //io为输入 等待从机
 
}
 // 接收数据,高位先行
uint8_t DHT11_ReceiveByte(void)
{
    uint8_t Byte=0x00;
    for(int i=0;i<8;i++)
    {
			//数据0:54us低电平+23-27高电平  数据1:54us低电平+68-74高电平
            while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==0);//等待低电平时间过去
            Delay_us(40);  //高电平持续时间超过40 说明数据为1
            if(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==1)  //读到为1,说明为高电平
            { 
                Byte|=(0x80>>i); //将数据位写入 Byte 中,从高位到低位  高位先行
                while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==1);//等待高电平结束
            }
            
 
    }
    return Byte;
 
}
//接收数据
//该函数每次读出的温湿度数值是上一次读取测量的结果 
char DHT11_GetData(uint8_t *Humi,uint8_t* Temp)
{
 
    char Mark='+'; //温度 零下还是零上
    uint8_t Humi_H,Humi_L,Temp_H,Temp_L,Check; //温湿度高低位、校验位
    
    DHT11_Start();//通信
 
    if(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==0)
    {
        while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==0);  //DHT11响应完毕
        while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==1);  // 准备接收高电平之后的数据
			  //湿度高8位    湿度低8位   温度高8位     温度低8位      校验位  传感器输出40位数据
       Humi_H=DHT11_ReceiveByte();                   
       Humi_L=DHT11_ReceiveByte();//等于0
       Temp_H=DHT11_ReceiveByte();
       Temp_L=DHT11_ReceiveByte();//温度低8位中的Bit8为1则表示负温度,否则为正温度,后7位为小数部分
       Check=DHT11_ReceiveByte();
 
       if(Humi_H+Humi_L+Temp_H+Temp_L==Check) //校验
       {
        *Humi=Humi_H; //传送数据
        *Temp=Temp_H;//小数部分不做处理
				
		//如果温度的低8位的最高位为1,表示温度为负数
        if((Temp_L&0x80)==0x80)
        {
            Mark='-';
        }
 
       }
		//DHT11继续输出低电平54微秒后转为输入状态,释放总线变为高电平。
        while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_Pin)==0);
        GPIO_SetBits(DHT11_IO,DHT11_Pin); //释放总线
    }
    return Mark;
}
//获取实时温湿度
//连续获取两次数据,DHT11模块会在上一次结束信号时重测温湿度数据
char DHT11_GetRealData(uint8_t *Humi,uint8_t* Temp)
{
    char Mark='+';
 
    DHT11_GetData(Humi,Temp);
    Delay_ms(1000);
    Delay_ms(1000);
    Delay_ms(100);          //数据手册规定读取传感器数据大于2s
    Mark=DHT11_GetData(Humi,Temp);
 
    return Mark;
 
}

DHT11.h

#ifndef __DTH11_H
#define __DTH11_H

//上电后等待1秒才调用函数
char DHT11_GetData(uint8_t *Humi,uint8_t* Temp);
char DHT11_GetRealData(uint8_t *Humi,uint8_t* Temp);//实时温湿度
void DHT11_Start(void);
#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "DTH11.H"

uint8_t Humi,Temp;
int main(void)
{
	OLED_Init();
	DHT11_Start();
	OLED_ShowString(1, 1, "Humi:");
	OLED_ShowString(2, 1, "Temp:");
	Delay_ms(1000);
	while (1)
	{
		DHT11_GetData(&Humi,&Temp);
		DHT11_GetRealData(&Humi,&Temp);
		OLED_ShowNum(1,6,Humi,2);
		OLED_ShowNum(2,6,Temp,2);
	}
}

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

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

相关文章

Git错误分析

错误案例1&#xff1a; 原因&#xff1a;TortoiseGit多次安装导致&#xff0c;会记录首次安装路径&#xff0c;若安装路径改变&#xff0c;需要配置最后安装的路径。

gitLab使用流程

标题1.配置账户 git config --global user.name git config --global user.email mygitlabmali.cn 标题2.生成秘匙 ssh-keygen -t rsa -C “mygitlabmail.cn” 。 //输入命令后一直回车 &#xff0c;输入命令后一直回车&#xff08;密码可以不填&#xff09;&#xff0c;至…

重载赋值运算符

c编译器可能会给类添加四个函数 1默认构造函数 2默认析构函数 3默认拷贝构造函数&#xff0c;对成员变量进行浅拷贝。 4默认赋值函数&#xff0c;队成员变量进行浅拷贝。 #include<iostream> using namespace std; class CGirl { public:int m_bh;string m_name;voi…

推荐3款Windows系统的神级软件,免费、轻量、绝对好用!

DiskView DiskView是一款用于管理和查看磁盘空间的工具&#xff0c;它集成了于微软的Windows操作系统资源管理器中&#xff0c;以显示直观的磁盘空间使用情况。该软件通过生成图形化地图&#xff0c;帮助用户组织和管理大量文件和文件夹&#xff0c;从而高效地管理磁盘空间。用…

SKM Power*Tools 10.0

SKM Power*Tools 10.0是功能强大的电气电力系统分析设计解决方案&#xff01;综合软件提供强大的功能和领先的技术&#xff0c;在检查、计算、负载分配、流量、瞬态稳定性等多个方面提供领先的支持&#xff0c;可对不同的安全设备、系统进行评估分析和比较&#xff0c;使用 Pow…

GoodTask for Mac:优雅高效的任务管理助手

在快节奏的工作生活中&#xff0c;你是否需要一个优雅且高效的任务管理工具来助你一臂之力&#xff1f;GoodTask for Mac正是你的理想选择&#xff01; GoodTask以其简洁直观的界面设计&#xff0c;让你一眼就能看清所有的待办事项。你可以轻松创建任务、设置提醒&#xff0c;…

证券交易系统中服务器监控系统功能设计

1.背景介绍 此服务器监控系统的目的在于提高行情服务器的监管效率&#xff0c;因目前的的行情服务器&#xff0c;包括DM、DT、DS配置数量较多&#xff0c;巡回维护耗时较多&#xff0c;当行情服务器出现异常故障&#xff0c;或者因为网络问题造成数据断线等情况时&#xff0c;监…

安乃达:看不懂的募资

不好玩啊&#xff0c;高标接连被S&#xff0c;市场激进资金找到了新股作为抱团方向。 首日大涨超100%&#xff0c;两日涨幅133%&#xff0c;今天果不其然被电风扇刮走了&#xff0c;今天我们聊聊新加入A股大本营的公司——安乃达。 首先&#xff0c;安乃达是国内直驱轮毂电机头…

秒验—手机号码置换接口

功能说明 提交客户端获取到的token、opToken等数据&#xff0c;验证后返回手机号码 服务端务必不要缓存DNS&#xff0c;否则可能影响服务高可用性 调用地址 POST https://identify-verify.dutils.com/auth/auth/sdkClientFreeLogin 请求头 Content-Type &#xff1a;appli…

字节码编程javassist之结合hotswap在运行期动态修改方法返回值

写在前面 本文看下如何通过javassist结合hotswap在运行期动态修改方法的返回值。 1&#xff1a;代码 要修改的代码 public class ApiTest {public String m1(String info) {return "info is: " info;} }javasssit代码 package com.dahuyou.javassist.huohuo;im…

十大排序:插入/希尔/选择/堆/冒泡/快速/归并/计数/基数/桶排序 汇总(C语言)

目录 前言非线性时间比较类插入排序(1) 直接插入排序(2) 希尔排序 选择排序(3) 选择排序优化版(4) 堆排序 交换排序(5) 冒泡排序(6) 快速排序hoare版本挖坑版前后指针版非递归版 归并排序(7) 归并排序递归版非递归版 线性时间比较类(8) 计数排序基数排序与桶排序 总结 前言 在计…

【C++】unordered系列容器的封装

你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 unordered系列的封装 1 unordered_map 和 unordered_set2 改造哈希桶2.1 模版参数2.2 加入迭代器 3 上层封装3.1 unordered_set3.2 unordered_map 4 面…

基于ssm口红商城管理的设计与实现

一、&#x1f468;‍&#x1f393;网站题目 口红商城项目可以提供更加便捷和高效的购物方式。消费者可以在家中使用电脑或手机随时随地购物&#xff0c;避免了传统购物方式中需要花费时间和精力去实体店铺购物的麻烦。此外&#xff0c;口红商城项目还提供了更多的选择和更低的…

Windows 与 Windows Server 2022环境下如何开启远程桌面

文章目录 前言Windows 环境下如何开启远程桌面控制功能Windows Server 环境下如何开启远程桌面 前言 我这边是客户需要搭建一套备份系统&#xff0c;整体的系统流程是这样的&#xff1a;客户的笔记本或者其他PC工具可以自由访问到我司搭建的服务器平台并进行文件传输&#xff…

【字符串】【滑动窗口+位运算+双指针】1、无重复字符的最长子串+2、尽可能使字符串相等+3、最长优雅子数组+4、移动零+5、反转字符串

2道简单3道中等 1、无重复字符的最长子串&#xff08;难度&#xff1a;中等&#xff09; 该题对应力扣网址 超时代码 老实说&#xff0c;在我写博客的时候&#xff0c;也不知道为啥超时了&#xff0c;因为我看和我AC的代码时间也差不了多少吧&#xff08;如果有大佬知道&…

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(二)增加基本的发起人审批与多用户多实例

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、AssigneeNode 增加approvalText public abstract class AssigneeNode extends Node {// 审批对象private AssigneeTypeEnum assigneeType;// 表单内人员private String formUser;// 表…

【最详细】PhotoScan(MetaShape)全流程教程

愿天下心诚士子&#xff0c;人人会PhotoScan&#xff01; 愿天下惊艳后辈&#xff0c;人人可剑开天门&#xff01; 本教程由CSDN用户CV_X.Wang撰写&#xff0c;所用数据均来自山东科技大学视觉测量研究团队&#xff0c;特此鸣谢&#xff01;盗版必究&#xff01; 一、引子 Ph…

Linux_共享内存通信

目录 1、共享内存原理 2、申请共享内存 2.1 ftok 2.2 测试shmget、ftok 2.3 查看系统下的共享内存 3、关联共享内存 3.1 测试shmat 4、释放共享内存 4.1 测试shmctl 5、实现共享内存通信 6、共享内存的特性 结语 前言&#xff1a; 在Linux下&#xff0c;有一…

【C++】日期类

鼠鼠实现了一个日期类&#xff0c;用来练习印证前几篇博客介绍的内容&#xff01;&#xff01; 目录 1.日期类的定义 2.得到某年某月的天数 3.检查日期是否合法 4.&#xff08;全缺省&#xff09;构造函数 5.拷贝构造函数 6.析构函数 7.赋值运算符重载 8.>运算符重…

【论文阅读】VASA-1: Lifelike Audio-Driven Talking FacesGenerated in Real Time

整体框架。不直接生成视频帧&#xff0c;而是在潜在空间中生成整体面部动态和头部运动&#xff0c;条件是音频和其他信号。给定这些运动潜在编码&#xff0c;通过面部解码器生成视频帧&#xff0c;还接受从输入图像中提取的外观和身份特征作为输入。 构建了一个面部潜在空间并…