? ? ? ?暑假终究还是结束了,但是既然开学了那么期末还会远吗?然而每当期末总会遇到一些课程设计,我每次总是想要大展拳脚一下,但是面对期末复习,最后更多的是通过为主。所以我整理了一些项目希望可以帮到大家。在文章最后更是附上原理图以及程序以备不时之需。
? ? ? ?本次设计制作的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(); //读数据eeprom
if(a_a == 0xff) //新的单片机初始单片机内问EEPOM
{
a_a = 1;
phone_i = 0;
write_eepom();
}
}
/*************定时器0初始化程序***************/
void time_init()
{
EA = 1; //开总中断
TMOD |= 0X01; //定时器0、工作方式1
ET0 = 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(); //初始化eeprom
init_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; // 50ms
value ++;
if(value % 10 == 0)
{
flag_500ms = 1; //500ms
value = 0;
}
}
void uatr0() interrupt 4
{
if(RI == 1)
{
RI = 0;
}
}
|