stm32项目之DHT11温湿度显示(LCD1602)

学习目标:

  • 掌握LCD1602的使用
  • 掌握DHT11的原理及使用

  • 学习内容:

    1. 看懂LCD1602和DHT11时序图
    2. 看懂DHT11的原理
    3. 掌握LCD1602的显示
    4. 编写程序用LCD1602显示温湿度

    DHT11部分:

    DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次

    通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数

    部分用于以后扩展,现读出为零.操作流程如下:

    一次完整的数据传输为40bit,高位先出。

    数据格式:8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据

    +8bit校验和

    数据传送正确时校验和数据等于“
    8bit湿度整数数据+8bit湿度小数数据

    +8bi温度整数数据+8bit温度小数数据”
    所得结果的末8位。

    通讯过程如图所示:

    说明:总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必
    须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后, 等待主机开始信号结束,然后80us低电平响应信号.主机发送开始信号结束 后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

    说明:总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。

     校验和 数据为前四个字节相加。
    传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。如果,某次从传感器中读取如下5Byte数据:

     由以上数据就可得到湿度和温度的值,计算方法:
    humi (湿度)= byte4 . byte3=45.0 (%RH)
    temp (温度)= byte2 . byte1=28.0 ( ℃)
    CHECK(校验)= R_H + R_L + T_H + T_L
    注意:DHT11一次通讯时间最大3ms,主机连续采样间隔建议不小于100ms。

    高电平的长短决定了数据位是0还是1.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.

    数字0信号表示方法:

     数字1信号表示方法:

     

    ——————————————————————————————————————-

    遇到的问题:为什么在显示数据时,总有一句write_com(0x80);等之类的语句?

    解:LCD1602的程序,每行16个显示字符,第一行地址从0x80~0x80+16,第二行0xc0+16;

    当我们想在指定位置写入数据时,要先指定地址,如在第一行第一位写入,地址位是00H,再加上DB7的1,即80H(0010000000),第二行第一位是40H,再加上DB7的1,即C0H(0011000000),依次类推。


    手册原话:DDRAM
    位址设置指令设置
    DDRAM
    位址指针,它将
    DDRAM
    存储显示字符的字符码的首地址 ADD6 ~ ADD0 送入 AC 中,于是显示字符的字符
    码就可以写入 DDRAM
    中或者从
    DDRAM
    中读出;值得注意的是:在 LCD
    显示屏一行显示方式下,
    DDRAM
    的位址范围为:

    00H ~ 4FH
    ;两行显示方式下,
    DDRAM
    的位址范围为:第一行
    00H ~ 27H

    第二行
    40H ~ 67H

     LCD1602时序:

    写操作时序图:

    读操作时序图:

     

    时序说明: 

    ———————————————————————————————————————————

    写相关代码:

    /******LCD1602写命令函数********/
    void write_com(unsigned char command)
    {
    //RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器
    	RS = 0;  
    	RW = 0; 	//高读低写
    	LCD = command;
    	delay5ms(); //这里延时最低要30纳秒 我们直接给5ms
    	E = 1;		//使能拉高 
    	delay5ms(); //最低要求延迟150纳秒 我们直接给5ms
    	E = 0;
    }
    
    /******LCD1602写数据函数********/
    void write_data(unsigned char dat)
    {
    //RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器
    	RS = 1;
    	RW = 0;
    	LCD = dat;
    	delay5ms(); //这里延时最低要30纳秒 我们直接给5ms
    	E = 1;		//使能拉高 
    	delay5ms(); //最低要求延迟150纳秒 我们直接给5ms
    	E = 0;
    }

    DHT11相关代码:

    sbit DATA = P2^0; //DHT11 数据引脚
    unsigned char ret;
    unsigned char DHTDATA[5] = {'\0'}; //存放40位 数据
    unsigned char code array[] = {"humi:"}; //湿度
    unsigned char code array1[] = {"temp:"}; //温度
    
    /*DHT11接收数据函数*/
    unsigned char DHT_receive_data()
    {
    	unsigned char i;
    	unsigned char dat=0;  //0000 0000
    
    		
    	for(i=0;i<8;i++)
    	{
    		while(!DATA); //等待DHT 50us低电平信号过去
    		delay30us(); //延时大概30us 如何还是高电平 则为1
    		
    
    		dat<<=1; //左移一位 因为数据是从高位开始传
    		if(DATA == 1)
    		{
    			dat|=0x01;
    		}
    /*		else
    		{
    			dat|=0x00;
    		}	 
    */
    		while(DATA); //等待DHT 拉低 准备下一位开始
    
    	}
    	return dat;
    	
    }
    
    
    /*DHT11读取函数*/
    void DHT_receive()
    {
    	unsigned char R_H,R_L,T_H,T_L,CHECK;
    	 //主机发送信号
    	DATA = 1;
    	delay30us();
    	DATA = 0;
    	delay20ms(); //延时大于18ms
    	DATA=1;
    	delay30us();	 //延时30us  20-40us 均可
    
    	DATA=1;
    	if(DATA == 0)   //判断DHT是否进入响应
    	{
    
    		while(!DATA);	   //等待从机80us低电平响应信号过去
    		while(DATA); //等待从机80us高电平信号过去
    
    	   	/*获取温湿度数据*/
    		R_H = DHT_receive_data();	//湿度高位
    		R_L = DHT_receive_data();
    		T_H = DHT_receive_data();
    		T_L = DHT_receive_data();
    
    		CHECK = DHT_receive_data();
    
    		DATA=0;
    		delay55us();
    		DATA=1;
    	
    		/*校验*/
    		if((R_H + R_L + T_H + T_L) == CHECK)
    		{
    			DHTDATA[0] = R_H;
    			DHTDATA[1] = R_L;
    			DHTDATA[2] = T_H;
    			DHTDATA[3] = T_L;
    
    			DHTDATA[4] = CHECK;	
    		}
    			
    	}
    }
    
    /*显示DHT11数据函数*/
    void DHT_display()
    {
    	write_com(0x85);
    	write_data(DHTDATA[0]/10 + 0x30);
    	write_com(0x86);
    	write_data(DHTDATA[0]%10 + 0x30);
    	write_com(0x87);
    	write_data('.');	
    	write_com(0x88);
    	write_data(DHTDATA[1]/10 + 0x30);
    	write_com(0x89);
    	write_data('%');
    	write_com(0xC5);
    	write_data(DHTDATA[2]/10 + 0x30);
    	write_com(0xC6);
    	write_data(DHTDATA[2]%10 + 0x30);
    	write_com(0xc7);
    	write_data('.');
    	write_com(0xC8);
    	write_data(DHTDATA[3]/10 + 0x30);
    	write_com(0xC9);
    	write_data(0xDF); //度
    	write_com(0xca);		
    	write_data('C');
    }

    main函数:

    /*主函数入口*/
    void main()
    {
    	unsigned char i;
    	init_lcd(); //初始化1602
    //1602的程序,每行16个显示单元,
    //第一行地址从0x80~0x80+16,第二行0xc0~0xc0+16
    	write_com(0x80);  //第一行第一个开始显示 humi:
    	for(i=0;i<5;i++)
    	{
    		write_data(array[i]);
    	}
    
    	write_com(0xc0);  //第二行第一个开始显示 temp:
    	for(i=0;i<5;i++)
    	{
    		write_data(array1[i]);
    	}
    
    	while(1)
    	{
    		delay1s(); //等待 1s 以越过不稳定状态
    		DHT_receive();   //DHT11读取函数
    		DHT_display();//1602显示温湿度
    					
    	}
    }

    物联沃分享整理
    物联沃-IOTWORD物联网 » stm32项目之DHT11温湿度显示(LCD1602)

    发表评论