TA的每日心情 | 怒 2023-7-25 22:49 |
---|
签到天数: 385 天 连续签到: 1 天 [LV.9]以坛为家II
|
1、DHT11介绍
DHT11是一款比较便宜的温湿度传感器模块。读取数据只需要占用一个IO口。能够同时测量温度和相对湿度。
2、接口说明
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻
3、电源引脚
DHT11的供电电压为 3-5.5V。传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。
4、串行接口(单纯双向)
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
5、驱动代码
dht11.h
/** **************************************************************************************** * * @file dht11.h * * @brief dht11传感器操作模块头文件 * * Copyright (C) sunsjw 2015 * * $Rev: 1.0 $ * **************************************************************************************** */#ifndef __DHT11_H#define __DHT11_H #include <stdint.h>//IO操作函数 #define PBout(n) BITBAND_REG(PTB->DOR,n)#define PBin(n) BITBAND_REG(PTB->DIR,n)#define DHT11_DQ_OUT PBout(0) //数据端口 PB0 #define DHT11_DQ_IN GPIO_ReadInputBit(GPIOC,GPIO_PIN_0) //数据端口 PB0#define DHT11_SETOUT GPIOC->CTLR1 = (GPIOC->CTLR1 & 0xFFFFFFF0 | 0x01)#define DHT11_SETIN GPIOC->CTLR1 = (GPIOC->CTLR1 & 0xFFFFFFF0 | 0x08)#define DHT11_HIGH GPIO_SetBits(GPIOC,GPIO_PIN_0)#define DHT11_LOW GPIO_ResetBits(GPIOC,GPIO_PIN_0)void DHT11_Init(void); //初始化DHT11uint16_t DHT11_Read_Data(void); //读取温湿度uint8_t DHT11_Read_Byte(void); //读出一个字节uint8_t DHT11_Read_Bit(void); //读出一个位uint8_t DHT11_Check(void); //检测是否存在DHT11void DHT11_Rst(void); //复位DHT11 #endifdht11.c
/** **************************************************************************************** * * @file dht11.c * * @brief dht11传感器操作模块文件 * * Copyright (C) sunsjw 2015 * * $Rev: 1.0 $ * **************************************************************************************** */#include "gd32f20x_gpio.h" // Keil:evice:StdPeriph Drivers:GPIO#include "dht11.h"#include "delay.h"/*! * @brief 复位DHT11 * * @param None * * @return None */void DHT11_Rst(void){ DHT11_SETOUT; DelayUs(1); DHT11_LOW; //拉低DQ DelayMs(20); //拉低至少18ms DHT11_HIGH; //DQ=1 DelayUs(30); //主机拉高20~40us }/*! * @brief 等待DHT11的回应 * * @param None * * @return 0:未检测到DHT11的存在,(低电平80us,高电平80us),1:存在 */uint8_t DHT11_Check(void){ uint8_t retry=0; DHT11_SETIN; //DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; DelayUs(1); }; if(retry>=100) return 0; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; DelayUs(1); }; if(retry>=100) return 0; return 1;}/*! * @brief 从DHT11读取一个位 (起始位50us低电平,26-28us高电平代表0,70us高电平代表1) * * @param None * * @return 1/0 */uint8_t DHT11_Read_Bit(void){ uint8_t retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; DelayUs(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; DelayUs(1); } DelayUs(35);//等待40us if(DHT11_DQ_IN) return 1; else return 0;}/*! * @brief 从DHT11读取一个字节 * * @param None * * @return 读到的数据 */uint8_t DHT11_Read_Byte(void){ uint8_t i,dat; DHT11_SETIN; dat=0; for (i=0; i<8; i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat;}/*! * @brief 从DHT11读取一次数据 * * @param None * @param[in,out] temp:温度值(范围:0~50°),humi:湿度值(范围:20%~90%) * @return 0:读取失败,非0值:高8位是温度值,低8位是湿度值 */uint16_t DHT11_Read_Data(){ uint8_t buf[5]; uint16_t result; uint8_t i; DHT11_Rst(); if(DHT11_Check()) { for(i=0; i<5; i++) //读取40位数据 { buf=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { result = buf[2]; result <<= 8; result |= buf[0]; } } else return 0; return result;}/*! * @brief 初始化DHT11的IO口 DQ 同时检测DHT11的存在 * * @param None * * @return None */void DHT11_Init(void){ GPIO_InitPara gpio_stru; /*初始化DHT11使用的GPIO*/ gpio_stru.GPIO_Mode = GPIO_MODE_OUT_PP; gpio_stru.GPIO_Pin = GPIO_PIN_0; gpio_stru.GPIO_Speed = GPIO_SPEED_10MHZ; GPIO_Init(GPIOC,&gpio_stru); GPIO_SetBits(GPIOC,GPIO_PIN_0); }主程序main.c
#include <stdio.h>#include "gd32f20x.h" // Device header#include "cmsis_os.h" // ARM::CMSIS:RTOS:Keil RTX#include "delay.h"#include "dht11.h"#include "oled.h"uint8_t showBuffer[32];void RCC_config(void);void GPIO_config(void);void SPI_config(void);void ShowDHT11(void);void thread_led(const void *arg){ uint16_t pin = (uint16_t)arg; for(;;) { if(GPIO_ReadOutputBit(GPIOD,pin)) GPIO_ResetBits(GPIOD,pin); else GPIO_SetBits(GPIOD,pin); osDelay(pin); }}void task_dht11(const void* arg){ for(;;) { ShowDHT11(); osDelay(1000); }}osThreadDef(thread_led,osPriorityNormal,3,0);osThreadDef(task_dht11,osPriorityHigh,1,0);int main(){ osKernelInitialize(); RCC_config(); GPIO_config(); SPI_config(); DelayInit(); DHT11_Init(); OLED_Init(); OLED_Clear(); GP2Y_init(); osThreadCreate(osThread(thread_led),(void*)GPIO_PIN_11); osThreadCreate(osThread(task_dht11),NULL); osKernelStart(); while(1) { osDelay(1000); }}void RCC_config(void){ RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOA|RCC_APB2PERIPH_GPIOD|RCC_APB2PERIPH_GPIOC,ENABLE); RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_SPI1,ENABLE); RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_ADC1,ENABLE); RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_USART2,ENABLE); RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_TIMER6,ENABLE); RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV6);}void GPIO_config(void){ /*初始化LED灯的GPIO*/ GPIO_InitPara gpio_stru; gpio_stru.GPIO_Mode = GPIO_MODE_OUT_PP; gpio_stru.GPIO_Speed = GPIO_SPEED_10MHZ; gpio_stru.GPIO_Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13; GPIO_Init(GPIOD,&gpio_stru);}void SPI_config(void){ SPI_InitPara spi_stru; spi_stru.SPI_FirstBit = SPI_FIRSTBIT_MSB; spi_stru.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT; spi_stru.SPI_Mode = SPI_MODE_MASTER; spi_stru.SPI_PSC = SPI_PSC_64; spi_stru.SPI_SCKPH = SPI_SCKPH_1EDGE; spi_stru.SPI_SCKPL = SPI_SCKPL_LOW; spi_stru.SPI_SWNSSEN = SPI_SWNSS_SOFT; spi_stru.SPI_TransType = SPI_TRANSTYPE_BDMTX; spi_stru.SPI_CRCPOL = 7; SPI_Init(SPI1,&spi_stru); SPI_CRC_Enable(SPI1,DISABLE); SPI_Enable(SPI1,ENABLE);}void ShowDHT11(void){ uint16_t data = DHT11_Read_Data(); sprintf((char*)showBuffer,":%3d",data>>8); OLED_ShowCHinese(0,2,6);//显示汉字温 OLED_ShowCHinese(16,2,8);//显示汉字度 OLED_ShowString(32,2,showBuffer); OLED_ShowCHinese(64,2,9);//显示℃ sprintf((char*)showBuffer,":%3d",data & 0xFF); OLED_ShowCHinese(0,4,7);//显示汉字温 OLED_ShowCHinese(16,4,8);//显示汉字度 OLED_ShowString(32,4,showBuffer); OLED_ShowCHinese(64,4,11);//显示%}实验效果:
热门推荐:
轻轻松松入门GD32F207开发板 |
|