基于DHT11的温湿度显示

DHT11概述

特性

DHT11采用单总线式数字信号,一根数据线即可实时采集温湿度数据,模块配带专用的数字数据技术,具有极高的可靠性和稳定性。DHT11通过一根数据线即可实现与MCU间的通信,资源开销小,其时序通过数据总线延时调整。相关参数如下

参数///
供电电压3.3-5.5V DC
输出单总线数字信号
测量精度0.1℃

时序

DHT11温湿度采集模块配置时序极其重要,时序图如图 所示。MCU将总线拉低大于18ms,作为保证DHT11能检测到的最小时间,紧接着拉高电平并延时20us~40us,等待DHT11低电平响应,若返80us的低电平即证明DHT11接收正常,紧接着DHT11翻转电平80us,进入准备状态发送数据。当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
在这里插入图片描述

校验

DHT11数据包包含8位湿度整数+8位湿度小数+8为温度整数+8位温度小数+8位校验,且高位在前低位在后。当检验和等于温湿度各8位相加时,数据有效。

代码

#include "tim.h"
#include "dht11.h"

#define CPU_FREQUENCY_MHZ    8	//8M晶振,可修改,根据板子来
uint8_t Data[5];  

void Delay_us(__IO uint32_t delay)      //抵达延时
{
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}

void DHT_GPIO_SET_OUTPUT(void)           //向DHT11发送激活信号
{
	GPIO_InitTypeDef GPIO_InitStructure;    
	GPIO_InitStructure.Pin=GPIO_PIN_0;      
	GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;

	GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void DHT_GPIO_SET_INPUT(void)       //向MCU发送数据
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin=GPIO_PIN_0;
	GPIO_InitStructure.Mode=GPIO_MODE_INPUT;
	GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}


uint8_t DHT_Read_Byte(void)       //8位一组
{
	 uint8_t ReadData=0;  
	 uint8_t temp;      
	 uint8_t retry=0;  
	 uint8_t i;    
	 for(i=0; i<8; i++)   
	 {
			while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0 && retry<100)  
			//等待DHT应答
			{
					Delay_us(1);
				  retry++;             
			}
			retry=0;
			
			Delay_us(40);    
			if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==1)   temp=1;
			 else   temp=0;
			 while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==1 && retry<100)
       //等待一位采集完毕,即输出低电平
			 {
				 Delay_us(1);
				 retry++;
			 }
			 retry=0;
			 
			 ReadData<<=1;   
			 ReadData |= temp;        
	 }

		return ReadData;
}


uint8_t DHT_Read(void)  //40位数据
{
	 uint8_t retry=0;
	 uint8_t i;
		
	 DHT_GPIO_SET_OUTPUT();    
	 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);    //唤醒
	 HAL_Delay(18);
	 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);     //拉高等待
	 Delay_us(20);
	

	 DHT_GPIO_SET_INPUT();
	 Delay_us(20);
	 if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)       //低电平响应
	 {

		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0 && retry<100)  等待低电平响应结束
		{
		   Delay_us(1);
			 retry++;
		}
		retry=0;
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==1 && retry<100)   //高电平开始,唤醒响应结束,开始接收数据
		{
		   Delay_us(1);
			 retry++;
		}
		retry=0;

		for(i=0; i<5; i++)
		{
			 Data[i] = DHT_Read_Byte();  
//			printf("aa");
//			printf("\r\n");
		}
		Delay_us(50);
//	printf("Tem:%2d.%d",Data[2],Data[3]);
//	printf("\r\n");
//	printf("Hum:%2d.%d",Data[0],Data[1]);
//	printf("\r\n");
//	printf("Hello World!\r\n");
	}
	 
	 uint32_t sum=Data[0]+Data[1]+Data[2]+Data[3];     //校正
	 if((sum)==Data[4])    return 1;  
	   else   return 0;
}

LCD1602 IIC总线

由于LCD1602过多的占用IO口资源,故采用IIC转8位并口的PCF8574转接板作为扩展板。PCF8574无法通过8位控制LCD,而是采用4线通信模式,将8位拆分为高4位和低4位,分两次发送指令数据。

代码

#include "lcd1602.h"
#include "main.h"

extern I2C_HandleTypeDef hi2c1;  
#define SLAVE_ADDRESS_LCD  0x4E 

int number_pow(char  x,char y)   
{
	char i=0;
	int result=1;
	
	for(i=1;i<y;i++)
	result*=x;
	return result;
}

void lcd_send_cmd (char cmd){
	char data_u, data_l;
	uint8_t i2c_frame_data[4];
	data_u = (cmd&0xf0);
	data_l = ((cmd<<4)&0xf0);
	i2c_frame_data[0] = data_u|0x0C;  //en=1, rs=0
	i2c_frame_data[1] = data_u|0x08;  //en=0, rs=0
	i2c_frame_data[2] = data_l|0x0C;  //en=1, rs=0
	i2c_frame_data[3] = data_l|0x08;  //en=0, rs=0
	HAL_I2C_Master_Transmit(&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) i2c_frame_data, 4, 100);
	HAL_Delay(1);
}

void lcd_send_data (char data){
	char data_u, data_l;
	uint8_t i2c_frame_data[4];
	data_u = (data&0xf0);
	data_l = ((data<<4)&0xf0);
	i2c_frame_data[0] = data_u|0x0D;  //en=1, rs=0
	i2c_frame_data[1] = data_u|0x09;  //en=0, rs=0
	i2c_frame_data[2] = data_l|0x0D;  //en=1, rs=0
	i2c_frame_data[3] = data_l|0x09;  //en=0, rs=0
	HAL_I2C_Master_Transmit(&hi2c1, SLAVE_ADDRESS_LCD, (uint8_t *) i2c_frame_data, 4, 100);
	HAL_Delay(1);
}

void lcd_clear (void){
	lcd_send_cmd (0x01);  
	HAL_Delay(1);
}

void lcd_put_cur(int row, int col){
	switch(row){
	case 0:
		col |= 0x80;
		break;
	case 1:
		col |= 0xC0;
		break;
	}
	lcd_send_cmd(col);
}

void lcd_init (void){
//	HAL_Delay(50); 
//	lcd_send_cmd(0x30);
//	HAL_Delay(5); 
//	lcd_send_cmd(0x30);
//	HAL_Delay(1);
//	lcd_send_cmd(0x30);
//	HAL_Delay(10);
//	lcd_send_cmd(0x20); 
//	HAL_Delay(10);
	lcd_send_cmd(0x28); 
	HAL_Delay(1);
	lcd_send_cmd(0x28);
	HAL_Delay(1);
	lcd_send_cmd(0x28); 
	HAL_Delay(1);

	HAL_Delay(1);
	lcd_send_cmd(0x01); 
	HAL_Delay(1);
	lcd_send_cmd(0x06); 
	HAL_Delay(1);
	lcd_send_cmd(0x0E); 

	HAL_Delay(1);
}

void lcd_send_string (char *str){
    while(*str){lcd_send_data(*str++);}
	HAL_Delay(1);
}
void lcd_show(char x,char y,int num,int len,int flag)    
{
	char i=0;
	lcd_put_cur(x, y);
	for(i=len;i>0;i--)
	{
		if(flag)  
		{
			lcd_send_data('0'+num/number_pow(10,i-1)/10);
		}else lcd_send_data('0'+num/number_pow(10,i-1)%10);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kong sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值