功能介绍:
0.本系统采用STC89C52作为单片机
1.系统采用LCD1602作为显示液晶实时显示数据
2.采用GSM作为通信模块,当发生被盗嫌疑时候发送短信给手机
3.系统带有手机靠近自动解锁功能,同时也带有红外遥控解锁功能
4.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
#include "lcd1602.h"
#include "delay.h"
#include "infrared.h"
#include "gsm_at.h"
#include "data_unit.h"
#include "uart.h"
#include "eeprom52.h"
sbit KEY_OPEN = P3^3; //引脚定义
sbit KEY_CLOSE = P3^5;
sbit LED_GREEN = P2^1;
sbit LED_RED = P2^2;
sbit BUZZER = P2^0;
#define BUZZER_ON (BUZZER = 0)
#define BUZZER_OFF (BUZZER = 1)
sbit BLUETOOTH_PIN = P1^4; //蓝牙自动解锁控制引脚
sbit SHAKE_PIN = P1^1; //震动传感器
sbit HC_SR501 = P1^0; //人体活动传感器
sbit RELAY_LOCK = P2^3; //电磁锁
bit g_irFlag = 0; //红外接收标志,收到一帧正确数据后置1
unsigned char g_irCode[4];
unsigned char refreshFlag = 0; //更新显示标志
unsigned char setFlag = 0; //设置参数标志
bit lockFlag = 1; //锁的状态标志
bit monitorFlag = 0; //监控标志
bit alarmFlag = 0; //报警标志
unsigned char time500msCnt = 0;
unsigned char time500msCnt2 = 0;
bit oldPinState = 0;
bit nowPinState = 0;
char dis0[16]; //定义显示区域临时存储数组
void CheckKey(void);
void CheckBluetooth(void);
void Timer1_Init(void); //定时器初始化
void main(void)
{
IR_INPUT = 1;
Timer1_Init();
IR_Init();
Uart_Init();
LCD_Init(); //初始化液晶
DelayMs(200); //延时有助于稳定
LCD_Clear(); //清屏
LCD_DispStr(0, 0, " Welcome! ");
DelayS(1);
LCD_DispStr(0, 0, " Waiting... ");
DelayS(5);
err_num = GSM_Init(); //GSM初始化
DelayMs(10);
if (gsm_init_flag) //初始化完成
{
err_num = GSM_Text_Mode(); //GSM 设置Text模式
}
DelayMs(10);
if (gsm_config_flag)
{
err_num = GSM_Delete_Sms("1"); //删除短信1
}
DelayMs(10);
if (!(gsm_init_flag || gsm_config_flag || gsm_delete_flag)) // AT命令报错
{
BUZZER_ON;
LCD_DispStr(0, 0, " Init Err Num ");
LCD_WriteData((int)err_num+'0');
DelayS(1);
BUZZER_OFF;
}
else
{
LCD_DispStr(0, 0, " Init OK! ");
}
DelayS(3);
EEPROM52_Init(); //初始化电话号码
LCD_DispStr(0, 0, " Status ");
while (1) //主循环
{
gsm_receive_process(); //gsm接收处理
if (lockFlag == 1) //已上锁
{
LED_RED = 0;
LED_GREEN = 1;
RELAY_LOCK = 1; //关闭锁
if (alarmFlag == 0)
{
if (HC_SR501 == 0 && SHAKE_PIN == 0) //有人且震动
monitorFlag = 1;
if (monitorFlag == 1) //进入监控状态
{
if (time500msCnt >= 10 && time500msCnt <= 20) //进入监控模式后的5s~10s,持续监测
{
if (HC_SR501 == 0 && SHAKE_PIN == 0) //再次检测到有人且震动
{
alarmFlag = 1;
time500msCnt = 0;
BUZZER_ON;
LCD_DispStr(0, 1, " Warning! ");
GSM_Send_Sms(phone1, "Please pay attention to your car!");
DelayMs(10);
}
}
else if (time500msCnt > 20) //超过10s没检测到
{
monitorFlag = 0; //退出监控
time500msCnt = 0;
}
}
else
{
time500msCnt = 0;
BUZZER_OFF;
}
}
else //报警模式
{
if (time500msCnt >= 120) //响铃1分钟退出报警模式
{
alarmFlag = 0;
}
}
}
else
{
LED_RED = 1;
LED_GREEN = 0;
alarmFlag = 0;
monitorFlag = 0;
RELAY_LOCK = 0; //打开锁
BUZZER_OFF;
}
if (refreshFlag == 1) //刷新界面
{
refreshFlag = 0;
TR1 = 0;
if (lockFlag == 1) //已上锁
{
if (alarmFlag == 0)
{
if (monitorFlag == 1) //进入监控状态
{
time500msCnt++;
}
else
{
time500msCnt = 0;
LCD_DispStr(0, 1, " Lock ");
}
}
else //报警模式
{
time500msCnt++;
}
}
else
{
LCD_DispStr(0, 1, " Open ");
if (time500msCnt2 > 0)
{
time500msCnt2--;
}
else
{
RELAY_LOCK = 0; //关闭锁
LED_RED = 0;
LED_GREEN = 1;
lockFlag = 1;
}
}
TR1 = 1;
}
CheckKey(); //检测按键
CheckBluetooth(); //检测蓝牙自动解锁控制引脚
}
}
void CheckKey(void)
{
static unsigned char rekey = 0;
if ((KEY_OPEN == 0) || (KEY_CLOSE == 0)) //检测到按键按下
{
DelayMs(10); //小抖动
if (rekey == 0)
{
if (KEY_OPEN == 0) //检测是否按下
{
rekey = 1;
lockFlag = 0;
time500msCnt2 = 20; //开锁20*500ms=10s
}
else if (KEY_CLOSE == 0) //
{
rekey = 1;
lockFlag = 1;
}
}
}
else
{
rekey = 0; //防止重复检测到按键
}
if (g_irFlag == 1 && g_irCode[2] == IRCodeMap[0][0])
{
lockFlag = 0;
g_irFlag = 0;
time500msCnt2 = 20; //开锁20*500ms=10s
}
else if (g_irFlag == 1 && g_irCode[2] == IRCodeMap[2][0])
{
lockFlag = 1;
g_irFlag = 0;
}
}
void CheckBluetooth(void)
{
nowPinState = BLUETOOTH_PIN;
if (oldPinState == 0 && nowPinState == 1) //检测到蓝牙自动解锁控制引脚上升沿
{
DelayMs(10);
if (BLUETOOTH_PIN == 1)
{
lockFlag = 0; //开锁
time500msCnt2 = 20; //开锁20*500ms=10s
}
}
oldPinState = nowPinState;
}
/**************************************************************************************************
*************************************红外解码定时器程序********************************************
**************************************************************************************************/
//外部中断解码程序_外部中断0
void Ext0_Interrupt(void) interrupt 0
{
unsigned char i, j;
unsigned char byt;
unsigned int time;
time = IR_GetLowTime();
if ((time < 7833) || (time > 8755))
{
IE0 = 0;
return;
} //找到启始码
time = IR_GetHighTime();
if ((time < 3686) || (time > 4608)) //时间判定范围为4.0~5.0ms,
{ //超过此范围则说明为误码,直接退出
IE0 = 0;
return;
}
//接收并判定后续的4 字节数据
for (i = 0; i < 4; i++) //循环接收4 个字节
{
for (j = 0; j < 8; j++) //循环接收判定每字节的8 个bit
{
//接收判定每bit 的560us 低电平
time = IR_GetLowTime();
if ((time < 313) || (time > 718)) //时间判定范围为340~780us,
{ //超过此范围则说明为误码,直接退出
IE0 = 0;
return;
}
//接收每bit 高电平时间,判定该bit 的值
time = IR_GetHighTime();
if ((time > 313) && (time < 718)) //时间判定范围为340~780us,
{ //在此范围内说明该bit 值为0
byt >>= 1; //因低位在先,所以数据右移,高位为0
}
else if ((time > 1345) && (time < 1751)) //时间判定范围为1460~1900us,
{ //在此范围内说明该bit 值为1
byt >>= 1; //因低位在先,所以数据右移,
byt |= 0x80; //高位置1
}
else //不在上述范围内则说明为误码,直接退出
{
IE0 = 0;
return;
}
}
g_irCode[i] = byt; //接收完一个字节后保存到缓冲区
}
g_irFlag = 1; //接收完毕后设置标志
IE0 = 0; //退出前清零INT0 中断标志
}
/**************************************************************************************************
***************************************************************************************************
**************************************************************************************************/
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Timer1_Init(void)
{
TMOD &= 0x0F; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH1 = (65536 - 18432) / 256; //重新赋值 20ms
TL1 = (65536 - 18432) % 256;
EA = 1; //总中断打开
ET1 = 1; //定时器中断打开
TR1 = 1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer1_Interrupt(void) interrupt 3
{
static unsigned char time20ms = 0;
TH1 = (65536 - 18432) / 256; //重新赋值 20ms
TL1 = (65536 - 18432) % 256;
time20ms++;
if (time20ms >= 25)
{
refreshFlag = 1;
time20ms = 0;
}
}