IMG_20210401_105914.jpg (3.84 MB, 下載次數: 35)
下載附件
2021-4-1 14:13 上傳
單片機源程序如下:
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
//定義四個輸出端口
sbit Led_jiashi=P3^4; //加濕
sbit Led_qushi=P3^3; //去濕
sbit Led_jiangwen=P3^1; //降溫
sbit Led_shengwen=P3^2; //升溫
//定義三個設置按鍵
sbit Key_SET = P2^0;
sbit Key_ADD = P2^1;
sbit Key_SUB = P2^2;
sbit Key_OK = P2^3;
//定義24C02數據口
sbit SCL = P1^0;
sbit SDA = P1^1;
//定義DHT11數據口
sbit DATA = P1^7;
sbit buzz=P3^5;
//定義LCD1602端口
sbit E=P1^3; //1602使能引腳
//sbit RW=P2^6; //1602讀寫引腳
sbit RS=P1^2; //1602數據/命令選擇引腳
//定義全局變量
uchar U8FLAG,U8temp,U8comdata,U8RH_data_H_temp,U8RH_data_L_temp,U8T_data_H_temp,U8T_data_L_temp,U8checkdata_temp;
uchar U8RH_data_H,U8RH_data_L,U8T_data_H,U8T_data_L,U8checkdata;
uchar Mode,humidity,temperature;
char TH,TL,HH,HL;
bit bdata FlagStartRH,hot,cold,humid,dry,BJ;
//定時器0初始化
void Timer0_Init()
{
ET0 = 1; //允許定時器0中斷
TMOD = 0x11; //定時器工作方式選擇
TL0 = 0xFF;
TH0 = 0x4B; //定時器賦予初值
TR0 = 1; //啟動定時器
}
//定時器0中斷
void Timer0_ISR (void) interrupt 1 using 0
{
uchar RHCounter;
TL0 = 0xFF;
TH0 = 0x4B; //定時器賦予初值
RHCounter++;
if(RHCounter%10==0&&BJ==1)
buzz=!buzz;
else if(BJ==0)
buzz=1;
//每2秒鐘啟動一次溫濕度轉換
if (RHCounter >= 40)
{
FlagStartRH = 1;
RHCounter = 0;
}
}
/*********************************
BASE DRIVE
**********************************/
void DELAY(unsigned int t)
{
while(t!=0)
t--;
}
/******************************
IIC DRIVE
******************************/
void IICStart(void)
{
SCL=0;
DELAY(1);
SDA=1; SCL=1; DELAY(1);
SDA=0; DELAY(1);
SCL=0;
}
void IICStop(void)
{
SDA=0;SCL=1; DELAY(1);
SDA=1; DELAY(1);
SCL=0;
}
void SEND0(void)
{
SDA=0;
SCL=1;
DELAY(1);
SCL=0;
}
void SEND1(void)
{
SDA=1;
DELAY(1);
SCL=1;
DELAY(1);
SCL=0;
}
bit Check_Ack(void)
{
unsigned char errtime=250;
DELAY(1);
SCL=1;
DELAY(1);
CY=SDA;
while(CY)
{
errtime--;
CY=SDA;
if (!errtime)
{
IICStop();
return 1;
}
}
DELAY(1);
SCL=0;
return 0;
}
void Write_byte(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((dat<<i)&0x80)
SEND1();
else
SEND0();
}
}
unsigned char Read_byte(void)
{
unsigned char i,temp=0;
for(i=0;i<8;i++)
{
SDA=1;
SCL=1;
DELAY(1);
if(SDA==1)
{
temp=temp<<1;
temp=temp|0x01;
}
else
temp=temp<<1;
SCL=0;
}
return temp;
}
/************************************
EEPROM DRIVE
Addr:from 0x00-->
*************************************/
unsigned char rdeeprom(unsigned char addr)
{
unsigned char temp=0;
bit flag=0;
IICStart();
Write_byte(0xa0);
Check_Ack();
Write_byte(addr);
Check_Ack();
IICStart();
Write_byte(0xa1);
Check_Ack();
temp=Read_byte();
SEND1();
IICStop();
return temp;
}
void wrteeprom(unsigned char addr,unsigned char dat)
{
IICStart();
Write_byte(0xa0);
Check_Ack();
Write_byte(addr);
Check_Ack();
Write_byte(dat);
Check_Ack();
IICStop();
}
void Delay1(uint j)
{
uchar i;
for(;j>0;j--)
{
for(i=0;i<27;i++);
}
}
void Delay_10us(void)
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void COM(void)
{
uchar i;
for(i=0;i<8;i++)
{
U8FLAG=2;
while((!DATA)&&U8FLAG++);
Delay_10us();
Delay_10us();
Delay_10us();
U8temp=0;
if(DATA)U8temp=1;
U8FLAG=2;
while((DATA)&&U8FLAG++);
//超時則跳出for循環
if(U8FLAG==1)break;
//判斷數據位是0還是1
// 如果高電平高過預定0高電平值則數據位為 1
U8comdata<<=1;
U8comdata|=U8temp; //0
}//rof
}
//--------------------------------
//-----溫濕度讀取子程序 ------------
//--------------------------------
//----以下變量均為全局變量--------
//----溫度高8位== U8T_data_H------
//----溫度低8位== U8T_data_L------
//----濕度高8位== U8RH_data_H-----
//----濕度低8位== U8RH_data_L-----
//----校驗 8位 == U8checkdata-----
//----調用相關子程序如下----------
//---- Delay();, Delay_10us();,COM();
//--------------------------------
uchar RH(void)
{
//主機拉低18ms
DATA=0;
Delay1(180); //原來為5
DATA=1;
//總線由上拉電阻拉高 主機延時20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主機設為輸入 判斷從機響應信號
DATA=1;
//判斷從機是否有低電平響應信號 如不響應則跳出,響應則向下運行
if(!DATA) //T !
{
U8FLAG=2;
//判斷從機是否發出 80us 的低電平響應信號是否結束
while((!DATA)&&U8FLAG++);
U8FLAG=2;
//判斷從機是否發出 80us 的高電平,如發出則進入數據接收狀態
while((DATA)&&U8FLAG++);
//數據接收狀態
COM();
U8RH_data_H_temp=U8comdata;
COM();
U8RH_data_L_temp=U8comdata;
COM();
U8T_data_H_temp=U8comdata;
COM();
U8T_data_L_temp=U8comdata;
COM();
U8checkdata_temp=U8comdata;
DATA=1;
//數據校驗
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
if(U8temp==U8checkdata_temp)
{
U8RH_data_H=U8RH_data_H_temp;
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
}
return 1;
}
else //傳感器不響應
{
return 0;
}
}
/********************************************************************
* 文件名 : 液晶1602顯示.c
* 描述 : 該程序實現了對液晶1602的控制。
***********************************************************************/
/********************************************************************
* 名稱 : delay()
* 功能 : 延時,延時時間大概為140US。
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void delay()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++);
}
/********************************************************************
* 名稱 : enable(uchar del)
* 功能 : 1602命令函數
* 輸入 : 輸入的命令值
* 輸出 : 無
***********************************************************************/
void enable(uchar del)
{
P0 = del;
RS = 0;
E = 1;
delay();
E = 0;
delay();
}
/********************************************************************
* 名稱 : write(uchar del)
* 功能 : 1602寫數據函數
* 輸入 : 需要寫入1602的數據
* 輸出 : 無
***********************************************************************/
void write(uchar del)
{
P0 = del;
RS = 1;
E = 1;
delay();
E = 0;
delay();
}
/********************************************************************
* 名稱 : L1602_init()
* 功能 : 1602初始化,請參考1602的資料
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void L1602_init(void)
{
enable(0x38);
enable(0x0c);
enable(0x06);
enable(0x01); //清屏要放在最后
}
/********************************************************************
* 名稱 : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改變液晶中某位的值,如果要讓第一行,第五個字符顯示"b" ,調用該函數如下
L1602_char(1,5,'b')
* 輸入 : 行,列,需要輸入1602的數據
* 輸出 : 無
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
write(sign);
}
/********************************************************************
* 名稱 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改變液晶中某位的值,如果要讓第一行,第五個字符開始顯示"ab cd ef" ,調用該函數如下
L1602_string(1,5,"ab cd ef;")
* 輸入 : 行,列,需要輸入1602的數據
* 輸出 : 無
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
while(1)
{
if(*p == '\0') break;
write(*p);
p++;
}
}
//顯示整型的溫濕度數據用,共占用4位,其中一位符號位
void L1602_int(uchar hang, uchar lie, int num)
{
uint temp;
uint gewei,shiwei,baiwei,sign;
if (num >= 0)
sign = 0;
else
sign = 1;
temp = abs(num);
baiwei = temp / 100;
temp = temp - baiwei*100;
shiwei = temp / 10;
gewei = temp - shiwei*10;
num = abs(num);
if (num>=100)
{
// L1602_char(hang, lie+1, baiwei+48);
L1602_char(hang, lie+2, shiwei+48);
L1602_char(hang, lie+3, gewei+48);
}
else if (num>=10)
{
if (sign == 1)
L1602_char(hang, lie+1, '-');
L1602_char(hang, lie+2, shiwei+48);
L1602_char(hang, lie+3, gewei+48);
}
else
{
if (sign == 1)
L1602_char(hang, lie+2, '-');
else
L1602_char(hang, lie+2, ' ');
L1602_char(hang, lie+3, gewei+48);
}
}
void display()
{
if(Mode==0)
{
L1602_int(1,3,temperature);
L1602_char(1,7,0xdf);
L1602_int(1,12,humidity);
if(hot==1&&cold==0&&humid==0&&dry==0)
{L1602_string(2,1," It's very hot! ");BJ=1;}
else if(hot==1&&cold==0&&humid==1&&dry==0)
{L1602_string(2,1," Hot and humid! ");BJ=1;}
else if(hot==1&&cold==0&&humid==0&&dry==1)
{L1602_string(2,1," Hot and dry! ");BJ=1;}
else if(hot==0&&cold==1&&humid==0&&dry==0)
{L1602_string(2,1," It's very cold!");BJ=1;}
else if(hot==0&&cold==1&&humid==1&&dry==0)
{L1602_string(2,1," Cold and humid!");BJ=1;}
else if(hot==0&&cold==1&&humid==0&&dry==1)
{L1602_string(2,1," Cold and dry! ");BJ=1;}
else if(hot==0&&cold==0&&humid==1&&dry==0)
{L1602_string(2,1,"It's very humid!");BJ=1;}
else if(hot==0&&cold==0&&humid==0&&dry==1)
{L1602_string(2,1," It's very dry! ");BJ=1;}
else if(hot==0&&cold==0&&humid==0&&dry==0)
{L1602_string(2,1,"Good environment");BJ=0;}
}
}
/***按鍵函數***/
void KEY()
{
if(Key_SET==0)
{
Delay1(200);
if(Key_SET==0)
{
Mode++;
if(Mode==1)
{
L1602_string(1,1," TH: C HH: %");
L1602_char(1,8,0xdf);
L1602_string(2,1," TL: C HL: %");
L1602_char(2,8,0xdf);
L1602_int(1,4,TH);
L1602_int(1,12,HH);
L1602_int(2,4,TL);
L1602_int(2,12,HL);
enable(0x80+6);
enable(0x0f);
}
else if(Mode==2)
{
enable(0x80+0x40+6);
enable(0x0f);
}
else if(Mode==3)
{
enable(0x80+14);
enable(0x0f);
}
else if(Mode==4)
{
enable(0x80+0x40+14);
enable(0x0f);
}
else if(Mode>=5)
{
Mode=1;
enable(0x80+6);
enable(0x0f);
}
while(!Key_SET);
}
}
else if(Key_ADD==0)
{
Delay1(200);
if(Key_ADD==0)
{
if(Mode==1)
{
TH++;
if(TH>=100)
TH=99;
L1602_int(1,4,TH);
enable(0x80+6);
}
else if(Mode==2)
{
TL++;
if(TL>=TH)
TL=TH-1;
L1602_int(2,4,TL);
enable(0x80+0x40+6);
}
else if(Mode==3)
{
HH++;
if(HH>=100)
HH=99;
L1602_int(1,12,HH);
enable(0x80+14);
}
else if(Mode==4)
{
HL++;
if(HL>=HH)
HL=HH-1;
L1602_int(2,12,HL);
enable(0x80+0x40+14);
}
while(!Key_ADD);
}
}
else if(Key_SUB==0)
{
Delay1(200);
if(Key_SUB==0)
{
if(Mode==1)
{
TH--;
if(TH<=TL)
TH=TL+1;
L1602_int(1,4,TH);
enable(0x80+6);
}
else if(Mode==2)
{
TL--;
if(TL<=0)
TL=0;
L1602_int(2,4,TL);
enable(0x80+0x40+6);
}
else if(Mode==3)
{
HH--;
if(HH<=HL)
HH=HL+1;
L1602_int(1,12,HH);
enable(0x80+14);
}
else if(Mode==4)
{
HL--;
if(HL<=0)
HL=0;
L1602_int(2,12,HL);
enable(0x80+0x40+14);
}
while(!Key_SUB);
}
}
if(Key_OK==0&&Mode!=0)
{
Delay1(200);
if(Key_OK==0)
{
L1602_string(1,1,"Tem: C Hum: %");
L1602_string(2,1,"Good environment");
Mode=0;
wrteeprom(0,TH);
Delay1(20);
wrteeprom(1,TL);
Delay1(20);
wrteeprom(2,HH);
Delay1(20);
wrteeprom(3,HL);
enable(0x0c);
while(Key_OK==0);
}
}
}
//數據初始化
void Data_Init()
{
Led_qushi = 1;
Led_jiashi=1;
Led_jiangwen = 1;
Led_shengwen = 1;
}
/********************************************************************
* 名稱 : Main()
* 功能 : 主函數
***********************************************************************/
void main()
{
uint i, j, testnum;
EA = 0;
Timer0_Init();
Data_Init();
EA = 1;
L1602_init();
L1602_string(1,1," Welcome to T&H ");
L1602_string(2,1," Control System!");
for (i=0;i<1000;i++)
for (j=0;j<1000;j++)
{;}
L1602_string(1,1," ");
L1602_string(2,1," ");
L1602_string(1,1,"Tem: C Hum: %");
L1602_string(2,1,"Good environment");
TH=rdeeprom(0);
Delay1(20);
TL=rdeeprom(1);
Delay1(20);
HH=rdeeprom(2);
Delay1(20);
HL=rdeeprom(3);
while(1)
{
if (FlagStartRH == 1) //溫濕度轉換標志檢查
{
TR0 = 0;
testnum = RH();
FlagStartRH = 0;
TR0 = 1;
humidity = U8RH_data_H; //讀出溫濕度,只取整數部分
temperature = U8T_data_H;
if(Mode==0) //溫濕度控制
{
if (temperature > TH)
{
Led_jiangwen = 0;
hot=1;
Led_shengwen = 1;
cold=0;
// BJ=1;
}
else if(temperature<TL)
{
Led_shengwen = 0;
cold=1;
Led_jiangwen = 1;
hot=0;
buzz=0;
// BJ=1;
}
else
{
Led_jiangwen=1;
Led_shengwen=1;
hot=0;
cold=0;
buzz=1;
}
if (humidity > HH)
{
Led_qushi = 0;
humid=1;
Led_jiashi = 1;
dry=0;
// BJ=1;
}
else if(humidity<HL)
{
Led_jiashi = 0;
dry=1;
Led_qushi = 1;
humid=0;
// BJ=1;
}
else
{
Led_qushi=1;
Led_jiashi=1;
humid=0;
dry=0;
}
}
else
{
Led_shengwen=1;
Led_jiangwen=1;
Led_jiashi=1;
Led_qushi=1;
hot=0;
cold=0;
humid=0;
dry=0;
BJ=0;
}
}
display();
KEY();
}
}
|