Proteus仿真电路图
LCD1602.C
#include "LCD1602.h"
/**********************************************
函数功能:LCD1602写命令函数
函数名称:void Lcd1602_Write_Cmd(unsigned char cmd)
**********************************************/
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;
}
/**********************************************
函数功能:LCD1602写数据函数
函数名称:void Lcd1602_Write_Data(unsigned char dat)
**********************************************/
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;
}
/**********************************************
函数功能:LCD1602字符显示坐标定位函数
函数名称:void LcdSetCursor(unsigned char x,unsigned char y)
**********************************************/
void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示(x,y),x:行数控制;y:列数控制;
{
unsigned char addr;
if(y == 0)
addr = 0x00 + x;//第一行开始,x表示一行的第x个
else
addr = 0x40 + x;//第二行开始,x表示一行的第x个
Lcd1602_Write_Cmd(addr|0x80);
}
/**********************************************
函数功能:LCD1602固定字符显示函数
函数名称:void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)
**********************************************/
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)
{
LcdSetCursor(x,y); //当前字符的坐标
while(*str != '\0') //如果字符串不是换行字符,则继续显示当前字符串。
{
Lcd1602_Write_Data(*str++);
}
}
/**********************************************
函数功能:系统上电后LCD1602的初始化
函数名称:void InitLcd1602()
**********************************************/
void InitLcd1602() //1602初始化
{
Lcd1602_Write_Cmd(0x38); //打开,5*8,8位数据
Lcd1602_Write_Cmd(0x0c);
Lcd1602_Write_Cmd(0x06);
Lcd1602_Write_Cmd(0x01); //清屏
}
/**********************************************
函数功能:实现若干个10毫秒的延时
函数名称:void LCD_Delay10ms(unsigned int c)
**********************************************/
void LCD_Delay10ms(unsigned int c) //误差 0us
{
unsigned char i, j;
for (;c>0;c--)
{
i = 20;
j = 113;
do
{
while (--j);
} while (--i);
}
}
void Read_Busy() //忙检测函数,判断bit7是0,允许执行;1禁止
{
unsigned char temp;
LCD1602_DB = 0XFF; // 十六进制:1111 1111
LCD1602_RS = 0; // 0 指令
LCD1602_RW = 1; // 1 读
do
{
LCD1602_EN = 1; // 拉高
temp = LCD1602_DB; // 将 LCD 状态保存在 temp 中,用于判忙
LCD1602_EN = 0; // 负跳变使能
}while(temp & 0x80); // 结果为 1,LCD 忙,继续循环;结果为 0,LCD 不忙,可以进行后面的操作
}
LCD1602.H
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include "reg52.h"
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
51单片机的I/O口定义
**********************************/
#define LCD1602_DB P0 //data bus 数据总线
sbit LCD1602_RS = P2^0;
sbit LCD1602_RW = P2^1;
sbit LCD1602_EN = P2^2;
/**********************************
函数声明
**********************************/
/**********************************
函数名称:void LCD_Delay10ms(unsigned int c);
函数功能:延时函数封闭调用
封闭函数依据:封闭前提为51单片机12MHz
**********************************/
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
DHT11.H
#ifndef _DHT11_H_
#define _DHT11_H_
#include <reg52.h>
#include "intrins.h"
#include "stdio.h"
sbit Temp_data = P1^0;
unsigned int rec_dat[4];
unsigned char rec_dat_lcd0[6];
unsigned char rec_dat_lcd1[6];
unsigned char rec_dat_lcd2[6];
unsigned char rec_dat_lcd3[6];
void DHT11_start(); //DHT11起始信号
unsigned char DHT11_rec_byte(); //接收一个字节
void DHT11_receive(); //接收温湿度数据
void DHT11_delay_us(unsigned char n); //延时us --2*n+5us
void DHT11_delay_ms(unsigned int z); //延时ms
#endif
DHT11.C
#include "intrins.h"
#include "DHT11.h"
void DHT11_start()//DHT11起始信号
{
Temp_data=1;
DHT11_delay_us(2);
Temp_data=0;
DHT11_delay_ms(20);
Temp_data=1;
DHT11_delay_us(13);
}
unsigned char DHT11_rec_byte()//接收一个字节
{
unsigned char i,dat;
for(i=0;i<8;i++)
{
while(!Temp_data);
DHT11_delay_us(8);
dat<<=1;
if(Temp_data==1)
{
dat+=1;
}
while(Temp_data);
}
return dat;
}
void DHT11_receive()//接收温湿度数据
{
unsigned int R_H,R_L,T_H,T_L;
unsigned char RH,RL,TH,TL,revise;
DHT11_start();
Temp_data=1;
if(Temp_data==0)
{
while(Temp_data==0); //等待拉高
DHT11_delay_us(40); //拉高后延时80us
R_H = DHT11_rec_byte(); //接收湿度高八位
R_L = DHT11_rec_byte(); //接收湿度低八位
T_H = DHT11_rec_byte(); //接收温度高八位
T_L = DHT11_rec_byte(); //接收温度低八位
revise = DHT11_rec_byte(); //接收校正位
DHT11_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 DHT11_delay_us(unsigned char n)//延时us --2*n+5us
{
unsigned int c;
for(c=2*n+5;c>0;c--)
{
_nop_();
}
}
void DHT11_delay_ms(unsigned int z)//延时ms
{
unsigned char i, j;
for(;z>0;z--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
main.c
#include "reg52.h"
#include "intrins.h"
#include "stdio.h"
#include "LCD1602.h"
#include "DHT11.h"
sfr AUXR=0X8E; //NOTES:sbit是位操作,用于将某个sfr中具体位赋值给一个变量
void Timer0Init(void); //1毫秒@11.0592MHz
void Show_Temperature_Humidity();
void Systeminitial();
//主函数
void main()
{
Systeminitial();
while(1);
}
//中断函数,每次定时器溢出进入中断,执行中断函数
void time0() interrupt 1
{
//将温湿度测试以及显示函数封闭处理,以提高中断函数的可读性
Show_Temperature_Humidity();
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;//打开总中断,打开定时器0中断
ET0=1;
}
void Systeminitial()
{
Timer0Init();//初始化定时器
InitLcd1602();
//显示固定字符串标识符
LcdShowStr(0,0,"Humid:");
LcdShowStr(0,1,"Tempt:");
}
void Show_Temperature_Humidity()
{
static unsigned int c=0;
c++;
if(c==25)
{
c=0;
//显示固定字符串标识符
LcdShowStr(0,0,"Humid:");
LcdShowStr(0,1,"Tempt:");
DHT11_delay_ms(150);
DHT11_receive();
//这个函数是打印字符函数,应该是起到数值转化的作用。
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]);
DHT11_delay_ms(100);
//湿度
LcdShowStr(6,0,rec_dat_lcd0);
LcdShowStr(8,0,".");
LcdShowStr(9,0,rec_dat_lcd1);
LcdShowStr(10,0,"%");
//温度
LcdShowStr(6,1,rec_dat_lcd2);
LcdShowStr(8,1,".");
LcdShowStr(9,1,rec_dat_lcd3);
LcdShowStr(10,1,"C");
}
}