|
這個(gè)程序在分的很細(xì),可以看超聲部分或溫濕檢測部分程序。
程序如下:
#include <reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define Data P1 //LCD1602的數(shù)據(jù)口
#define NOP() {_nop_();_nop_();_nop_();_nop_();} //用于延時(shí)
//LCD1602控制引腳定義
//sbit RS = P2^6;
//sbit RW = P2^5;
//sbit E = P2^7;
sbit RS = P2^0; //復(fù)位端
sbit RW = P2^1; //寫數(shù)據(jù)端
sbit E = P2^2; //使能端
//溫濕DHT11的數(shù)據(jù)引腳定義
sbit DHT=P2^3;
//這些數(shù)組用于數(shù)據(jù)的緩存
uchar wendu_char[]=" temperature";//12 用于提示的字符
uchar shidu_char[]=" humidity";//10 用于提示的字符
uchar wendu[] ="wen:00.00 d";//11 數(shù)據(jù)格式,當(dāng)讀取的數(shù)據(jù)會(huì)保存到數(shù)組的相應(yīng)的位上
uchar shidu[]="shi:00.00 RH";//12 //同上一句
uchar table[]={" make ^!^ in "};//14 //用于提示
uchar table1[]={" 2013-12-20 "};//12 //用于提示
//uchar qingxu1[]={" ^!^ "};//11
//uchar qingxu2[]={"good weather"};//12
//uchar qingxu3[]={" -_-! "};//12
//uchar qingxu4[]={"bad weather!"};//12
unsigned char shiZ,shiX,wenZ,wenX,check; //用于存讀出傳感器的數(shù)據(jù),因?yàn)樽x出的是整型數(shù)據(jù),之后用于轉(zhuǎn)換成字符存于上面的數(shù)組中
unsigned char shiH,shiL,wenH,wenL; //
unsigned char flag; //定義一個(gè)標(biāo)志位
unsigned int n=20,m; //定義一些會(huì)在下面用到的全局變量
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void delay(uint a); //超聲波模塊和溫濕模塊的公用延時(shí)函數(shù)
void delay_10us() ;
void delay_1ms(unsigned int i) ;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//超聲波部分的函數(shù)
/////////////////////////////////////////////////////
sbit Tx=P3^3; //超聲波模塊發(fā)射脈沖的引腳定義
sbit Rx=P3^2; //超聲波模塊接收回波的引腳定義
uchar code table2[]={"Distance Test:"}; //14 //用于提示
uchar temp_dis[]= {"000.0 cm"};// 8 //用于顯示數(shù)據(jù)的緩沖數(shù)組
long int t;//讀出的數(shù)據(jù)現(xiàn)存于這些變量,再轉(zhuǎn)換成字符賦給上面的數(shù)組
double distance;
uchar cache[4]={0,0,0,0}; //用于裝入分離的數(shù)據(jù)的各個(gè)位
//外部中斷0用于計(jì)算超聲波模塊接收到回波的時(shí)間,用于計(jì)算距離
void init0() //外部中斷0在接收到Rx腳的高電平觸發(fā)定時(shí)器計(jì)時(shí),當(dāng)高電平回波結(jié)束時(shí)是下降沿
{//定時(shí)器0的初始化
TMOD=0x01;
TH0=0;
TL0=0;
//外部中0的初始化
EX0=1; //外部中斷的
IT0=1; //設(shè)置為低電平觸發(fā),下降沿有效
//打開總中斷
//EA=1;
}
//超聲波模塊初始化
void HC05_Init()
{ //依據(jù)模塊的資料,把發(fā)射腳拉高大于10us,再把發(fā)射腳拉低,模塊就會(huì)自動(dòng)發(fā)送探測的脈沖
EA=1;
Tx=1;
NOP();NOP();NOP();NOP(); //用于延時(shí),保持大于8us的要求
Tx=0; //發(fā)射腳拉低
while(!Rx); //當(dāng)RX為零時(shí)等待
TR0=1; //開啟計(jì)數(shù)
while(Rx); //當(dāng)RX為1計(jì)數(shù)并等待
TR0=0; //關(guān)閉計(jì)數(shù)
//TR0=1; //打開定時(shí)器0,以便從發(fā)送脈沖開始計(jì)時(shí),到接收到外部中斷0后關(guān)閉
distance=0.17*t; //計(jì)算距離的公式
// distance=(340*t)/2;
}
//數(shù)值轉(zhuǎn)換
void distance_convert(long int dat)
{
//把得到的數(shù)據(jù)分離出個(gè),十,百等位,裝入數(shù)組中
//0.17*t知道測量的值有兩個(gè)小數(shù)點(diǎn),且該超聲波模塊可以測量到幾百厘米,所以,得到的數(shù)據(jù)格式位000.00cm,
//我們要保留1為小數(shù),又因?yàn)閈,%的運(yùn)算為整數(shù),則先把數(shù)據(jù)乘以10,再求出各個(gè)對應(yīng)的位放到對應(yīng)的數(shù)組
//dat=dat*10;
cache[0]=dat/1000; //實(shí)際對應(yīng)原數(shù)據(jù)的百位,因?yàn)榘褦?shù)據(jù)*10處理了,向高位移了一位
cache[1]=dat/100;
cache[2]=dat/10;
cache[3]=dat; //
//裝入數(shù)組,加'0'是將整型的數(shù)據(jù)轉(zhuǎn)換成字符數(shù)據(jù)
temp_dis[0]=cache[0]+'0'; //數(shù)組的格式位uchar temp_dis[]= {"000.0 cm"};
temp_dis[1]=cache[1]+'0';
temp_dis[2]=cache[2]+'0';
temp_dis[4]=cache[3]+'0';
}
//溫度度部分的函數(shù)(DHT11)
////////////////////////////////////
//延時(shí)函數(shù)1ms
void delay_1ms(unsigned int i)
{
unsigned int j=88;
for(;i>0;i--)
{
while(j>0)j--;
}
}
//延時(shí)函數(shù)10us
void delay_10us()
{
unsigned char i;
i--;
i--;
i--;
i--;
i--;
i--;
}
//延時(shí)函數(shù)可調(diào)
void delay(uint a)
{
uint y;
for(;a>0;a--)
for(y=100;y>0;y--);
}
//讀取DHT11的數(shù)據(jù),其為單總線通訊,只用一條線,已經(jīng)定義為DHT,區(qū)別于I2C通訊
char read_data()
{
unsigned char i,num,temp;
num=0;
for(i=0;i<8;i++)
{
flag=2;
while((!DHT)&&flag++); //判斷從機(jī)是否發(fā)出80us的低電平相應(yīng)信號是否結(jié)束
delay_10us();
delay_10us();
delay_10us();
if(DHT==1)
{
temp=1;
flag=2;
while(DHT&&flag++);
} //超時(shí)則跳出
else
temp=0;
num<<=1; //一位一位的讀出存入變量num中
num|=temp;
}
return(num); //讀8個(gè)位的數(shù)據(jù),為一個(gè)字節(jié)
}
//讀取DHT11的40位數(shù)據(jù)函數(shù)//////////////////////////////////////////////////////////////////////////////
void read_init()
{
DHT=0; //主機(jī)拉低21ms
delay_1ms(21);
DHT=1; //總線由上拉電阻拉高40us
delay_10us();
delay_10us();
delay_10us();
delay_10us();
DHT=1; //主機(jī)設(shè)為輸入 判斷從機(jī)相應(yīng)信號
if(!DHT) //判斷從機(jī)是否把總線拉低
{
flag=2;
while((!DHT)&&flag++); //等待從機(jī)把總線拉低
flag=2;
while(DHT&&flag++); //判斷從機(jī)是否拉低總線,即響應(yīng)
//接收數(shù)據(jù)
shiH=read_data();//因?yàn)閞ead_data()只讀出一個(gè)字節(jié),而DHT讀出的是連續(xù)的5個(gè)字節(jié),所以不用for()
shiL=read_data();
wenH=read_data();
wenL=read_data();
check=read_data();
DHT=1;
}
}
//DH11數(shù)據(jù)處理
void DHT11dada()
{
unsigned char temp;
read_init();
temp=shiH+shiL+wenH+wenL; //檢驗(yàn)也為8位的二進(jìn)制,等于前面的數(shù)據(jù)之和
if(check==temp)
{ //檢驗(yàn)數(shù)據(jù)對了就賦給另外幾個(gè)變量來轉(zhuǎn)換
shiZ=shiH;
shiX=shiL;
wenZ=wenH;
wenX=wenL;
}
wendu[4]='0'+wenZ/10; //分離出各個(gè)位,并轉(zhuǎn)換成字符數(shù)據(jù),依據(jù)上面的數(shù)組定義wendu[] ="wen:00.00 d";的數(shù)據(jù)格式,把對應(yīng)的數(shù)據(jù)寫到對應(yīng)的位
wendu[5]='0'+wenZ; //分理出的是溫度的個(gè)位,在數(shù)組中的第六個(gè)位置,所以寫入該位更新,以便顯示
wendu[8]='0'+wenX/10; //第七位為 .
wendu[9]='0'+wenX;
shidu[4]='0'+shiZ/10; //同理,濕度的格式為shidu[]="shi:00.00 RH";
shidu[5]='0'+shiZ;
shidu[8]='0'+shiX/10;
shidu[9]='0'+shiX;
}
//LCD1602部分函數(shù) 各個(gè)函數(shù)依據(jù)LCD1602的時(shí)序編寫
////////////////////////////////////////////////////////
//LCD1602寫指令函數(shù)
void lcd_write_com(uchar c)
{
delay_1ms(5);
E=0;
RS=0;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
}
//LCD1602寫數(shù)據(jù)函數(shù)
void lcd_write_dat(uchar c)
{
delay_1ms(5);
E=0;
RS=1;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
RS=0;
}
//LCD1602初始化
void lcd_init()
{
delay_1ms(5);
lcd_write_com(0x38);
lcd_write_com(0x38);
lcd_write_com(0x38);
lcd_write_com(0x06);
lcd_write_com(0x0c);
lcd_write_com(0x01);
}
//LCD1602清屏函數(shù)
void qingping()
{
lcd_write_com(0x01);
delay(5);
}
//顯示開始標(biāo)題
void disp(void) //顯示子函數(shù)
{ uchar i,j;
lcd_write_com(0x80);//往第一行寫入字符串,寫完一個(gè)字符會(huì)自動(dòng)調(diào)到第二個(gè)地址寫入數(shù)據(jù)
for(i=0;i<13;i++)
{
lcd_write_dat(table[ i]);
}
lcd_write_com(0x80+40);//往第二行寫入日期
for(j=0;j<11;j++)
{
lcd_write_dat( table1[j]);
}
delay(3000);//顯示的時(shí)間長短
qingping();//清屏
}
//顯示溫濕函數(shù)
void display_DHT11()
{ uchar h,n,e,m;
//uchar x,y;
lcd_write_com(0x80);
for(e=0;e<12;e++) //寫入溫度數(shù)據(jù)
{
lcd_write_dat(wendu_char[e]);
}
lcd_write_com(0x80+40);
for(n=0;n<11;n++) //寫入溫度數(shù)據(jù)
{
lcd_write_dat(wendu[n]);
}
delay(3000);
qingping();//清屏
lcd_write_com(0x80);
for(h=0;h<10;h++) //寫入濕度數(shù)據(jù)
{
lcd_write_dat(shidu_char[h]);
}
lcd_write_com(0x80+40);
for(m=0;m<12;m++) //寫入濕度數(shù)據(jù)
{
lcd_write_dat(shidu[m]);
}
delay(3000);
qingping();
// //情緒表達(dá)部分 //因?yàn)?1內(nèi)存寫滿了,只能舍去這部分
// if(shiZ>=16&&shiZ<=28)
// {
// lcd_write_com(0x80);
// for(y=0;y<11;y++)
// {
// lcd_write_dat(qingxu1[y]);
// }
// lcd_write_com(0x80+0x40);
// for(x=0;x<12;x++)
// {
// lcd_write_dat(qingxu2[x]);
// }
// delay(3000);
// qingping();
// }
// if(shiZ<=16&&shiZ>=28)
// {
// lcd_write_com(0x80);
// for(y=0;y<12;y++)
// {
// lcd_write_dat(qingxu3[y]);
// }
// lcd_write_com(0x80+0x40);
// for(x=0;x<12;x++)
// {
// lcd_write_dat(qingxu4[x]);
// }
// delay(3000);
// qingping();
// }
}
//顯示超聲波數(shù)據(jù)
void display_HC05()
{
uchar k,w;
lcd_write_com(0x80);//超聲波測距顯示部分:K,W
for(k=0;k<14;k++)
{
lcd_write_dat(table2[k]);
}
lcd_write_com(0x80+0x40);
for(w=0;w<8;w++)
{
lcd_write_dat(temp_dis[w]);
}
delay(3000);
qingping();
}
////不寫在一起是為了及時(shí)將數(shù)據(jù)輸出,因?yàn)樽x完傳感器才輸出,有的傳感器的數(shù)據(jù)已經(jīng)變化了
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//主函數(shù)
void main()
{ uchar x,s;
lcd_init();
init0();
Tx=0;//超聲波發(fā)送口初始化,
while(1)
{
disp();//顯示開始的字符
for(x=0;x<2;x++)
{
DHT11dada();//溫濕的數(shù)據(jù)
}
display_DHT11();//顯示溫濕的數(shù)據(jù)
for(s=0;s<2;s++)
{
HC05_Init(); //需要放到while(1)中 因?yàn)橐粩嘤|發(fā)超聲波模塊的脈沖得出距離
distance_convert(distance);
}
display_HC05();
}
}
//外部中斷0的中斷函數(shù),記回波的時(shí)間,即發(fā)送測量脈沖開始計(jì)時(shí),到接收到回波時(shí)產(chǎn)生外部中斷,把得到的時(shí)間賦給t
void int0() interrupt 0
{ EA=0;
t=(TH0*256+TL0); //讀取定時(shí)器的時(shí)間
TH0=0; //清空定時(shí)器
TL0=0;
} |
|