STM32+DHT11温湿度传感器

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度rn",dat[0],dat[2]);
     //printf("湿度:%d.%d%%,温度:%d.%d度rn",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

上结果图

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>