LCD1602与DHT11温湿度的使用
在下面编写过程中,学了模块化的编程思想,在后面的学习过程中更应该多使用模块化编写,不仅仅书写代码规范 效率执行也高。
一、理解LCD1602原理
1602液晶也叫1602字符型液晶,它能显示2行字符信息,每行又能显示16个字符,所以简称1602。它是一种专门用来显示字母、数字、符号的点阵型液晶模块
它是由若干个5x7或者5x10的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片。
VL是液晶显示偏压信号,当感觉屏幕过暗或过亮是可以调节此电压来调整亮度
RS是高电平是是数据选项,是低电平是命令选项
R/W 是高电平是读操作,是低电平是写操作
E是使能信号
D0 ~ D7是数据I/O口,单片机可以往传数据来让液晶显示不同的数据
BLA是背光源正极(A表示正),BLK是背光源负极(K表示负极),如果没背光数据是难以看清的
常用命令
输入命令是0x01
RS是低电平是输入的命令
R/W低电平表示写入
清除液晶显示器,即将 DDRAM 的内容全部填入"空白"的 ASCII码 20H;
清完屏光标归位,即将光标撤回液晶显示屏的左上方
将地址计数器(AC)的值设为 0,就是最走上角那个
二、DHT11温湿度的了解
简介
DHT11作为一款低价、入门级的温湿度传感器,常用于我们的单片机设计实例中;它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
DHT11为 4 针单排引脚封装,如下图,采用单线制串行接口,只需加适当的上拉电阻,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。
数据格式
8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
8位校验和
“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”相加所得结果的末8位。
控制时序
要实现对DHT11传感器的控制和数据的读取,需先学会分析DHT11的控制时序。时序主要分为三部分:1:触发DHT11采集数数据;2:读取数字0;3:读取数字1;。
(1)触发DHT11采集数据
总线空闲状态为高电平,单片机把总线拉低等待DHT11响应,单片机把总线拉低必须大于18ms,保证DHT11能检测到起始信号。
当DHT11接收到单片机的开始信号后,等待单片机开始信号结束,然后发送80us低电平响应信号。
单片机发送开始信号结束后,延时等待20-40us后,切换为输入状态,等待DHT11的80us低电平信号结束,然后判断DHT11是否是否发出 80us 的高电平;如果是,即可开始采集数据。
LCD1602头文件模块化
#ifndef _LCD1602_H_
#define _LCD1602_H_
typedef unsigned char u8;
typedef unsigned int u16;
void LCD_Delay1ms();//延时函数
void LCD_WriteCommand(u8 Command);//写指令函数
void LCD_WriteData(u8 Data);//写数据函数
void LCD_Init();//LCD初始化函数
void LCD_ShowChar(u8 Line ,u8 Columu,u8 Char);//显示当个字符
void LCD_ShowString(u8 Line ,u8 Columu,u8 *String); //显示字符串
void LCD_SetCursor(u8 Line ,u8 Columu);//设置字符显示位置
int LCD_Pow(int x,int y);//判断输入的数字是多少位
void LCD_ShowNum(u8 Line,u8 Columu,u16 Number,u8 Length); //显示数字
#endif
LCD1602函数代码
#include<REG51.H>
#include"LCD1602.h"
#include<INTRINS.H>
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0
void LCD_Delay1ms()//@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
//дָÁî µÍµçÆ½
void LCD_WriteCommand(u8 Command)
{
LCD_RS = 0; //设置指令模式
LCD_RW = 0; //写模式
LCD_DataPort = Command; //传入数据
LCD_E = 1;
LCD_Delay1ms();
LCD_E = 0;
LCD_Delay1ms();
}
//дÊý¾Ý
void LCD_WriteData(u8 Data)
{
LCD_RS = 1; //ÉèÖÃÖ¸Áîģʽ
LCD_RW = 0; //ÉèÖÃдģʽ
LCD_DataPort = Data; //дָÁî
LCD_E = 1;
LCD_Delay1ms();
LCD_E = 0;
LCD_Delay1ms() ;
}
//³õʼ»¯lcd
void LCD_Init()
{
LCD_WriteCommand(0x38); //配置八位数据接口
LCD_WriteCommand(0x0c); //显示开 光标关
LCD_WriteCommand(0x06); //光标加1 ,画面不动
LCD_WriteCommand(0x01); //清屏
}
//ÉèÖùâ±êº¯Êý
void LCD_SetCursor(u8 Line ,u8 Columu)
{
if(Line==1)
{
LCD_WriteCommand(0x80 |(Columu -1));
}
else
{
LCD_WriteCommand(0x80 |(Columu -1) + 0x40);
}
}
//ÏÔʾ×Ö·û
void LCD_ShowChar(u8 Line ,u8 Columu,u8 Char)
{
LCD_SetCursor(Line,Columu);
LCD_WriteData(Char);
}
//дÈë×Ö·û´®
void LCD_ShowString(u8 Line ,u8 Columu,u8 *String)
{
u8 i;
LCD_SetCursor(Line,Columu);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
//ÏÔʾ´Î·½º¯Êý
int LCD_Pow(int x,int y)
{
u8 i,result =1;
for(i=0;i<y;i++)
{
result *= x;
}
return result;
}
//ÏÔʾÊý×Öº¯Êý
void LCD_ShowNum(u8 Line,u8 Columu,u16 Number,u8 Length)
{
u8 i;
LCD_SetCursor(Line,Columu);
for(i=Length; i>0 ;i--)
{
LCD_WriteData('0'+Number/ LCD_Pow(10,i-1)%10);
}
}
DHT11头文件
#ifndef _DHT11_H_
#define _DHT11_H_
void DTH11_Delay_us(u8 n);
void DTH11_Delay_ms(u8 n);
void DTH11_START(); //起始信号
u8 DTH11_rec_Byte();//接受一个字节
void DTH11_rec_Temp_Data(); //接受温湿度数据
void InitUart(void); //使用定时器1,作为串口波特率
#endif
DHT11代码
#include<REG51.H>
#inlcude"DTH11.h"
sbit Temp_data = P3^6;
typedef unsigned char u8;
typedef unsigned int u16;
u8 rec_dat[4];
u8 rec_dat_lcd0[6];
u8 rec_dat_lcd1[6];
u8 rec_dat_lcd2[6];
u8 rec_dat_lcd3[6];
//ÑÓʱus
void DTH11_Delay_us(u8 n)
{
while(n--);
}
//延时函数
void DTH11_Delay_ms(u8 n)
{
u8 i,j;
for(i=0;i<n;i++)
{
for(j=0;j<110;j++);
}
}
//ÆðʼÐźÅ
void DTH11_START()
{
Temp_data = 1; //高电平先维持一小段时间
DTH11_Delay_us(2); //2us
Temp_data = 0; // 拉低
DTH11_Delay_ms(20); //至少18ms
Temp_data = 1;
DTH11_Delay_us(13);
}
//½ÓÊÜÒ»¸ö×Ö½Úº¯Êý
u8 DTH11_rec_Byte()
{
u8 i,Data;
for(i=0;i<8;i++)
{
while(!Temp_data); /等待低电平过去
DTH11_Delay_us(8); //延时8us 如果还是 高电平则为1
Data<<=1;
if(Temp_data==1)
{
Data+=1;
}
while(Temp_data); //等待拉低 准备下一位
}
return Data;
}
//接受温湿度数据
void DTH11_rec_Temp_Data()
{
u16 R_H,R_L,T_H,T_L;
u8 RH,RL,TH,TL,revise;
DTH11_START(); //主机发送信号
Temp_data = 1;
if(Temp_data == 0) //判断DHT11是否进入响应
{
while(Temp_data == 0); //等待低电平
DTH11_Delay_us(40); //µÈ´ý40us
R_H=DTH11_rec_Byte(); //接受湿度高八位
R_L=DTH11_rec_Byte(); //接受湿度低八位
T_H=DTH11_rec_Byte(); //接受温度高八位
T_L=DTH11_rec_Byte(); //接受温度低八位
revise =DTH11_rec_Byte(); //接受校验位
DTH11_Delay_us(25);
if(R_H+R_L+T_H+T_L ==revise)
{
RH = R_H;
RL = R_L;
TH = T_H;
TL = T_L;
}
rec_dat[0]=RH;
rec_dat[1]=RL;
rec_dat[2]=TH;
rec_dat[3]=TL;
}
}
void InitUart(void) //使用定时器1
{
SCON = 0x40; //串口通信方式1
REN = 1; //允许串口接受
TMOD = 0x20; //配置寄存器 定时器1
TH1 = 0xF3;
TL1 = 0xF3; //配置波特率
TI = 1;
TR1 = 1;
}
主函数
#include<REG51.H>
#include"LCD1602.h"
#include"DHT11.h"
#include"stdio.h"
extern u8 rec_dat[4];
extern u8 rec_dat_lcd0[6];
extern u8 rec_dat_lcd1[6];
extern u8 rec_dat_lcd2[6];
extern u8 rec_dat_lcd3[6];
void main()
{
DTH11_START();
LCD_Init();
LCD_ShowString(1,0,"Humi");
LCD_ShowString(2,1,"Temp£º");
while(1)
{
DTH11_Delay_ms(150);
DTH11_rec_Temp_Data();
sprintf(rec_dat_lcd0,"%d",rec_dat[0]);
sprintf(rec_dat_lcd1,"%d",rec_dat[1]);
sprintf(rec_dat_lcd2,"%d",rec_dat[2]);
sprintf(rec_dat_lcd3,"%d",rec_dat[3]);
DTH11_Delay_ms(150);
//显示湿度
LCD_ShowString(1,6,rec_dat_lcd0);
LCD_ShowString(1,8,".");
LCD_ShowString(1,9,rec_dat_lcd1);
LCD_ShowString(1,10,".");
//显示温度
LCD_ShowString(2,6,rec_dat_lcd2);
LCD_ShowString(2,8,".");
LCD_ShowString(2,9,rec_dat_lcd3);
LCD_ShowString(2,10,".");
}
}
上述只是记录自己的学习过程,有错的欢迎各位大佬指正 。