摘 要
为了应对目前人们提出的对生活越来越智能的要求,在提高生活品质的同时降低意外事件发生对用户造成的经济损失或其他损失。针对日常生活中经常发生的火灾,失窃,电力资源浪费等生活问题,本设计正是在这种需求背景下展开研究。基于单片机的智能家居安防系统设计集成了防可燃气体烟雾泄露 、防外来人员入侵、防火、智能控制家电等功能,可实现自动检测、声光报警、远程查询、远程报警、远程控制等。
以STC89C52单片机为核心器件,再加上电阻,电容,晶体振荡器等器件,构成了单片机的最小系统。以及其它智能探测器组成的检测模块,在监测到灾情时只输出报警信号开关量,单片机处理器自动控制GSM接口电路。根据险情类别,自动向用户手机发送短信报警,当用户在家遇到灾情或其他情况时,亦可通过求救按钮向外界发出报警信息。
本设计具有成本较低,功能实用,灵活多样,简便有效等特点,有效的降低了用户住宅遇到和发生险情及其他意外事件的风险,有效的避免了因险情及其他意外事件造成的经济及其他损失,将居民损失降到最小,同时也将提高用户的生活品质水平。
关键词:安防系统; 智能家居; 单片机; GSM模块; 远程报警
1 控制系统方案设计
1.1 设计要求
(1)进入系统后,液晶屏实时显示当前温度传感器所测温度值以及当前设置温度传感器报警阈值,通过“温度加”及“温度减”来对温度报警的阈值来进行调节。
(2)如所测温度值达到报警阈值后,系统启动声光报警,并发送英文报警短信到用户手机。
(3)用户开始设防之后,红外人体模块检测到有人时,系统启动声光报警,并发送英文报警短信到用户手机。
(4)如可燃气体/烟雾传感器检测到可燃气体/烟雾时,系统启动声光报警,并发送英文报警短信到用户手机。
(5)如用户需了解屋内当前温度值时,通过任意手机拨打电话,系统自动挂断电话,并回复屋内当前温度值。
(6)用户可通过手机编辑短信发送到手机模块的方式,控制继电器闭合与断开,利用LED灯的亮与灭,表示家用电器开启与关闭。
1.2 总控制方案设计
以STC89C52单片机作为系统的“心脏”,加上电阻、电容、晶振等器件的加持,组成最小系统[4]。以及其它智能探测器组成的检测模块,在监测到灾情时只输出报警信号开关量,单片机处理器自动控制GSM接口电路。根据险情类别,自动向用户手机发送短信报警,当用户在家遇到灾情或其他情况时,亦可通过求救按钮向外界发出报警信息。总控制框图如图1.1所示。
1.3 单片机方案设计及工作原理
方案一:采用32位的LPC2138作为控制CPU,LPC2138采用了PHILIPS公司基于ARM7TDMI-S核的ARM芯片,拥有RDI标准接口、同步Flash刷新技术以及影射寄存器窗口等三项国内ARM仿真器设计最领先的3种技术,内部PLL锁相环倍频可以得到更高的CPU处理速度,硬件自带的AD、DA、捕获、匹配以及同步与异步的通信方式更方便用户的编程设计,并且可以达到很高的实时性,但是价格较昂贵[5]。
图1.1系统总体框图
2. 电路设计仿真和实物
STC89C52是一种低功耗、高性能CMOS8位微控制器,具有60K 在系统可编程Flash 存储器器、中央处理器、程序存储器(Flash)、数据存储器(RAM)、EEPROM、定时/计数器、I/O接口、UART接口和中断系统、SPI接口、高速A/D转换模块、PWM(或捕捉/比较单元)以及硬件看门狗、电源监控、片内RC振荡器等模块[12]。
本系统设计主要应用的是A/D转换模块、SPI接口、定时/计数器、I/O接口等功能模块。具体原理图如图2.1所示。
图2.1单片机主电路原理图
.
原理图
电路板实物图
源程序清单
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
bit Alarm_flag; //温度发送短信标志位,=1表示已经发送,=0表示没有发送
bit Smoke_Alarm; //烟雾发送短信标志位,=1表示已经发送,=0表示没有发送
bit Steal_Alarm; //防盗发送短信标志位,=1表示已经发送,=0表示没有发送
bit NEW_SMS; //短消息提示标志位
bit READ_SMS; //读取短消息标志位
bit ATH; //挂机标志位
uchar xdata UART0_Data[256]; //存放手机模块的数组
uchar UART0_Len=0; //定义长度
uchar Len=0; //定义长度
uchar code Command_AT[]=“AT\r\n”; //发送AT,建立连接
uchar code Command_AT_CMGF[]=“AT+CMGF=1\r\n”; //把格式设置为text格式
uchar code Command_AT_CMGS[]=“AT+CMGS=”; //发送到指定号码指令
uchar code Command_AT_YIN[]={0x22}; //发送指定号码双引号
uchar code Command_AT_ENTER[]=“\r\n”; //发送指定号码双引号
uchar code Command_AT_NUM[]=“17640148362”; //发送到指定号码
uchar code Command_AT_IPR[]=“AT+IPR=9600\r\n”; //设置波特率
uchar Command_AT_CMGR[]=“AT+CMGR= \r\n”; //读第几条短信
uchar Command_AT_CMGD[]=“AT+CMGD= \r\n”; //删除第几条短信
uchar code Command_AT_CMGD1[]=“AT+CMGD=01\r\n”; //删除第1条短信
uchar code Command_AT_CNMI[]=“AT+CNMI=1,1,2\r\n”; //设置短消息提示
uchar code Command_AT_CLIP[]=“AT+CLIP=1\r\n”; //来电显示
uchar code Command_AT_CRC[]=“AT+CRC=0\r\n”; //设置来电开头为RING,有电话打入收到RING提醒
uchar code Command_ATH[]=“ATH\r\n”; //挂电话
uchar code Command_ATE[]=“ATE1\r\n”; //设置回显
uchar code Command_AT_End[]={0x1A}; //发送短信内容结束符
uchar code Command_NUM[]=“0123456789±”; //短信里温度值提取的数字
uchar Command_AT_Tem[42]=" C,Temperature exceed limit,please note!“; //温度超过界限,请注意!
uchar code Command_Someone[33]=“Someone in the house,please note!”; //有人在屋里,请注意!
uchar code Command_Smoke[37]=“Combustible gas or smoke,please note!”; //烟雾或可燃性气体,请注意!
uchar code Command_Help[35]=“Someone call for help, please note!”; //有人求救,请注意!
uchar code Command_Opened[13]=“It is opened!”; //打开
uchar code Command_Closed[13]=“It is closed!”; //关闭
uchar code OPEN[]=”#OPEN#“; //开启
uchar code CLOSE[]=”#CLOSE#"; //关闭
sbit rs=P1^0; //LCD1602位定义
sbit rw=P1^1; //LCD1602位定义
sbit e=P1^2; //LCD1602位定义
uchar code table1[]=“NOW Temper: C”; //液晶屏显示内容
uchar code table2[]=“SET Temper: C”; //液晶屏显示内容
uchar code table3[]=" “; //清屏内容
uchar code table4[]=” GSM Module! "; //初始化显示内容
uchar code table5[]=“SIM Initialize!!”; //初始化显示内容
sbit UP =P1^6; //加键
sbit DOWN =P1^7; //减键
sbit HELP =P2^0; //求救键
sbit BEEP =P1^4; //蜂鸣器接口
sbit SMOKE=P3^6; //烟雾接口
sbit STEAL=P3^5; //防盗接口
sbit DQ=P3^7; //温度数据口
sbit JDQ=P1^3; //继电器接口,低有效
int temperature; //全局变量 温度
int Set_temp=50; //设置温度,默认是50度
uchar Timer_Counter; //定时器中断计数
void Send_Message(void); //函数声明
void Send_Command(uchar Value[],uchar Len); //函数声明
void Send_Message(void);
void Send_Message1(void);
void Send_Message2(void);
void Send_Message3(void);
void Send_Message4(void);
void Send_Message5(void);
/LCD1602********************/
void delay_lcd(uint z) //显示屏延时0.2ms函数
{
uint x,y;
for(x=z;x>0;x–)
for(y=20;y>0;y–);
}
void delay1(uint z) //GSM短信延时1ms函数
{
uint x,y;
for(x=z;x>0;x–)
for(y=110;y>0;y–);
}
void write_com(uchar com) //LCD1602写指令函数
{
rw=0;
delay_lcd(5);
rs=0;
delay_lcd(5);
e=1;
delay_lcd(5);
P0=com;
delay_lcd(5);
e=0;
delay_lcd(5);
}
void write_date(uchar date) //LCD1602写数据函数
{
rw=0;
delay_lcd(5);
rs=1;
delay_lcd(5);
e=1;
delay_lcd(5);
P0=date;
delay_lcd(5);
e=0;
delay_lcd(5);
}
void init() //LCD1602初始化函数
{
uchar num;
e=0; // 时序表e初始为0
write_com(0x38); //设置162显示,57点阵,8位数据接口
write_com(0x0c); //设置光标
write_com(0x06); //光标自动加1,光标输入方式
write_com(0x01); //清屏
write_com(0x80); //设置初始显示位置
for(num=0;num<16;num++)
{
write_date(table4[num]); //显示数组table1的内容
delay_lcd(1);
}
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_date(table5[num]); //显示数组table2的内容
delay_lcd(1);
}
}
void LCD_Display_String(unsigned char line,unsigned char *string)
{ //液晶屏显示内容,把要显示的内容写到对应的位置
unsigned char i;
unsigned char address=0;
if(line1)
{
address=0x80; //0X80是第1行的第1个位置 ,0x81第2位
}
else if(line2)
{
address=0x80+0x40; //0X80+0x40是第2行的第1个位置 ,0X80+0x40+1是第2行第2位
}
for(i=0;i<16;i++)
{
write_com(address);
write_date(string[i]);
address++;
}
}
void temperature_dispaly(char add,char dat) //温度显示函数:第一个:参数的地址,第二个:参数的内容
{
uchar shi,ge;
shi=dat/10; //把温度的十位提取出来
ge=dat%10; //把温度的个位提取出来
write_com(0x80+add); //要写的地址
write_date(0x30+shi); //十位的内容 1602字符库
write_date(0x30+ge); //个位的内容 1602字符库
if((temperature>0)&(temperature<100)) //温度在正常范围内转换
{
Command_AT_Tem[1]=Command_NUM[temperature/10]; //把十位的数字存到Command_AT_Tem[1]
Command_AT_Tem[2]=Command_NUM[temperature%10]; //把个位的数字存到Command_AT_Tem[2]
}
}
/DS18B20**************/
/*void delay(uint y) //DS18B20延时函数25us左右(仿真用、实际调试、需要的延时时间不同)
{
while(y–);
}
*/
void delay(uint z) //DS18B20延时函数34us左右(仿真用、实际调试、需要的延时时间不同)
{
uint x,y;
for(x=z;x>0;x–)
for(y=1;y>0;y–);
}
void write_byte(uint dat) //写一个字节
{
uchar i;
for(i=0;i<8;i++) //循环八次 共有八位
{
DQ=0; //写零
DQ=dat&0x01; //向总线写位数据,从最低位写起
delay(4);
DQ=1; //写一
dat>>=1; //下次写作准备,移位数据
}
delay(4);
}
uchar read_byte(void) //读一个字节,返回值
{
uchar i;
uint value;
for(i=0;i<8;i++) //循环八次 共有八位
{
DQ=0;
value>>=1;
DQ=1; //释放总线
if(DQ)
value|=0x80; //DQ=1,value取1
delay(4);
}
return value;
}
void ds18b20_init() //初始化函数
{
uint n;
DQ=1;
delay(8);
DQ=0;
delay(80); //低电平480——960us
DQ=1; //总线释放
delay(8); //等待50——100us
n=DQ; //读取复位状态
delay(4);
}
int readtemperature() //读整数部分
{
int a,b; //高八位,低八位
ds18b20_init();
write_byte(0xcc); //跳过rom匹配,跳过读序列号的操作,可节省操作时间
write_byte(0x44); //启动温度检测
delay(300); //测温度
ds18b20_init(); //开始操作前需要复位
write_byte(0xcc); //跳过rom匹配
write_byte(0xbe); //写读寄存器中温度值的命令
a=read_byte(); //low 低位开始读取
b=read_byte(); //high 高位开始读取
b<<=8; //把高位左移八位
b=b|a; //高八位与第八位进行或运算,得到总和
if(b>=0) //如果温度大于等于0
{
b=b0.0625; //直接乘以0.0625
write_com(0x80+12); //在LCD1602对应的位置不写内容
write_date(0x20);
if((b>0)&(b<100))
Command_AT_Tem[0]=Command_NUM[10];//Command_AT_Tem[0]为+,表示温度大于或等于0
}
else //温度小于0
{
b=~b+1; //取反码再加一
b=b0.0625; //再运算
write_com(0x80+12); //在LCD1602对应的位置写一个负号
write_date(0x2d);
if((b>0)&(b<100))
Command_AT_Tem[0]=Command_NUM[11];//Command_AT_Tem[0]为-,表示温度小于0
}
return b; //返回b,此时以表示温度
}
/按键***********************/
void KEY(void)
{
if(HELP0) //求救按键按下
{
delay1(2); //延时消抖
if(HELP0) //按键确实按下
{
BEEP=1; //开蜂鸣器
Send_Message5(); //发送短信
while(!HELP); //等待按键释放
}
}
if(UP0) //按键按下
{
delay1(2); //延时消抖
if(UP0) //按键确实按下
{
while(!UP); //等待按键释放
Set_temp++; //设置的温度值加一
if(Set_temp100) //温度值到达100
{
Set_temp=0; //清零
}
}
}
if(DOWN0) //按键按下
{
delay1(2); //延时消抖
if(DOWN==0) //按键确实按下
{
while(!DOWN); //等待按键释放
Set_temp–; //设置的温度值减一
if(Set_temp<0) //温度值小于0
{
Set_temp=99; //变为最大值
}
}
}
temperature_dispaly(0x40+13,Set_temp); //显示设置值到LCD
}
/检测各部分是否异常***********************/
void Check(void)
{
if(temperature>Set_temp) //如果实际温度值大于设置值
{
if((temperature>0)&(temperature<100)) //温度在正常范围内才报警
{
BEEP=1; //启动蜂鸣器
if(Alarm_flag==0) //警报标志位为1时发送温度报警信息
{
Send_Message3(); //发送温度过高报警短信
}
Alarm_flag=1; //标志位置一,表示短信已经发送,避免重复发送短信
}
}
if(temperature<=Set_temp) //正常情况
{
Alarm_flag=0; //清除标志位,下次温度超过继续发送短信一次
}
if(STEAL==0) //检测到人体
{
BEEP=1; //启动蜂鸣器
if(Steal_Alarm==0) //警报标志位为1时发送防盗报警信息
{
Send_Message2();
}
Steal_Alarm=1; //标志位置一,表示短信已经发送,避免重复发送短信
}
if(STEAL==1) //正常情况
{
Steal_Alarm=0; //清除标志位,下次继续发送短信一次
}
if(SMOKE==0) //检测到可燃性气体
{
BEEP=1; //启动蜂鸣器
if(Smoke_Alarm==0) //警报标志位为1时发送烟雾报警信息
{
Send_Message1();
}
Smoke_Alarm=1; //标志位置一,表示短信已经发送,避免重复发送短信
}
if(SMOKE==1) //正常情况
{
Smoke_Alarm=0; //清除标志位,下次温度超过继续发送短信一次
}
if((SMOKE==1)&&(temperature<=Set_temp)&&(STEAL==1)&&(HELP=1))
{
BEEP=0; //关闭蜂鸣器
}
}
/GSM***********************/
void Sys_Init(void)
{
TMOD=0x21; //设置定时器1的工作方式为方式2
TH1=0xfd;
TL1=0xfd; //设置串行口波特率为9600
TR1=1; //开启定时器1
SCON=0x50; //设置串行口的工作方式为方式一,允许接收
PCON=0x00;
ES=1; //开串行口中断
EA=1; //开总中断
JDQ=1; //关闭继电器
BEEP=0; //关闭蜂鸣器
}
void Delay_0_5s(uint y) //延时1s
{
uint a;
for(a=0;a<10*y;a++) //20为1s
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
while(!TF0);
TF0=0;
}
}
void Send_Command(uchar Value[],uchar Len) //发送指令,Value[]表示发送哪个数组,Len表示发送该数组里的几位
{
uchar i;
for(i=0;i<Len;i++)
{
SBUF=Value[i];
while(!TI);
TI=0;
}
}
void GSM_Init(void) //GSM模块初始化
{
Send_Command(Command_ATE,5); //设置回显
delay1(1000);
Send_Command(Command_AT,3); //建立连接
delay1(10);
Send_Command(Command_AT_CMGF,10); //设置为text格式
delay1(2000);
Send_Command(Command_AT_CNMI,14); //设置为设置为中断方式接收短信,即接收短信后向下位机串口发送 +CMTI: “SM”,1 。
delay1(3000);
Send_Command(Command_AT_CLIP,10); //设置来电提示 RING +CLIP:
delay1(1000);
Send_Command(Command_AT_CRC,9); //设置来电提示 RING +CLIP:
delay1(1000);
Send_Command(Command_AT_IPR,12); //设置波特率=9600
delay1(1000);
}
void Read_Message(void)
{
if(NEW_SMS==1) //有新消息
{
if((UART0_Data[Len+13]>=0x30)&&(UART0_Data[Len+13]<=0x39)) //短信数第二位有数据,表示有二位数或三位数
{
if((UART0_Data[Len+14]>=0x30)&&(UART0_Data[Len+14]<=0x39)) //三位数 暂不处理
{
}
if((UART0_Data[Len+14]<0x30)||(UART0_Data[Len+14]>0x39)) //二位数
{
Command_AT_CMGR[8]=UART0_Data[Len+12]; //第一位为短信数十位
delay1(10);
Command_AT_CMGR[9]=UART0_Data[Len+13]; //第二位为短信数个位
delay1(10);
Command_AT_CMGD[8]=UART0_Data[Len+12]; //第一位为短信数十位
delay1(10);
Command_AT_CMGD[9]=UART0_Data[Len+13]; //第一位为短信数个位
delay1(10);
}
}
if((UART0_Data[Len+13]<0x30)||(UART0_Data[Len+13]>0x39)) //短信数第二位无数据,表示只有一位数
{
Command_AT_CMGR[8]=0x30; //第一位为0
delay1(10);
Command_AT_CMGR[9]=UART0_Data[Len+12]; //第二位为短信数
delay1(10);
Command_AT_CMGD[8]=0x30; //第一位为0
delay1(10);
Command_AT_CMGD[9]=UART0_Data[Len+12]; //第二位为短信数
delay1(10);
}
Send_Command(Command_AT_CMGR,11); //发送"AT+CMGR=?",读取第几条短信
delay1(1000); //延时
UART0_Data[Len+13]=0x40;UART0_Data[Len+14]=0x40;
UART0_Len=0;
NEW_SMS=0; //清除新消息提示标志
}
if(READ_SMS==1) //读取消息
{
if(((UART0_Data[Len+6]==OPEN[0])&&(UART0_Data[Len+7]==OPEN[1])&&(UART0_Data[Len+8]==OPEN[2])&&(UART0_Data[Len+9]==OPEN[3])&&(UART0_Data[Len+10]==OPEN[4])&&(UART0_Data[Len+11]==OPEN[5]))//移动
||(UART0_Data[Len+3]==OPEN[0])&&(UART0_Data[Len+4]==OPEN[1])&&(UART0_Data[Len+5]==OPEN[2])&&(UART0_Data[Len+6]==OPEN[3])&&(UART0_Data[Len+7]==OPEN[4])&&(UART0_Data[Len+8]==OPEN[5]))//联通
{
JDQ=0; //开启继电器
Send_Command(Command_AT_CMGD,11); //删除短信
delay1(1000);
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_Opened,13); //发送消息
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(2000);
}
if(((UART0_Data[Len+6]==CLOSE[0])&&(UART0_Data[Len+7]==CLOSE[1])&&(UART0_Data[Len+8]==CLOSE[2])&&(UART0_Data[Len+9]==CLOSE[3])&&(UART0_Data[Len+10]==CLOSE[4])&&(UART0_Data[Len+11]==CLOSE[5])&&(UART0_Data[Len+12]==CLOSE[6]))//移动
||(UART0_Data[Len+3]==CLOSE[0])&&(UART0_Data[Len+4]==CLOSE[1])&&(UART0_Data[Len+5]==CLOSE[2])&&(UART0_Data[Len+6]==CLOSE[3])&&(UART0_Data[Len+7]==CLOSE[4])&&(UART0_Data[Len+8]==CLOSE[5])&&(UART0_Data[Len+9]==CLOSE[6]))//联通
{
JDQ=1; //关闭继电器
Send_Command(Command_AT_CMGD,11); //删除短信
delay1(1000);
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_Closed,13); //发送消息
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(2000);
}
UART0_Data[Len+13]=0x40;UART0_Data[Len+14]=0x40;
UART0_Len=0;
READ_SMS=0;
}
if(ATH==1) //电话打入,需要判断是否为注册号码拨打,是则挂机和结束报警,否则直接挂机
{
Send_Command(Command_ATH,4); //发送挂机命令
delay1(1000);
Send_Message4(); //发送当前温度
ATH=0;
UART0_Len=0; //标志
}
}
void Send_Message(void) //发送到指定号码
{
Send_Command(Command_AT_CMGS,8); //发送指令
delay1(500);
Send_Command(Command_AT_YIN,1); //发送引号
delay1(100);
Send_Command(Command_AT_NUM,11); //发送号码
delay1(100);
Send_Command(Command_AT_YIN,1); //发送引号
delay1(100);
Send_Command(Command_AT_ENTER,1); //发送回车
delay1(100);
}
void Send_Message1(void) //发送警报浓度
{
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_Smoke,37); //发送烟雾报警信息
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(100);
}
void Send_Message2(void) //发送入室盗贼短信息
{
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_Someone,33); //发送警报消息
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(100);
}
void Send_Message3(void) //发送警报温度
{
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_AT_Tem,42); //发送温度
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(100);
}
void Send_Message4(void) //发送当前温度
{
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_AT_Tem,4); //发送温度
delay1(500);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(100);
}
void Send_Message5(void) //发送求救信号
{
Send_Message(); //发送到指定号码
delay1(1000); //等待回复输入符号
Send_Command(Command_Help,35); //发送求救信息
delay1(1000);
Send_Command(Command_AT_End,1); //发送短信结束符
delay1(100);
}
/主程序***********************/
void main()
{
Sys_Init(); //单片机系统初始化
init(); //液晶屏初始化
Delay_0_5s(50); //等待模块初始化
temperature=readtemperature(); //读取实时温度
GSM_Init(); //模块初始化
Send_Command(Command_AT_CMGD1,11); //删除短信第一条短信息,腾出空间接收短信
delay1(500);
TH0=(65536-50000)/256; //50MS定时
TL0=(65536-50000)%256;
ET0=1; //允许T0中断
TR0=1; //开启定时器
LCD_Display_String(1,table1); //显示内容
LCD_Display_String(2,table2); //显示内容
Timer_Counter=50; //第一次直接进入温度读取
while(1)
{
if(Timer_Counter>=20) //每1s读取一次温度 20*50ms=1s
{
Timer_Counter=0; //清除
temperature=readtemperature(); //读取实时温度
}
temperature_dispaly(13,temperature); //显示温度到LCD1602
KEY(); //扫描按键程序
Check(); //检测传感器情况
Read_Message(); //读取短信内容
}
}
/定时器中断服务子程序 无需调用************************/
void Timer0() interrupt 1 //定时器T0中断函数
{
TH0=(65536-50000)/256; //赋初值=50ms
TL0=(65536-50000)%256; //TH0=3C,TL0=B0
Timer_Counter++;
}
/串口中断服务子程序 无需调用 有数据就直接进入************************/
void Serial() interrupt 4
{
RI=0; //接收完毕
UART0_Data[UART0_Len] = SBUF; //存入到对应数组
if(SBUF==0x2B) //+号 表示有短信或者电话打入
{
Len=UART0_Len; //记录序号
}
if((UART0_Data[Len+1]==0x43)&&(UART0_Data[Len+2]==0x4D)&&(UART0_Data[Len+3]==0x54)&&(UART0_Data[Len+4]==0x49))
{ //接收到的内容是短信提示UART0_Data【】="+CMTI",比较前五位
NEW_SMS=1; //短信标志位置一
}
if((UART0_Data[Len+1]==0x43)&&(UART0_Data[Len+2]==0x4D)&&(UART0_Data[Len+3]==0x47)&&(UART0_Data[Len+4]==0x52))
{ //接收到的内容是读取短信提示UART0_Data【】="+CMGR",比较前五位
READ_SMS=1; //读取短信标志位置一
}
if((UART0_Data[Len+1]==0x43)&&(UART0_Data[Len+2]==0x4C)&&(UART0_Data[Len+3]==0x49)&&(UART0_Data[Len+4]==0x50)&&(UART0_Data[Len+5]==0x3A))
{ //接收到的内容是电话提示UART0_Data【】="+CLIP:",比较前6位
ATH=1; //挂机标志位置一
}
UART0_Len++; //序号递增
}
3 系统主程序设计
本设计的软件部分是以单片机的程序作为核心,其他子程序依照主程序来进行设计,整个系统的运行是主程序与各子程序之间的相互配合来完成的。程序首先需要完成各部分的初始化,然后对是否需要对报警电话号码进行调整的判断,然后通过读取各传感器所采集数据来判断是否有报警,在然后根据判断发送报警,如果没有报警则返回[18]~[19]。流程图如图3.1所示。
图3.1主程序流程图
4 软件仿真
5.1软件仿真图
如图5.1所示为软件仿真图。
图5.1软件仿真图
5.2软件仿真详解
首先进行,系统上电,各电路初始化,SIM800L开始读取网络信息,读取完成后LCD显示当前温度值与预设报警温度阈值如图5.2所示。
图5.2 LCD屏显示
然后此时系统已进入正式运行状态,按动“温度加”、“温度减”按钮时,显示屏中预设温度值随其发生变化,如图5.3所示。按动“温度减”,温度阈值也会随之变小,类似于图5.3,这里不再做赘述。
图5.3按动温度加仿真
当改变当前温度,并超过所设温度阈值“50℃”时,灾情灯亮起,同时蜂鸣器也发出报警声,如图5.4所示。
图5.4温度报警仿真
当检测到可燃气体或烟雾时,灾情灯亮起,同时蜂鸣器也发出报警声,如图5.5所示。
当人体红外模块检测到有人时,盗情灯亮起,同时蜂鸣器也发出报警声,如图5.6所示。
图5.5可燃气体报警仿真
图5.6人体红外检测报警仿真
由于仿真无法加入SIM800L模块无法进行与用户交互功能的展示,以上所有“盗情”及“险情”无法进行仿真,同样也无法进行继电器在收到短信后的“断电”与“闭合”的仿真,无法演示其对家电的控制。
结 论
本文从整体到部分详细介绍了智能家居报警控制器的设计。通过查阅大量资料,本文提出了几种可行性方案,对硬件电路的实现方案进行了分析对比,并最终选择了基于GSM模块的实现方案。在比较重要的部分进行了详细的论述,并且给出了程序及说明,其可靠性和稳定性都达到了很好的效果。本设计已经完成了对智能住宅盗情、火情、煤气泄漏等进行自动监测并实现了自动报警功能。经测试,人体电红外传感器的感应范围为6.3m左右;在外界温度超过报警温度值时,DS18B20温度传感器能够准确感应,并发出报警,基本实现预期目的,同时系统还能够辨别不同险情,进行不同的报警,方便主人正确处理险情,使设计跟家智能化、人性化。
本设计中使用的芯片只是当前电子科技发展的一般产物,随着科技的不断发展,更高密度,更高精度的芯片将会取代现有的产品。在现代电子科技的高速发展过程中,微型化、集成化、高密度化以及设备的高精度化已经成为一种长期的趋势,这就要求我们力求使用更精确的设备。
本设计从具有成本较低,功能实用,灵活多样,简便有效等特点,有效的降低了用户住宅遇到和发生险情及其他意外事件的风险,有效的避免了因险情及其他意外事件造成的经济及其他损失,将居民损失降到最小,同时也将提高用户的生活品质水平。