要求如下:
(1)用溫濕度模塊采集當前環境的溫度和濕度,并在LCD上顯示;
(2)用按鍵可以設定一個溫度范圍,當前溫度不在所設置的溫度范圍內時,LED閃動報警,當溫度在設定溫度范圍內時,停止報警;
(3)用按鍵可以設定一個濕度范圍,當前濕度不在所設置的濕度范圍內時,LED閃動報警,當濕度在設定濕度范圍內時,停止報警;
(4)LCD上能正確顯示當前溫度、濕度、設定溫度、設定濕度;
(5)顯示系統持續工作的時間,從系統上電開始計時,到目前為止,總共運行了多少時間,格式為“HH:MM:SS”。
完成情況:
(1)LCD上顯示--------完成
(2)設定溫濕度范圍---完成(k1:界面切換 k2:數值加 k3:數值減)
(3)顯示持續時間-----完成
LCD1602.h
#include "reg51.h"
#ifndef __LCD1602_H_
#define __LCD1602_H_
#define LCD1602_DATAPINS P0
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DATA=P2^0; //定義數據線
sbit LCD1602_RS=P2^6; //定義rs端口
sbit LCD1602_RW=P2^5; //定義rw端口
sbit LCD1602_E=P2^7; //定義en端口
void LcdWriteCom(uchar com);
void LcdWriteData(uchar dat);
void LcdInit();
#endif
LCD1602.c
#include "led1602.h"
/*******************************************************************************
* 函 數 名 : Lcd1602_Delay1ms
* 函數功能 : 延時函數,延時1ms
* 輸 入 : c
* 輸 出 : 無
* 說 名 : 該函數是在12MHZ晶振下,12分頻單片機的延時。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //誤差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 數 名 : LcdWriteCom
* 函數功能 : 向LCD寫入一個字節的命令
* 輸 入 : com
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS //當沒有定義這個LCD1602_4PINS時
void LcdWriteCom(uchar com) //寫入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //選擇發送命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待數據穩定
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5); //保持時間
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //寫入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //選擇寫入命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //發送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名 : LcdWriteData
* 函數功能 : 向LCD寫入一個字節的數據
* 輸 入 : dat
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //寫入數據
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇輸入數據
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //寫入數據
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5); //保持時間
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //寫入數據
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇寫入數據
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //寫入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名 : LcdInit()
* 函數功能 : 初始化LCD屏
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //開顯示
LcdWriteCom(0x0c); //開顯示不顯示光標
LcdWriteCom(0x06); //寫一個指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設置數據指針起點
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //將8位總線轉為4位總線
LcdWriteCom(0x28); //在四位線下的初始化
LcdWriteCom(0x0c); //開顯示不顯示光標
LcdWriteCom(0x06); //寫一個指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設置數據指針起點
}
#endif
main.c
/********************************************************************************************************/
#include<reg51.h>
#include<intrins.h>
#include<led1602.h>
#define uchar unsigned char //無符號字符型類型數據
#define uint unsigned int //無符號整型數據
sbit led=P2^2;
sbit k1=P3^1;
sbit k2=P3^2;
sbit k3=P3^3;
uchar dat_r[4]; //用于存放從DHT11讀取到的數值
uchar num[]="0123456789";
uchar Disp[]="RTHC%·";
uint i,j,k;
uchar hrh=80,lrh=40,hth=20,lth=5;
uchar c[8];
uchar b[8],shi,fen,miao;
uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
void Timer0Init();
/*********************************************************************************************
函數名:延時函數
調 用:Delay30us();/Delay20ms();/Delay1s();
參 數:無
返回值:無
結 果:延時相應時間
備 注:振蕩晶體為11.0592MHz(所有延時函數Copy自STC-ISP(v6.85).exe)
**********************************************************************************************/
void delay(uint i)
{
while(i--);
}
void Delay30us() //@11.0592MHz-40
{
unsigned char i;
i = 11;
while (--i);
}
void Delay20ms() //@11.0592MHz
{
unsigned char i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
void Delay1s() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*********************************************************************************************
函數名:DHT11啟動函數
結 果:DHT11開始工作
**********************************************************************************************/
void DHT11_start() // 主機控制DHT11開始工作
{
DATA=1; // 主線空閑狀態
_nop_();
_nop_();
DATA=0; // 主機發送開始工作信號
Delay20ms(); //延時18ms以上
DATA=1; // 拉高并延時等待DHT11響應
Delay30us();
}
/*********************************************************************************************
函數名:DHT11讀數據函數
調 用:? = DHT11_rec_byte();
參 數:無
返回值:
結 果:讀DHT11數據并保存到dat
備 注:
**********************************************************************************************/
uchar DHT11_rec_byte() //接收一個字節
{
uchar i,dat=0;
for(i=0;i<8;i++) //從高到低依次接收8位數據
{
while(!DATA); ////等待50us低電平過去
Delay30us();
Delay30us(); //延時60us,如果還為高則數據為1,否則為0
dat<<=1; //左移位使正確接收8位數據,數據為0時直接移位
if(DATA==1) //數據為1時,使dat加1來接收數據1
dat+=1;
while(DATA); //等待數據線拉低
}
return dat;
}
/*********************************************************************************************
函數名:接收DHT11的40位的數據并校驗
調 用:? = DHT11_receive();
參 數:無
返回值:無
結 果:結果保存到dat_r[ i]中
備 注:
**********************************************************************************************/
void DHT11_receive() //接收40位的數據
{
DHT11_start(); // 主機控制DHT11開始工作
if(DATA==0)
{
while(DATA==0); //等待拉高
Delay30us();
Delay30us();
Delay30us(); //拉高后延時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(); //接收校正位
Delay30us(); //結束
if((R_H+R_L+T_H+T_L)==revise) //校正
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
}
/*數據處理,方便顯示*/
dat_r[0]='0'+(RH/10);
dat_r[1]='0'+(RH%10);
dat_r[2]='0'+(TH/10);
dat_r[3]='0'+(TH%10);
}
}
void Timer0Init()
{
TMOD|=0X01;//選擇為定時器0模式,工作方式1,僅用TR0打開啟動。
TH0=0Xd8; //給定時器賦初值,定時10ms
TL0=0Xf0;
TR0=1;//打開定時器
}
void timepros()
{
b[0]=num[shi/10];
b[1]=num[shi%10];
b[2]=0x3a;
b[3]=num[fen/10];
b[4]=num[fen%10];
b[5]=0x3a;
b[6]=num[miao/10];
b[7]=num[miao%10];
}
void secondtimepros()
{
c[0]=num[lrh/10];
c[1]=num[lrh%10];
c[2]=num[hrh/10];
c[3]=num[hrh%10];
c[4]=num[lth/10];
c[5]=num[lth%10];
c[6]=num[hth/10];
c[7]=num[hth%10];
}
void keyprosA()
{
if(k1==0) //檢測按鍵 K1 是否按下
{
delay(1000); //消除抖動 一般大約 10ms
if(k1==0) //再次判斷按鍵是否按下
{
i++; //led 狀態取反
LcdWriteCom(0x01);
}
while(!k1); //檢測按鍵是否松開
}
}
void keyprosB()
{
if(k2==0) //檢測按鍵 K1 是否按下
{
delay(1000); //消除抖動 一般大約 10ms
if(k2==0) //再次判斷按鍵是否按下
{
j++; //led 狀態取反
LcdWriteCom(0x01);
}
while(!k2); //檢測按鍵是否松開
}
}
void keyprosC()
{
if(k3==0) //檢測按鍵 K1 是否按下
{
delay(1000); //消除抖動 一般大約 10ms
if(k3==0) //再次判斷按鍵是否按下
{
k++; //led 狀態取反
LcdWriteCom(0x01);
}
while(!k3); //檢測按鍵是否松開
}
}
/*********************************************************************************************
函數名:主函數
結 果:讀DHT11數據并送到1602顯示**********************************************************************************************/
void main (void)
{
static uint n;
Timer0Init();
LcdInit();
Delay1s(); //LCD初始化
while(1)
{
keyprosA();
keyprosB();
keyprosC();
if(TF0==1) //定時器T0溢出標志
{
TF0=0;
TH0=0Xd8; //給定時器賦初值,定時10ms
TL0=0Xf0;
n++;
}
if(n==100)
{
n=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==60)
{
shi=0;
miao=0;
fen=0;
}
}
}
if(i%5==0)
{
DHT11_receive();//接受數據
if(RH>hrh||RH<lrh||TH>hth||TH<lth)
{
led=~led;
}
else
{
led=1;
}
LcdWriteCom(0x80);//uchar Disp[]="RTHC%·";
LcdWriteData(Disp[0]);//R
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(dat_r[0]);
LcdWriteData(dat_r[1]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x08+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(dat_r[2]);
LcdWriteData(dat_r[3]);
LcdWriteData(Disp[3]);
timepros();
LcdWriteCom(0x44+0x80);
LcdWriteData(b[0]);
LcdWriteData(b[1]);
LcdWriteData(0X3a);
LcdWriteData(b[3]);
LcdWriteData(b[4]);
LcdWriteData(0X3a);
LcdWriteData(b[6]);
LcdWriteData(b[7]);
}
else if(i%5==1)
{
if(j!=0)
{
lrh=lrh+j;
j=0;
}
if(k!=0)
{
lrh=lrh-k;
k=0;
}
secondtimepros();
//首行
LcdWriteCom(0x80);//uchar Disp[]="RTHC%·";
LcdWriteData(Disp[0]);//R
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[0]);
LcdWriteData(c[1]);
LcdWriteData(Disp[4]);
LcdWriteData(0X2a);//<
LcdWriteCom(0x08+0x80);
LcdWriteData(Disp[0]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[2]);
LcdWriteData(c[3]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x40+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[4]);
LcdWriteData(c[5]);
LcdWriteData(Disp[3]);
LcdWriteCom(0x48+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[6]);
LcdWriteData(c[7]);
LcdWriteData(Disp[3]);
}
else if(i%5==2)
{
if(j!=0)
{
hrh=hrh+j;
j=0;
}
if(k!=0)
{
hrh=hrh-k;
k=0;
}
secondtimepros();
//首行
LcdWriteCom(0x80);//uchar Disp[]="RTHC%·";
LcdWriteData(Disp[0]);//R
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[0]);
LcdWriteData(c[1]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x08+0x80);
LcdWriteData(Disp[0]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[2]);
LcdWriteData(c[3]);
LcdWriteData(Disp[4]);
LcdWriteData(0X2a);//<
LcdWriteCom(0x40+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[4]);
LcdWriteData(c[5]);
LcdWriteData(Disp[3]);
LcdWriteCom(0x48+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X2a);//:
LcdWriteData(c[6]);
LcdWriteData(c[7]);
LcdWriteData(Disp[3]);
}
else if(i%5==3)
{
if(j!=0)
{
lth=lth+j;
j=0;
}
if(k!=0)
{
lth=lth-k;
k=0;
}
secondtimepros();
//首行
LcdWriteCom(0x80);//uchar Disp[]="RTHC%·";
LcdWriteData(Disp[0]);//R
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[0]);
LcdWriteData(c[1]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x08+0x80);
LcdWriteData(Disp[0]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[2]);
LcdWriteData(c[3]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x40+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[4]);
LcdWriteData(c[5]);
LcdWriteData(Disp[3]);
LcdWriteData(0X2a);//<
LcdWriteCom(0x48+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[6]);
LcdWriteData(c[7]);
LcdWriteData(Disp[3]);
}
else if(i%5==4)
{
if(j!=0)
{
hth=hth+j;
j=0;
}
if(k!=0)
{
hth=hth-k;
k=0;
}
secondtimepros();
//首行
LcdWriteCom(0x80);//uchar Disp[]="RTHC%·";
LcdWriteData(Disp[0]);//R
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[0]);
LcdWriteData(c[1]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x08+0x80);
LcdWriteData(Disp[0]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[2]);
LcdWriteData(c[3]);
LcdWriteData(Disp[4]);
LcdWriteCom(0x40+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[4]);
LcdWriteData(c[5]);
LcdWriteData(Disp[3]);
LcdWriteCom(0x48+0x80);
LcdWriteData(Disp[1]);//T
LcdWriteData(Disp[2]);//H
LcdWriteData(0X3a);//:
LcdWriteData(c[6]);
LcdWriteData(c[7]);
LcdWriteData(Disp[3]);
LcdWriteData(0X2a);//<
}
}
}
}
|