STM32传感器外设集--温湿度模块(DHT11)
目录
原理图
介绍
main.c
bsp_dht11.h
bsp_dht11.c
core_delay.h
core_delay.c
原理图
介绍
DHT11是我们最常见的一种温湿度传感器,但是精度不是特别高,我这边直接借用野火官方例程
main.c
int main(void)
{DHT11_Data_TypeDef DHT11_Data;/* 初始化系统定时器 */SysTick_Init();USART_Config();//初始化串口1printf("\r\n***野火STM32 dht11 温湿度传感器实验***\r\n");/*初始化DTT11的引脚*/DHT11_Init ();while(1){ /*调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息*/if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS){printf("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",\DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);} else{printf("Read DHT11 ERROR!\r\n");}Delay_ms(2000);}}
bsp_dht11.h
#ifndef __DHT11_H
#define __DHT11_H#include "stm32f10x.h"/************************** DHT11 数据类型定义********************************/
typedef struct
{uint8_t humi_int; //湿度的整数部分uint8_t humi_deci; //湿度的小数部分uint8_t temp_int; //温度的整数部分uint8_t temp_deci; //温度的小数部分uint8_t check_sum; //校验和} DHT11_Data_TypeDef;/************************** DHT11 连接引脚定义********************************/
#define DHT11_Dout_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd
#define DHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOC#define DHT11_Dout_GPIO_PORT GPIOC
#define DHT11_Dout_GPIO_PIN GPIO_Pin_0/************************** DHT11 函数宏定义********************************/
#define DHT11_Dout_0 GPIO_ResetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN )
#define DHT11_Dout_1 GPIO_SetBits ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) #define DHT11_Dout_IN() GPIO_ReadInputDataBit ( DHT11_Dout_GPIO_PORT, DHT11_Dout_GPIO_PIN ) /************************** DHT11 函数声明 ********************************/
void DHT11_Init ( void );
uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data );;#endif /* __DHT11_H */
bsp_dht11.c
#include "./dht11/bsp_dht11.h"
#include "./dwt_delay/core_delay.h" static void DHT11_GPIO_Config ( void );
static void DHT11_Mode_IPU ( void );
static void DHT11_Mode_Out_PP ( void );
static uint8_t DHT11_ReadByte ( void );/* 可以在下面的宏定义中把后面的延时函数替换换SysTick的延时函数,就是想用那个就换成那个的 */#define DHT11_DELAY_US(us) CPU_TS_Tmr_Delay_US(us)
#define DHT11_DELAY_MS(ms) CPU_TS_Tmr_Delay_MS(ms)/*** @brief DHT11 初始化函数* @param 无* @retval 无*/
void DHT11_Init ( void )
{DHT11_GPIO_Config ();DHT11_Dout_1; // 拉高GPIOB10
}/** 函数名:DHT11_GPIO_Config* 描述 :配置DHT11用到的I/O口* 输入 :无* 输出 :无*/
static void DHT11_GPIO_Config ( void )
{ /*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure; /*开启DHT11_Dout_GPIO_PORT的外设时钟*/DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE ); /*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN; /*设置引脚模式为通用推挽输出*/GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure ); }/** 函数名:DHT11_Mode_IPU* 描述 :使DHT11-DATA引脚变为上拉输入模式* 输入 :无* 输出 :无*/
static void DHT11_Mode_IPU(void)
{GPIO_InitTypeDef GPIO_InitStructure;/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;/*设置引脚模式为浮空输入模式*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; /*调用库函数,初始化DHT11_Dout_GPIO_PORT*/GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure); }/** 函数名:DHT11_Mode_Out_PP* 描述 :使DHT11-DATA引脚变为推挽输出模式* 输入 :无* 输出 :无*/
static void DHT11_Mode_Out_PP(void)
{GPIO_InitTypeDef GPIO_InitStructure;/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/ GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN; /*设置引脚模式为通用推挽输出*/GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure); }/* * 从DHT11读取一个字节,MSB先行*/
static uint8_t DHT11_ReadByte ( void )
{uint8_t i, temp=0;for(i=0;i<8;i++) { /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ while(DHT11_Dout_IN()==Bit_RESET);/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 */DHT11_DELAY_US(40); //延时x us 这个延时需要大于数据0持续的时间即可 if(DHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */{/* 等待数据1的高电平结束 */while(DHT11_Dout_IN()==Bit_SET);temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 }else // x us后为低电平表示数据“0”{ temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行}}return temp;}/** 一次完整的数据传输为40bit,高位先出* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{ /*输出模式*/DHT11_Mode_Out_PP();/*主机拉低*/DHT11_Dout_0;/*延时18ms*/DHT11_DELAY_MS(18);/*总线拉高 主机延时30us*/DHT11_Dout_1; DHT11_DELAY_US(30); //延时30us/*主机设为输入 判断从机响应信号*/ DHT11_Mode_IPU();/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ if(DHT11_Dout_IN()==Bit_RESET) {/*轮询直到从机发出 的80us 低电平 响应信号结束*/ while(DHT11_Dout_IN()==Bit_RESET);/*轮询直到从机发出的 80us 高电平 标置信号结束*/while(DHT11_Dout_IN()==Bit_SET);/*开始接收数据*/ DHT11_Data->humi_int= DHT11_ReadByte();DHT11_Data->humi_deci= DHT11_ReadByte();DHT11_Data->temp_int= DHT11_ReadByte();DHT11_Data->temp_deci= DHT11_ReadByte();DHT11_Data->check_sum= DHT11_ReadByte();/*读取结束,引脚改为输出模式*/DHT11_Mode_Out_PP();/*主机拉高*/DHT11_Dout_1;/*检查读取的数据是否正确*/if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)return SUCCESS;else return ERROR;}elsereturn ERROR;}/*************************************END OF FILE******************************/
core_delay.h
#ifndef __CORE_DELAY_H
#define __CORE_DELAY_H#include "stm32f10x.h"#define USE_DWT_DELAY 1 /* 使用dwt内核精确延时 */#if USE_DWT_DELAY
#define USE_TICK_DELAY 0 /* 不使用SysTick延时 */
#else
#define USE_TICK_DELAY 1 /* 使用SysTick延时 */
#endif/*简单任务管理*/
#define TASK_ENABLE 0
#define NumOfTask 3#if USE_DWT_DELAY//#define Delay_ms(ms) CPU_TS_Tmr_Delay_MS(ms)
//#define Delay_us(us) CPU_TS_Tmr_Delay_US(us)
///* 最大延时 60s=2的32次方/72000000 */
//#define Delay_s(s) CPU_TS_Tmr_Delay_S(s)/* 获取内核时钟频率 */
#define GET_CPU_ClkFreq() (SystemCoreClock)
#define SysClockFreq (SystemCoreClock)
/* 为方便使用,在延时函数内部调用CPU_TS_TmrInit函数初始化时间戳寄存器,这样每次调用函数都会初始化一遍。把本宏值设置为0,然后在main函数刚运行时调用CPU_TS_TmrInit可避免每次都初始化 */ #define CPU_TS_INIT_IN_DELAY_FUNCTION 1/******************************************************************************** 函数声明******************************************************************************/
uint32_t CPU_TS_TmrRd(void);
void CPU_TS_TmrInit(void);//使用以下函数前必须先调用CPU_TS_TmrInit函数使能计数器,或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
//最大延时值为60秒
void CPU_TS_Tmr_Delay_US(uint32_t us);
#define CPU_TS_Tmr_Delay_MS(ms) CPU_TS_Tmr_Delay_US(ms*1000)
#define CPU_TS_Tmr_Delay_S(s) CPU_TS_Tmr_Delay_MS(s*1000)#endif#endif /* __CORE_DELAY_H */
core_delay.c
/************************************************************* @brief core_delay.c* @author jiejie* @github https://github.com/jiejieTop* @date 2018-xx-xx* @version v1.0* @note 使用内核寄存器精确延时***********************************************************/#include "./dwt_delay/core_delay.h" /*
**********************************************************************
* 时间戳相关寄存器定义
**********************************************************************
*/
/*在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace),该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,最长能记录的时间为:60s=2的32次方/72000000(假设内核频率为72M,内核跳一次的时间大概为1/72M=13.8ns)当CYCCNT溢出之后,会清0重新开始向上计数。使能CYCCNT计数的操作步骤:1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能2、使能CYCCNT寄存器之前,先清03、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能*/#if USE_DWT_DELAY#define DWT_CR *(__IO uint32_t *)0xE0001000
#define DWT_CYCCNT *(__IO uint32_t *)0xE0001004
#define DEM_CR *(__IO uint32_t *)0xE000EDFC#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR_CYCCNTENA (1 << 0)/*** @brief 初始化时间戳* @param 无* @retval 无* @note 使用延时函数前,必须调用本函数*/
void CPU_TS_TmrInit(void)
{/* 使能DWT外设 */DEM_CR |= (uint32_t)DEM_CR_TRCENA; /* DWT CYCCNT寄存器计数清0 */DWT_CYCCNT = (uint32_t)0u;/* 使能Cortex-M DWT CYCCNT寄存器 */DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
}/*** @brief 读取当前时间戳* @param 无* @retval 当前时间戳,即DWT_CYCCNT寄存器的值*/
uint32_t CPU_TS_TmrRd(void)
{ return ((uint32_t)DWT_CYCCNT);
}///**
// * @brief 读取当前时间戳
// * @param 无
// * @retval 当前时间戳,即DWT_CYCCNT寄存器的值
// * 此处给HAL库替换HAL_GetTick函数,用于os
// */
//uint32_t HAL_GetTick(void)
//{
// return ((uint32_t)DWT_CYCCNT*1000/SysClockFreq);
//}/*** @brief 采用CPU的内部计数实现精确延时,32位计数器* @param us : 延迟长度,单位1 us* @retval 无* @note 使用本函数前必须先调用CPU_TS_TmrInit函数使能计数器,或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION最大延时值为8秒,即8*1000*1000*/
void CPU_TS_Tmr_Delay_US(__IO uint32_t us)
{uint32_t ticks;uint32_t told,tnow,tcnt=0;/* 在函数内部初始化时间戳寄存器, */
#if (CPU_TS_INIT_IN_DELAY_FUNCTION) /* 初始化时间戳并清零 */CPU_TS_TmrInit();
#endifticks = us * (GET_CPU_ClkFreq() / 1000000); /* 需要的节拍数 */ tcnt = 0;told = (uint32_t)CPU_TS_TmrRd(); /* 刚进入时的计数器值 */while(1){tnow = (uint32_t)CPU_TS_TmrRd(); if(tnow != told){ /* 32位计数器是递增计数器 */ if(tnow > told){tcnt += tnow - told; }/* 重新装载 */else {tcnt += UINT32_MAX - told + tnow; } told = tnow;/*时间超过/等于要延迟的时间,则退出 */if(tcnt >= ticks)break;} }
}#endif/*********************************************END OF FILE**********************/
STM32传感器外设集--温湿度模块(DHT11)相关推荐
- STM32传感器外设集 -- 蓝牙(HC-05)+超声波(hc-sr04)
前言 前言:蓝牙外设还没有给大家安排上,今天我就给大家安排上使用蓝牙传输超声波距离的例程,会给大家附带蓝牙的上位机的测试APP 一.模块介绍 1.连接图 蓝牙模块 引脚 超声波传感器 引脚 GND G ...
- STM32传感器外设集--语音模块(SYN6288)
目录 图片 SYN6288.h SYN6288.c stm32f10x_it.h main.c 图片 如何使用该模块呢,首先,SYN6288是使用串口通讯的,很多模块其实都是使用串口通讯,有助于指令的 ...
- 温湿度模块 DHT11/12 芯片 协议解析 - 简单易懂协议详解
1.产品概述 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器.它应用专用的数字模块采集技术和温湿度传感技术,确保 产品具有极高的可靠性与卓越的长期稳定性.传感器包括一个电容式 ...
- 【STM32】DHT11温湿度模块传感器详解代码
一.DHT11产品介绍 DHT11是数字温湿度传感器,测量范围:湿度20%-95%,温度0-50℃,广泛应用于加湿器.温湿度计.空调.汽车等领域. 二.典型应用电路 如上图DATA引脚用于MCU与DH ...
- Esp8266 进阶之路19 【外设篇①】esp8266驱动 ds18b20、dht11 温湿度传感器,采集温湿度传感器到服务器。(附带Demo)
本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...
- 基于 STM32 的语音识别智能家居控制系统的设计(LD3320语音识别芯片+ESP8266 WIFI模块+DHT11温湿度采集+MQ系列 烟雾及可燃气体+蜂鸣器+步进电机模拟窗帘+OLED液晶显示+
## **基于 STM32 的语音识别智能家居控制系统的设计(LD3320语音识别芯片+ESP8266 WIFI模块(阿里云 或ONENET或局域网)+DHT11温湿度采集+MQ系列 烟雾及可燃气体+ ...
- STM32的 DHT11温湿度模块+红外人体感应模块程序
基于物联网的智能窗户Day3 DHT11温湿度模块 HC_SR501红外人体感应模块 结果展示 ending DHT11温湿度模块 传感器包括一个高分子电阻式感湿度元件和一个NTC测温元件,并于一个高 ...
- STM32读取SHT3x系列温湿度传感器,标准库和HAL库
STM32读取SHT3x系列(SHT30.SHT31.SHT35)温湿度传感器的数据并显示在0.96寸OLED屏上. 我下面提供两份代码,一份是标准库使用硬件I2C的,另一份是HAL库使用软件模拟II ...
- Mind+上传模式的第三方Arduino用户库实现 -DHT11温湿度模块
Mind+上传模式的第三方Arduino用户库实现--DHT11模块读取温湿度 前言 Mind+是一款拥有自主知识产权的国产青少年编程软件,支持Arduino.micro:bit.掌控板等各种开源硬件 ...
最新文章
- 百度AI“杀入”新领域,我举双手支持!
- SCM-SVN集成服务器
- winedt (latex 编译器)解决中文的问题(CJK CTEX)
- mysql语言是数据的行数据_自己总结的一些my sql数据库的知识,需要的可以看一看...
- 预实验结果与试剂配比
- 斐讯K2刷机加上桥接网络
- UEFI开发与调试---OVMF 固件简介
- java五子棋人机代码_Java五子棋AI实现代码
- 高中知识三角函数怎么计算机,高中三角函数怎么学 有什么方法
- 李宏毅2022机器学习hw4
- Windows如何进入安全模式
- 失控的摄像头,谁是窥视者!
- IC前端数字验证导学
- K8S中的pod、services、容器的概念和区别
- socket阻塞和非阻塞有哪些影响
- 如何查找sci期刊的历年影响因子
- 用Python串口实时显示数据并绘图pyqtgraph(详细教程)
- 千锋2018年最新php基础进阶加高级实战全套视频教程
- Cow Pinball
- 一种跳板机的实现思路