暑假终究还是结束了,但是既然开学了那么期末还会远吗?然而每当期末总会遇到一些课程设计,我每次总是想要大展拳脚一下,但是面对期末复习,最后更多的是通过为主。所以我整理了一些项目希望可以帮到大家。在文章最后更是附上原理图以及程序以备不时之需。
本次设计制作的GSM短信防盗报警系统,具有红外报警功能,就是通过热释传感器检测是否有人进入并将报警信息通过GSM模块发短信到指定手机报警。
按照系统设计功能的要求,确定系统以单片机控制电路为核心由时钟电路、复位电路、电源电路、按键电路、1602显示电路、GSM模块电路和传感器电路共同组成。系统结构框图如下所示:
经过反复论证(实际上就是便宜简单)最终确定如下方案:
1.STC89C52单片机作为主控制器。
2.采用热释电红外线传感器采集信息。
3.通过1602液晶显示。
4.矩阵式薄膜按键
5.9V电源供电
6.SIM800L GSM模块报警
一、硬件电路系统设计
1.单片机最小系统设计
注意:由于单片机P0口内部不含上拉电阻,为高阻态,不能正常的输出高/低电平,因而该组端口在使用时必须外接上拉电阻。
下面对STC89C52各引脚的功能进行的介绍:
1)电源引脚Vcc和Vss
Vcc(40脚):电源端为+5V Vss(20脚):接地端。
2)时钟电路引脚XTAL1和XTAL2
XTAL2(18脚):接外部晶体和电容的一端。在单片机内部它是振荡电路反向放大器的输出端,振荡电路的频率就是晶体固有频率。若需采用外部时针电路时,该引脚输入外时钟脉冲。要检查89C52的振荡电路是否正常工作,可用示波器查看XTAL2端是否有脉冲信号输出。
XTAL1(19脚):接外部晶体和微调电容的另一端。在片内,它是振荡电路反向放大器的输入端。在采用外部时钟时,该引脚必须接地。
3)控制信号脚 RST ALE PSEN 和EA。
RST(9脚):RST是复位信号输入端,高电平有效。在此输入端保持两个机器周期(24个时钟振荡周期)的高电平时,就可以完成复位操作。
ALE/PROG(30引脚):地址锁存允许信号端。当STC89C52上电正常工作后,ALE引脚不断向外输出正脉冲信号。此频率为振荡器频率fosc的1/6,当CPU访问片外存储器时,ALE输出信号作为锁存低8位地址的控制信号。在CPU访问片外数据存储时,每取值一次(一个机器周期)会丢失一个脉冲。平时不访问片外存储时,ALE端也以1/6的振荡频率固定输出正脉冲,因而ALE信号可以用作对外输出时钟或定时信号。如果你想看一下STC89C52芯片的好坏,可用示波器查看ALE端是否有脉冲信号输出,如有脉冲信号输出,则STC89C52基本上是好的。ALE的负载驱动能力为8个LS型TTL(低功耗高速TTL)。
PSEN(29脚);程序存储允许输出信号引脚,在访问片外程序存储器时,此端定时输出负脉冲作为读片外存储器的选通信号。此引脚接ERROM的OE端。PSEN端有效,即允许读出ERROM/ROM中的指令码。CPU在从外部ERROM/ROM取指令期间,每个周期PSEN两次有效。不过,在访问片外RAM时,要少产生两次PSEN负脉冲信号。要检查一个STC89C52小系统上电后CPU能否正常到ERROM/ROM中读取指令码,也可用于示波器看PSEN端有无脉冲输出。如有,说明基本上工作正常。
EA/VPP(31脚):外部程序存储器地址允许输入端/固化编程电压输入端。当EA引脚接高电平时,CPU只访问片内ERROM/ROM并执行内部程序存储器中的指令。但在PC(程序计数器)的值超过OFFFH(对8751/8051为4k)时,将自动转向执行片外存储器的程序。当出入信号EA引脚接低电平(接地)时,CPU只访问外部ERROM/ROM并执行外部程序存储器中的指令,而不管是否有片内程序存储器。对于无芯片内的ROM的8031或8032,须外扩ERROM,此时必须将EA引脚接地。如果使用有片内ROM的AT89C52,外扩ERROM也是可以的,但也要使EA接地。
2.显示模块
1602LCD采用标准的14引脚(无背光)或16引脚(带背光)接口,各引脚接口说明如下表所示:
注意:
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
电路如下所示:
3.键盘模块
系统通过薄膜矩阵键盘设置,电路图如图所示:
4.防盗报警电路
下图为热释防盗报警电路,D3、D4为布防指示灯和传感器信号指示灯
二、系统软件设计
单片机系统除了必要的硬件支持外,还需要进行软件设计。主要由主程序、数据查询程序、按键处理程序等组成。
1.主程序设计
主程序是对整个系统框架的描述。此系统的主程序的功能是在上电后,完成系统的初始化,等待控制端信息命令的到达,并根据信息内容完成响应的动作,流程图如下所示:
2.显示程序设计:
如图为LCD1602显示流程图
三:原理图
四:程序
#include <reg52.h>
#include "lcd1602.h"
#define uchar unsigned char
#define uint unsigned int
#include "eepom52.h"uchar i;sbit red = P2^0; //红色发光二极管定义
sbit green = P2^1; //绿色发光二极管定义
sbit yellow = P2^2; //黄色发光二极管定义
sbit beep = P2^3; //蜂鸣器定义
sbit hw = P2^4; //红外热释传感器定义
bit flag_500ms = 0;
uchar flag_alarm ; //报警标志位
uchar flag_bufang ; //布防标志位
uchar flag_bufang_en ; //布防标志位使能
uint flag_value; //用做定时器的变量
bit flag_alarm_en;#define key_io P0
uchar key_can;
uchar a_a;uchar smg_i;
uchar dis_smg[11];
uchar phone_i; //电话号码是多少位
uchar phone_call[11]={" "};
uchar flag_send_en;uint temperature ; //
bit flag_500ms ;
uchar key_can; //按键值的变量
uchar menu_1; //菜单设计的变量
bit flag_lj_en; //按键连加使能
bit flag_lj_3_en; //按键连3次连加后使能 加的数就越大了
uchar key_time; //用做连加的中间变量
bit key_500ms ;
uchar flag_clock; //温度报警变量
uchar menu_shudu = 20; //用来控制连加的速度/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{uint i,j;for(i=0;i<q;i++)for(j=0;j<110;j++);
}#include "gsm.h"/******************把数据保存到单片机内部eepom中******************/
void write_eepom()
{SectorErase(0x2000);for(i=0;i<11;i++)byte_write(0x2000 + i,phone_call[i]);byte_write(0x2020,phone_i);byte_write(0x2059, a_a);
}/******************把数据从单片机内部eepom中读出来*****************/
void read_eepom()
{for(i=0;i<11;i++)phone_call[i] = byte_read(0x2000+i); phone_i = byte_read(0x2020);a_a = byte_read(0x2059);
}/******************初始化eeprom******************/
void init_eeprom() //初始化eeprom
{read_eepom(); //读数据eepromif(a_a == 0xff) //新的单片机初始单片机内问EEPOM{a_a = 1;phone_i = 0;write_eepom(); } }/*************定时器0初始化程序***************/
void time_init()
{EA = 1; //开总中断TMOD |= 0X01; //定时器0、工作方式1ET0 = 1; //开定时器0中断 TR0 = 1; //允许定时器0定时
}/****************独立按键处理函数************************/
void key()
{static uchar key_new = 0,key_old = 0,key_value = 0,key_l;key_io = 0x0f;if(key_new == 0) //按键松开{if(key_io == 0x0f)key_value ++;else key_value = 0;if(key_value >= 5) //按键松开松手检测{key_value = 0;key_new = 1; //按键松开后进入等待按键状态flag_lj_en = 0; //关闭连加使能flag_lj_3_en = 0; //关闭3秒后使能flag_value = 0; //清零write_eepom();}}else {if(key_io != 0x0f) //按键按下key_value ++;else key_value =0;if(key_value >= 5) //按键按下消抖{key_value = 0;key_new = 0; //按键松开后进入等待松开按键状态 key_time = 0;}} key_can = 20;if((key_new == 0) && (key_old == 1)){key_l = (key_io | 0xf0); //矩阵键盘扫描key_io = key_l;switch(key_io){case 0xee: key_can = 1; break; //得到按键值 case 0xde: key_can = 2; break; //得到按键值 case 0xbe: key_can = 3; break; //得到按键值 case 0x7e: key_can = 15; break; //得到按键值 case 0xed: key_can = 4; break; //得到按键值 case 0xdd: key_can = 5; break; //得到按键值 case 0xbd: key_can = 6; break; //得到按键值 case 0x7d: key_can = 14; break; //得到按键值 case 0xeb: key_can = 7; break; //得到按键值 case 0xdb: key_can = 8; break; //得到按键值 case 0xbb: key_can = 9; break; //得到按键值 case 0x7b: key_can = 13; break; //得到按键值 case 0xe7: key_can = 10; break; //得到按键值 case 0xd7: key_can = 0; break; //得到按键值 case 0xb7: key_can = 11; break; //得到按键值 case 0x77: key_can = 12; break; //得到按键值 }} key_old = key_new;
}/****************按键处理数码管显示函数***************/
void key_with()
{ if(key_can == 12) //退出键{menu_1 = 0;init_1602_dis_csf();write_com(0x0c); //关闭光标}if(key_can == 15) //设置键{menu_1 ++;if(menu_1 >= 2){menu_1 = 0;}if(menu_1 == 0){init_1602_dis_csf();write_com(0x0c); //关闭光标}if(menu_1 == 1){write_string(1,0," Input Phone "); write_string(2,0," ");clear_shuzu(dis_smg,11); for(i=0;i<phone_i;i++)dis_smg[i] = 0x30 + phone_call[i]; write_string_num(2,0,dis_smg,phone_i); //显示号码 lcd1602_guanbiao(1,phone_i + 0x40); //开光标 }menu_shudu = 20;}if(menu_1 == 1) //设置短信号码 {if(key_can < 10) //只有数字键{if(phone_i < 11){phone_call[phone_i] = key_can;dis_smg[phone_i] = 0x30 + key_can;phone_i ++;if(phone_i > 11)phone_i = 11;smg_i = phone_i;write_string_num(2,0,dis_smg,phone_i); //显示号码lcd1602_guanbiao(1,0 + phone_i + 0x40); //开光标 } }if(key_can == 10) //删除键{if(phone_i != 0){phone_i --;phone_call[phone_i] = ' '; dis_smg[phone_i] = ' ';write_string(2,0," ");write_string_num(2,0,dis_smg,phone_i); //显示号码 lcd1602_guanbiao(1,0 + phone_i + 0x40); //开光标 } }}
} /******************对应不同按键处理**********************/
void menu_kongwai_dis()
{if(menu_1 == 0){if(key_can == 1) //按键紧急报警{flag_alarm = 1; //报警标志位 ; }if(key_can == 2) //布防按键{flag_bufang_en = 1; } if(key_can == 3) //取消报警 把变量清零{flag_alarm = 0; flag_bufang = 0; flag_bufang_en = 0; flag_value = 0; flag_send_en = 0;beep = 1;red = 1; //关闭红灯green = 1; //关闭绿灯yellow = 1; //关闭黄灯 write_string(1,0," fd system "); write_string(2,0," wei bufang ");}}
}/******************红外报警处理**********************/
void hongwai_dis() // 红外报警处理
{if((flag_alarm == 1)) //报警{red = ~red; //红灯报警beep = ~beep; //蜂鸣器报警}if(menu_1 == 0){if(flag_alarm == 1){if(flag_send_en == 0){flag_send_en = 1; write_string(1,0," fang dao alarm "); send_PUD_fangdao(); //发送报警信息 请注意!温度报警。 }}}yellow = ~hw; //红外热释电指示灯 有输出就亮黄灯if(flag_bufang_en == 1) //准备开始布防{green = ~green; //绿灯闪 } if(flag_bufang == 1) //确认布防{green = 0; //如果延时布防成功 绿灯长亮if(hw == 1) //红外有输出{flag_alarm = 1; }}if(flag_bufang_en == 1){flag_value ++;if(flag_value >= 30) //15秒{flag_bufang = 1;flag_bufang_en = 0; flag_value = 0; write_string(2,0," yi bufang ");}}
}void main()
{ time_init(); //初始化定时器 init_1602();init_1602_dis_csf();init_uart();init_eeprom(); //初始化eeprominit_gsm();while(1){ if(flag_500ms == 1) //500ms 处理一次温度程序{ flag_500ms = 0; hongwai_dis(); // 红外报警处理}key(); //按键程序if(key_can < 20){key_with(); //设置报警温度 menu_kongwai_dis();}}
}/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{ static uchar value;TH0 = 0x3c;TL0 = 0xb0; // 50msvalue ++; if(value % 10 == 0){flag_500ms = 1; //500msvalue = 0;}
}void uatr0() interrupt 4
{if(RI == 1){RI = 0;}
}