接线:
代码:
main.c文件
/*
使用DHT11模块,检测温湿度,在lcd1602上面显示,因为1602显示不是每次都能出来,所以加了串口打印,会更加直观。
*/
#include
#include "lcd.h"
#include
#include
sbit Temp_data=P3^6; //信号引脚
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_delay_us(unsigned char n);
void DHT11_delay_ms(unsigned int z);
void DHT11_start();
unsigned char DHT11_rec_byte();
void DHT11_receive();
void InitUART(void);
//主函数
void main()
{
InitUART(); //串口中断初始化
P1=0xf0;
InitLcd1602();
LcdShowStr(0,0,"Shidu:");
LcdShowStr(0,1,"Wendu:");
while(1)
{
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(7,0,rec_dat_lcd0);
LcdShowStr(9,0,".");
LcdShowStr(10,0,rec_dat_lcd1);
LcdShowStr(11,0," %");
//温度
LcdShowStr(7,1,rec_dat_lcd2);
LcdShowStr(9,1,".");
LcdShowStr(10,1,rec_dat_lcd3);
LcdShowStr(11,1," C");
//下面通过串口助手打印温度
//我也为什么他不用中断服务函数,就可以打印,那好需要这个中断干嘛,不是可以直接打印吗?这是我的疑问。
printf("Humi:%d.%d \n",rec_dat[0],rec_dat[1]);
printf("Temp:%d.%d °C\n",rec_dat[2],rec_dat[3]);
}
}
//DHT11起始信号
void DHT11_start()
{
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;
}
}
//延时us --2*n+5us
void DHT11_delay_us(unsigned char n)
{
while(--n);
}
//延时ms
void DHT11_delay_ms(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
//使用定时器1作为串口波特率发生器
void InitUART(void)
{
TMOD=0x20; //定时器1的工作方式2
SCON=0x40; //串口通信工作方式1
REN=1; //允许接收
TH1=0xFD,TL1=0xFD; //波特率=9600
TI=1; //这里一定要注意
TR1=1;
EA = 1; //开总中断
}
Lcd.c文件
#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(0x06);
Lcd1602_Write_Cmd(0x01); //清屏
}
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--);
}
Lcd.h文件
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DB P0 //data bus 数据总线
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P2^7;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
//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
运行结果:
VID_20220410_172203