DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次
通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数
部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到速模式,等待主
机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,
用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,
如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后
转换到低速模式.
直接上代码
//main程序
#include "stdio.h"
#include "stm32f10x.h"
#include "USART.h"
#include "dht11.h"
#include "Delay.h"
extern u8 dat[5];
int main(void)
{
uart1_init();
printf( "串口printf函数测试\n" );
while (1)
{
if(DHT_Read())
printf("湿度:%d%%,温度:%d度\r\n",dat[0],dat[2]);
//printf("湿度:%d.%d%%,温度:%d.%d度\r\n",dat[0],dat[1],dat[2],dat[3]); 显示小数
Delay_ms(3000);
}
}
//UART1.C程序
#include "stm32f10x.h" // Device header
#include "stdio.h"
#include "USART.h"
u8 Recse;
void uart1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_InitStructure.USART_BaudRate = 9600; //波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不进行硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//模式为接收和发送双向
USART_InitStructure.USART_Parity = USART_Parity_No;//不校验
USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止1位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据8位
USART_Init(USART1, &USART_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//输出复用推挽
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//输入复用浮空
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Cmd(USART1, ENABLE);//使能串口1
}
/* 重定向printf函数 */
int fputc(int ch, FILE *f)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1,ch);
/* 等待发送完毕 */
return ch;
}
//UART.H程序
#ifndef __USART_H
#define __USART_H
void uart1_init(void);
#endif
//dht11.c程序
#include "dht11.h"
#include "Delay.h"
uint8_t dat[5]={0x00,0x00,0x00,0x00,0x00};
uint8_t sum=0;
//初始化为输出
void DHT11_GPIO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//初始化为输入
void DHT11_GPIO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//读一个字节
uint8_t DHT_Read_Byte(void)
{
uint8_t temp;
uint8_t ReadDat=0;
uint8_t retry = 0;
uint8_t i;
for(i=0;i<8;i++)
{
//数据信号低电平50us
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0&&retry<100)
{
Delay_us(1);
retry++;
}
retry=0;
Delay_us(30);
temp=0;//数字信号0,temp=0
//数字0信号高电平持续28us,数字1信号高电平70us,延时30us以确认数字0或1
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==1) temp=1;
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==1&&retry<100)//数字1信号高电平剩余40us
{
Delay_us(1);
retry++;
}
retry=0;
ReadDat<<=1;
ReadDat|=temp;
}
return ReadDat;
}
uint8_t DHT_Read(void)
{
uint8_t i;
uint8_t retry = 0;
//主机设置为输出,发送开始信号低电平18ms,高电平40us
DHT11_GPIO_OUT();
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
Delay_ms(18);
GPIO_SetBits(GPIOB,GPIO_Pin_14);
Delay_us(40);
//主机设置为输入,检查并接收响应信号低电平80us,高电平80us
DHT11_GPIO_IN();
Delay_us(20);
//延时20us,低电平80us,还剩60us,检查是否是低电平以确定是否有响应信号
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
{
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0&&retry<100)//接收响应信号低电平剩余60us
{
Delay_us(1);
retry++;
}
retry=0;//超过100us自动向下运行,以免卡死
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==1&&retry<100)//接收响应信号高电平80us
{
Delay_us(1);
retry++;
}
retry=0;
//接收8字节数据
for(i=0;i<5;i++)
{
dat[i]=DHT_Read_Byte();
}
Delay_us(50);//DHT11拉低总线50us作为结束信号,或者使用以下语句
// while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0&&retry<100)//接收响应信号低电平剩余60us
// {
// SysTick_Delay_us(1);
// retry++;
// }
// retry=0;
}
sum=dat[0]+dat[1]+dat[2]+dat[3];
if(dat[4]==sum)
{
return 1;
}
else
return 0;
}
//dth11.h程序
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
void DHT11_GPIO_OUT(void);
void DHT11_GPIO_IN(void);
uint8_t DHT_Read_Byte(void);
uint8_t DHT_Read(void);
#endif
//Delay.c程序
#include "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
//Delay.h程序
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif
上结果图文章来源:https://www.toymoban.com/news/detail-411933.html
文章来源地址https://www.toymoban.com/news/detail-411933.html
到了这里,关于STM32+DHT11温湿度传感器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!