基于51单片机的双通道DHT11温湿度显示器(LCD1602)

基于51单片机的双通道DHT11温湿度显示器(LCD1602)前言新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入前言这是单片机系统的课程大作业,做的有点仓促,代码其实也可以再优化一下,在这里抛砖引玉,希望能给大家带来一
摘要由CSDN通过智能技术生成

前言

这是单片机系统的课程大作业,做的有点仓促,代码其实也可以再优化一下,在这里抛砖引玉,希望能给大家带来一些思路。这也是第一次使用 Markdown编辑器 ,顺便学一下写作,淦,不说那么多废话了。

题目要求

本题目要求学生利用数字式温度和湿度采集环境信息采用I2C串口通讯技术返回单片机,并在LCD显示器实时显示,要求湿度误差不大于5%,温度误差不大于2摄氏度;要求能够显示二路的温度和湿度参数,在LCD屏幕上进行显示且刷新评率不低于0.5 Hz。系统组成包含有STC-89C52开发板,LCD1602显示屏,数字传感器DHT11。LCD显示要求可以同时显示两只传感器的任温度和湿度。

在这里插入图片描述

List item

实现的功能

前三个问题已经解决。按键切换不同状态时,后台仍在持续读取数据,最大值为开机以来的最大值,平均值为检测到近10次数据的平均值(51性能有限,其实是答主能力有限),次数过多单片机将无法显示正确数据。题目中提到使用IIC,但是答主咩用到,DHT11通过单总线通信,之后简单复制便实现了两路操作。

至于第四问,答主还没肝出来,如果在课程时间内能做出来就更新,不行的话就随缘啦~提供一个思路:LCD1602作为一个字符型LCD,没有画点函数,但内置8个自定义字符,是否可以通过自定义字符来显示曲线呢,大家有兴趣可以试一下。

  • 历次【版本优化】:
    21.10:00 添加外部中断按键消抖,优化部分代码,略微提高速度,可实现任务1.1要求
    解决了切屏后温度不实时更新的问题
    21.18:07 完成任务1.3
    21.22:00 1.2最大值部分调试成功
    22.09:26 1.2最大值可实现无缝记录,开机到显示的最大值一直有效。
    22.10:28 1.2单平均值串口测量成功
    22.11:16 1.2多平均值实时lcd、串口测量成功
    22.15:30 1.1显示实时值刷新率提高

思路介绍

本次实验中,首先是两路DHT11温湿度传感器,管脚分别接P2.0,P2.1。剩余两个管脚分别板子自带接VCC和GND。将外部中断P3.3与一个独立按键相连接。按要求插好LCD1602.工作时DHT11测量外界温度。将温度信息发送到STC-C52,STC-C52实时检测DHT11的在线状态,并使LCD1602实时显示.通过按键切换,显示两路DHT11温湿度传感器的离在线状态、实时温湿度、平均温湿度与最大温湿度。

开发板是在一块芯片中集成了CPU( 中央处理器)、RAM( 数据存储器)、ROM( 程序存储器)、定时器/ 计数器和多种功能的I/O( 输入/ 输出) 接口等一台计算机所需要的基本功能部件,从而可以完成复杂的运算、逻辑控制、通信等功能。
软件设计思路:软件程序的设计包括多个模块,包括LCD1602显示驱动模块、延时函数模块、温度模式切换显示模块中断服务函数模块两路DHT11温度检测模块、按键检测模块等。

代码部分

下面是大家喜闻乐见的代码部分

注意事项

在keil的codesize和memory model注意选择最大,否则程序可能烧不进去。
在这里插入图片描述

驱动部分

为了方便管理,我把按键和LCD驱动写了两个库文件,在实际使用中,按键扫描并没有用到,因为避免程序运行过慢,检测不到,选择使用外部中断来实现按键。

LCD1602驱动

先来个头文件:注意PIN口的定义,这里只是简单的驱动函数,大家在网上随便都能找到相似的。

#ifndef __LCD_H_
#define __LCD_H_

/**********************************
包含头文件
**********************************/
#include<reg52.h>


/**********************************
			PIN口定义
**********************************/
#define LCD1602_DB  P0     
sbit LCD1602_RS = P3^5;
sbit LCD1602_RW = P3^6;
sbit LCD1602_EN = P3^4;	 

//void Lcd1602_Delay1ms(uint c);   //误差 0usvo
void LCD_Delay10ms(unsigned int c);
//void Read_Busy();           //忙检测函数,判断bit7是0,允许执行;1禁止
void Lcd1602_Write_Cmd(unsigned char cmd);     //写命令
void Lcd1602_Write_Data(unsigned char dat);   //写数据
void LcdSetCursor(unsigned char x,unsigned char y);  //坐标显示
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);     //显示字符串
void InitLcd1602();              //1602初始化
					  
#endif

再来个C文件:只是简单的驱动函数,大家在网上随便都能找到相似的,也可以通过数据手册自己写。
这里有一个点,就是很多驱动都略写了LCD1602的读BUSY函数,具体原因求大佬告知。在这里为简化代码,我也忽略了。

#include <reg52.h>
#include "LCD.h"

void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令
{
   
    //Read_Busy();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
	LCD_Delay10ms(1);
    LCD1602_EN = 1;
	LCD_Delay10ms(1);
    LCD1602_EN = 0;    
}

void Lcd1602_Write_Data(unsigned char dat)   //写数据
{
   
      //Read_Busy();
      LCD1602_RS = 1;
      LCD1602_RW = 0;
      LCD1602_DB = dat;
	  LCD_Delay10ms(1);
      LCD1602_EN = 1;
	  LCD_Delay10ms(1);
      LCD1602_EN = 0;
}

//指定位置开始显示数据!
void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示
{
   
    unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;//第一行开始,x表示一行的第x个
    else
        addr = 0x40 + x;//第二行开始,x表示一行的第x个
    
    Lcd1602_Write_Cmd(addr|0x80);
}

void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串
{
   
    LcdSetCursor(x,y);      //当前字符的坐标
    while(*str != '\0')
    {
   
        Lcd1602_Write_Data(*str++);
    }
}

void InitLcd1602()              //1602初始化
{
   
    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据
    Lcd1602_Write_Cmd(0x0c);	//开显示,未添加光标闪烁
	Lcd1602_Write_Cmd(0x01);    //清屏   
	Lcd1602_Write_Cmd(0x06); 
   // Lcd1602_Write_Cmd(0x07);	//地址指针加一,右移
    
}

void LCD_Delay10ms(unsigned int c)   //误差 0us
{
   
    unsigned char a,b;
    for(;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}



按键驱动

没啥好说的,虽然写了,但其实我就没咋用到。。。。。。

头文件

#ifndef __KEY_H_
#define __KEY_H_

#include<reg52.h>

#define FOSC 11059200L
#define uint unsigned int
/**********************************
			PIN口定义
**********************************/  


sbit KEY    = P3^0;//独立按键S2
sbit KEY0   = P3^1;//独立按键S3
//sbit KEY    = P3^6;//上课用单片机
//sbit KEY0   = P3^5;




void KeyScanInd();//独立按键检测
void Keymode();  //模式切换
					 
#endif

C文件:没用到就注释了哈

#include <reg52.h>
#include "key.h"
#include "LCD.h"

//uint KeyValue=0;



//void KeyScanInd()
//{
   
//	KEY  = 1; //判断独立按键
//	KEY0 = 1; //判断独立按键
//	
//	if(KEY != 1)
//	{
   
//		Delayms(5);//软件消抖
//		if( KEY!= 1)
//		{
   
//			KeyValue++;
//			if(KeyValue==4) KeyValue=1;
//			while(KEY != 1);//松手检测	
//		}
//	}
//	
//	if(KEY0 != 1)
//	{
   
//		Delayms(5);//软件消抖
//		if( KEY0!= 1)
//		{
   
//			KeyValue--;
//			if(KeyValue==0) KeyValue=3;
//			while(KEY0 != 1);//松手检测	
//		}
//	}
//	
//}

//void Keymode()
//{
   
//	if(KeyValue==1)//当前值
//		{
   
//			LcdShowStr(0,0,"Present value!");
//			P1 = ~P1;
//		}
//	if(KeyValue==2)//平均值
//		{
   
//			LcdShowStr(0,0,"Average value!");
//			P1 = ~P1;
//		}
//	if(KeyValue==3)//最大值
//		{		
//			LcdShowStr(0,0,"Maximum value!");
//			P1 = ~P1;
//			
//		}		
//}



我使用到的按键是P3^3,通过外部中断1触发(不好意思忘更新了),这部分直接写到主要模块了。

//键盘函数中断版
void KeymodeINTER()
{
   
	switch(modeflag)
	{
   
		case 0:  displaySTATUS();
				 Lcd1602_Write_Cmd(0x01);  //清屏
		break;
		//当前值
		case 1: 			 
				displayNOW();  				 	         
				Lcd1602_Write_Cmd(0x01);    //清屏	
		break;
				 
		//平均值
		case 2:   				
				displayAVE();
				Lcd1602_Write_Cmd(0x01);    //清屏 
				 
		break;
		//最大值
		case 3:   
				 	         
				 displayMAX();	
				 Lcd1602_Write_Cmd(0x01);    //清屏	
		break;
		
		case 4:  
				 displayBight();	
				 Lcd1602_Write_Cmd(0x01);    //清屏	
		break;
		
		case 5:  
				 displayBight1();
				 modeflag = 0;	
				 Lcd1602_Write_Cmd(0x01);    //清屏	
		break;
	}	
}

主要模块

初始化

淦定义了好多变量,大家可以看一下代码的注释
这里有一点,在编写到最后,因为多定义两个数组,结果烧录进去程序就崩了,最后只好把一个二维数组改成一维的,放弃储存一些数据。

/*********************************************************************************
* 【编写时间】: 2021年3月22日
* 【作    者】: 手动打码,滑稽
* 【版    本】: 1.7
* 【编译环境】: Keil μVisio5	
* 【程序功能】: 			   			            			    
* 【版本更新】: 21.10:00 添加外部中断按键消抖,优化部分代码,略微提高速度,可实现功能1.1要求
				 解决了切屏后温度不实时更新的问题
				 21.18:07 完成任务1.3
				 21.22:00 1.2最大值部分调试成功
				 22.9:26   1.2最大值可实现无缝记录,开机到显示的最大值一直有效。
				 22.10:28  1.2单平均值串口测量成功
				 22.11:16  1.2多平均值实时lcd、串口测量成功
				 22.15:30  1.1显示实时值刷新率提高
* 【预期改动】:1.使用定时器0按键消抖,使用定时器1定时发送串口数据(可拓展为1.2平均值问题)--------失败
				2.不用数组储存数据,直接累加!!!解决问题1.2----------成功

**********************************************************************************/

#include <reg52.h>
#include <intrins.h>
#include <math.h>
#include <stdio.h>
#include "LCD.h"
#include
  • 24
    点赞
  • 115
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值