/**********************************************
設計者:胥學辰
時間:2011-11-1——2011-11-6
功能:18B20采集溫度,dht11采集濕度,光敏電阻采集光照等,
通過GSM接受指令傳輸參數,控制外部器件改變環(huán)境參數。
完整代碼下載:http://m.izizhuan.cn/f/gpsdd.rar
***********************************************/
#include<reg52.h>
#include<intrins.h>
#include<string.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ_wen=P2^0;
sbit DQ_shi=P2^1;
uchar i=0,j=0,flag,tm,temp,wet,dat;
char num[]="15282983798"; //定義要撥打的電話號碼
char code Huifu_S[]="Fa Song Success!"; //定義成功發(fā)送要回復的內容
char code Huifu_F[]="Fa Song Failure!"; //定義失敗發(fā)送要回復的內容
char Huifu_wsg[]="temp:00.00C wet:23%R"; //定義參數回復數組
char xdata Huancun[200]; //定義返回值存儲數組
char code Ok[]="OK"; //返回OK值標志
char code CMTI[]="+CMTI"; //接收短信標志
char code open_1[]="open1"; //短信控制1標志
char code open_2[]="open2"; //短信控制2標志
char code open_3[]="open3"; //短信控制3標志
char code open_4[]="open4"; //短信控制4標志
void delay_key(uchar z); //按鍵延時函數
void delay_GSM(uint y); //GSM模塊延時函數
void delay_18b20(uchar i); //18b20延時函數
void delay_dht11_C(uint j); //dht11長延時函數
void delay_dht11_D(uchar i); //dht11短延時函數
void chuankou_init(); //串口初始化函數
void clear_huancun(); //清除緩存函數
void send_ASCII(uchar *b); //發(fā)送ASCII代碼函數
void send_16_Hex(uchar c); //發(fā)送16進制代碼函數
bit panduan(uchar *a,uchar *b); //判斷是否返回OK與短信成功代碼
void GSM_Text_Message(uchar*num,uchar*Huifu); //Text模式短信發(fā)送函數
void GSM_Call(uchar *num); //撥打電話函數
void Tiqu_num(); //提取來電號碼函數
void init_18b20(); //18b20初始復位函數
void write_18b20_dat(uchar dat); //18b20寫入字節(jié)函數
uchar read_18b20_dat(); //18b20讀出字節(jié)函數
uchar read_18b20_temp_zs(); //18b20讀取溫度整數函數
uchar read_18b20_temp_xs(); //18b20讀取溫度小數函數
void dht11_init(void); //dht11初始化函數
uchar read_dht11(void); //dht11讀取濕度函數
void chuli_wen_wet_light(); //18b20_dht11_light處理函數
void main() //主函數
{
chuankou_init(); //串口初始化
clear_huancun(); //清除緩存
delay_GSM(1000); //延時
while(!panduan(Huancun,Ok)) //判斷返回值
{
send_ASCII("AT"); //發(fā)送聯機命令
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
P0=0x01; //步驟指示燈1
delay_GSM(600); //延時
}
clear_huancun(); //清除緩存
P0=0x02; //步驟指示燈2
delay_GSM(600); //延時
send_ASCII("AT+CNMI=2,1"); //設置當有新短信到來時提示
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(600); //延時
while(!panduan(Huancun,Ok)); //等待設置成功
clear_huancun(); //清除緩存內容
P0=0x03; //步驟指示燈3
delay_GSM(600); //延時
send_ASCII("AT+CMGF=1"); //文本(TEXT)模式
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(600); //延時
while(!panduan(Huancun,Ok)); //等待設置成功
clear_huancun(); //清除緩存內容
P0=0x04; //步驟指示燈4
delay_GSM(600); //延時
send_ASCII("AT+CMGD=1"); //刪除第一條信息
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(600); //延時
while(!panduan(Huancun,Ok)); //等待設置成功
clear_huancun(); //清除緩存內容
while(1) //與GSM模塊聯機成功后的大循環(huán)
{
P0=0x05; //步驟指示燈5
chuli_wen_wet_light(); //實時采集處理溫度
if(panduan(Huancun,CMTI)) //若緩存字符串中含有"+CMTI"就表示有新的短信
{
P0=0x06; //步驟指示燈6
clear_huancun(); //清除緩存內容
delay_GSM(600); //延時
send_ASCII("AT+CMGR=1"); //發(fā)送讀取信息指令
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(600); //延時
Tiqu_num(); //提取來電號碼
if(panduan(Huancun,open_1)) //如果信息內容是"open1"
{
P0=0x10; //指示燈
GSM_Text_Message(num,Huifu_wsg); //發(fā)送環(huán)境參數信息
GSM_Text_Message(num,Huifu_S); //發(fā)送成功短信回復
}
else if(panduan(Huancun,open_2)) //如果信息內容是"open2"
{
P0=0x20; //指示燈
GSM_Text_Message(num,Huifu_S); //發(fā)送成功短信回復
}
else if(panduan(Huancun,open_3)) //如果信息內容是"open3"
{
P0=0x40; //指示燈
GSM_Text_Message(num,Huifu_S); //發(fā)送成功短信回復
}
else if(panduan(Huancun,open_4)) //如果信息內容是"open4"
{
P0=0x80; //指示燈
GSM_Text_Message(num,Huifu_S); //發(fā)送成功短信回復
}
else
GSM_Text_Message(num,Huifu_F); //發(fā)送失敗短信回復
clear_huancun(); //清除緩存內容
delay_GSM(600); //延時
send_ASCII("AT+CMGD=1"); //刪除讀取后的信息
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(600); //延時
while(!panduan(Huancun,Ok)); //等待設置成功
clear_huancun(); //清除緩存內容
}
}
}
/****************************
各環(huán)節(jié)延時函數
*****************************/
void delay_key(uchar x) //按鍵控制延時函數
{
uchar y;
for(;x>0;x--)
for(y=110;y>0;y--);
}
void delay_GSM(uint y) //GSM模塊延時函數
{
uint x;
for(;y>0;y--)
{
x=1500;
while(x--);
}
}
void delay_18b20(uchar i) //18b20延時函數
{
while(i--);
}
void delay_dht11_C(uint j) //dht11長延時函數
{
uchar i;
for(;j>0;j--)
for(i=0;i<27;i++);
}
void delay_dht11_D(uchar i) //dht11短延時函數
{
for(;i>0;i--)
_nop_();
}
void chuankou_init() //串口初始化函數
{
SCON=0x50; //串口:方式1,允許發(fā)送和接收
TMOD=0x20; //定時器1:模式2,8位自動重裝模式,用于產生波特率
TH1=0xFD; //11.0592MHZ晶振,波特率為9600
TL1=0xFD;
TR1=1; //開啟定時器1
ES=1; //開啟串口中斷
EA=1; //開啟全局中斷
}
/****************************
GSM部分函數
*****************************/
void clear_huancun() //清除緩存內容函數
{
uchar k;
for(k=0;k<200;k++)
{
Huancun[k]=0; //將緩存內容清零
}
i=0; //接收字符串的起始存儲位置
}
void send_ASCII(uchar *b) //發(fā)送字符串函數
{
ES=0; //關串口中斷
for(b;*b!='\0';b++)
{
SBUF=*b;
while(TI!=1); //等待發(fā)送完成
TI=0; //清除發(fā)送中斷標志位
}
ES=1; //開串口中斷
}
void send_16_Hex(uchar c) //發(fā)送16進制函數
{
ES=0; //關串口中斷
SBUF=c;
while(TI!=1); //等待發(fā)送完成
TI=0; //清除發(fā)送中斷標志位
ES=1; //開串口中斷
}
bit panduan(uchar *a,uchar *b) //判斷是否成功返回值函數
{
if(strstr(a,b)!=NULL) //如果a包含了b,則1;否則0
return 1;
else
return 0;
}
void Tiqu_num() //提取來電號碼函數函數
{
uchar i;
for(i=0;i<11;i++)
{
num[i]=Huancun[i+36];
}
}
void GSM_Text_Message(uchar *num,uchar *Huifu) //Text模式短信發(fā)送
{
send_ASCII("AT"); //發(fā)送聯機命令
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(200);
send_ASCII("AT+CMGF=1"); //發(fā)送TXET命令
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(200);
send_ASCII("AT+CSCS=GSM");
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(200);
send_ASCII("AT+CSMP=17,167,0,0");
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(200);
send_ASCII("AT+CMGS="); //接收短信手機號
send_ASCII(num);
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a); //發(fā)送換行符
delay_GSM(200);
send_ASCII(Huifu); //發(fā)送發(fā)送成功命令
send_ASCII("\x1a"); //16進制結束標志
delay_GSM(200);
}
void GSM_Call(uchar *num) //撥打電話函數
{
send_ASCII("ATD");
send_ASCII(num);
send_ASCII("F;");
send_16_Hex(0x0d); //發(fā)送回車符
send_16_Hex(0x0a);
delay_GSM(200);
}
/****************************
18b20函數
*****************************/
void init_18b20()
{
uchar a;
DQ_wen=1; //DQ復位
delay_18b20(8); //稍做延時
DQ_wen=0; //單片機將DQ拉低
delay_18b20(80); //精確延時大于480us
DQ_wen=1; //拉高總線
delay_18b20(14); //延時
a=DQ_wen; //稍做延時后 如果a=0則初始化成功 a=1則初始化失敗
delay_18b20(100);
}
void write_18b20_dat(uchar dat) //18b20寫入字符函數
{
uchar i;
for(i=0;i<8;i++)
{
DQ_wen=0;
DQ_wen=dat&0x01;
delay_18b20(5);
DQ_wen=1;
dat>>=1;
}
}
uchar read_18b20_dat() //18b20讀出字符函數
{
uchar i,dat=0;
DQ_wen=1;
for(i=0;i<8;i++)
{
DQ_wen=0;
_nop_();
_nop_();
dat>>=1;
DQ_wen=1;
_nop_();
_nop_();
if(DQ_wen)
dat|=0x80;
delay_18b20(30);
DQ_wen=1;
}
return dat;
}
uchar read_18b20_temp_zs() //18b20溫度整數讀取函數
{
uchar a,b,c;
init_18b20();
write_18b20_dat(0xcc);
write_18b20_dat(0x44);
init_18b20();
write_18b20_dat(0xcc);
write_18b20_dat(0xbe);
a=read_18b20_dat();
b=read_18b20_dat();
c=a&0x0f;
b<<=4;
b+=(a&0xf0)>>4;
return b;
}
uchar read_18b20_temp_xs() //18b20溫度小數讀取函數
{
uchar a,b,c;
init_18b20();
write_18b20_dat(0xcc);
write_18b20_dat(0x44);
init_18b20();
write_18b20_dat(0xcc);
write_18b20_dat(0xbe);
a=read_18b20_dat();
b=read_18b20_dat();
c=a&0x0f;
b<<=4;
b+=(a&0xf0)>>4;
return c;
}
/****************************
dht11函數
*****************************/
void dht11_init(void) //dht11初始化復位函數
{
uchar i;
for(i=0;i<8;i++)
{
flag=2;
while((!DQ_shi)&&flag++);
delay_dht11_D(2);
tm=0;
if(DQ_shi)
tm=1;
flag=2;
while((DQ_shi)&&flag++);
if(flag==1)
break;
dat<<=1;
dat|=tm;
}
}
uchar read_dht11(void) //dht11讀取濕度函數
{
uchar wet_L,temp_L,temp_H,wet_H,JY;
DQ_shi=0;
delay_dht11_C(180);
DQ_shi=1;
delay_dht11_D(4);
DQ_shi=1;
if(!DQ_shi)
{
flag=2;
while((!DQ_shi)&&flag++);
flag=2;
while((DQ_shi)&&flag++);
dht11_init();
wet_H=dat;
dht11_init();
wet_L=dat;
dht11_init();
temp_H=dat;
dht11_init();
temp_L=dat;
dht11_init();
JY=dat;
DQ_shi=1;
tm=(temp_H+temp_L+wet_H+wet_L);
if(tm==JY)
{
temp=temp_H;
wet=wet_H;
}
}
return wet;
}
void chuli_wen_wet_light() //采集數據處理函數
{
uchar temp_zs,temp_xs,wet_zs;
temp_zs=read_18b20_temp_zs(); //讀取18b20溫度整數
temp_xs=read_18b20_temp_xs(); //讀取18b20溫度小數
wet_zs=read_dht11(); //dht11濕度整數
Huifu_wsg[6]=temp_zs%10+'0'; //數據轉化為字符存入字符數組
Huifu_wsg[5]=temp_zs/10+'0';
Huifu_wsg[9]=temp_xs%10+'0';
Huifu_wsg[8]=temp_xs/10+'0';
Huifu_wsg[17]=wet_zs%10+'0';
Huifu_wsg[16]=wet_zs/10+'0';
}
void timer4() interrupt 4 using 1
{
ES=0; //關串口中斷,防止中斷嵌套
if(TI) //如果是發(fā)送中斷,則不做任何處理
TI=0; //清除發(fā)送中斷標志位
if(RI) //如果是接送中斷,則進行處理
{
RI=0; //清除接收中斷標志位
Huancun[i]=SBUF; //將接收到的字符串存到緩存中
i++; //緩存指針向后移動
if(i>200) //如果緩存滿,將緩存指針指向緩存的首地址
i=0;
}
ES = 1; //開啟串口中斷
}