文章目录
- 项目背景
- 一、项目功能
- 二、材料选择
- 三、接收设备原理图设计
- 四、发送设备原理图设计
- 四、PCB设计
- 五、程序设计
哔哩哔哩视频链接: https://www.bilibili.com/video/BV1Wc411C7xH/?vd_source=e5082ef80535e952b2a4301746491be0
实物链接:https://m.tb.cn/h.56p9mFa?tk=3RLwWYHTa1C CZ0001
项目背景
此项目为做坏事、防盗、布防而设计,设计最大4个点位布防,布防点位有人会报警,布防点距离主机可达100-200米,遇到遮挡距离会减少。
场景1 :防盗
当家里有一间或者多间房间内部有重要或者贵重物资时,可以每间房放置一个发送器,接收器放置在有人监控区域内,当有人进入其中一个房间,就会报警,并显示是哪一间房间的报警器触发报警
场景2:做坏事
当你想去某个富豪家里偷东西时,你可以把布防点位设置在门口,走廊,或者大门,当你在屋子里偷盗的时候,可以不用观察是否有人闯入,放心偷盗,听到手机的主机报警后,第一时间找路线逃跑
场景3:护法
当你要在一个户外树林做私密的事情又害怕周围有人过来,你可以以你为中心,放置一个圆形区域的布防点,当你正在做私密事情的时候只需要注意听是否报警,听到报警立马停止做私密的事情,防止被人发现
一、项目功能
1、可以显示当前时间、星期、日期
2、可以修改当前时间、星期、日期
3、一台主机接收报警信号,多台从机发送报警信号,发送器可以无线发送200米距离到主机,主机显示是那台从机触发送的报警信号
4、一键开启关闭布防
5、查看报警记录,并记录报警时间
二、材料选择
(一)主控选择:STC89C52RC
STC89C52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
(二)显示屏选择:LCD1602
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能有所不同,但使用方法都是一样的。为了降低成本,绝大多数制造商都直接将裸片做到板子上。
(三)时钟芯片选择:DS1302
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。
(四)无线发送接收器
(五)外围器件:按键、蜂鸣器、开关、纽扣电池、电位器、三极管等
三、接收设备原理图设计
(一)最小系统
供电、晶振、复位电路
在这里插入图片描述
(二)显示屏电路
数据线接到P0,注意要接1K上拉电阻
(三)时钟芯片电路
3个引脚接到单片机IO口控制
(四)按键电路
(五)无线传感器
(六)电源电路与电源指示
四、发送设备原理图设计
采用人体热释电红外传感器,捕捉人体红外判断是否有人在传感器附近
发送设备,人体热释电传递信号给发送模块,无线发送到主机
四、PCB设计
接收设备
发送设备
五、程序设计
/**************************************************************************************
*项目名称:无线防盗系统主机
作者:化作尘
版本:V1.3
邮箱:2809786963@qq.com
更新时间:V1.1 2020年4月11日14:30:06
V1.2 2020年4月18日20:51:31
V1.3 2023年11月19日08点33分
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "ds1302.h"
#include "lcd.h"
#include "eeprom.h"
#include "temp.h"
#define TIME_SAVE_ID 0X56
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k1 = P1^0; //按键
sbit k2 = P1^1;
sbit k3 = P1^2;
sbit k4 = P1^3;
sbit sen1 = P1^6; //传感器
sbit sen2 = P1^7;
sbit sen3 = P3^2;
sbit sen4 = P3^3;
sbit lcdled = P2^4; //lcd背光
sbit beep = P1^4; //蜂鸣器
u16 ti=0; //修改第几个时间参数 、修改第几个闹钟参数
u8 status = 0; //接收信号标志
u8 countalm=0;
uchar lastTIME[7] = {0};
enum ALMSWITCH //定义枚举、报警布防开关
{
OFF,ON
} almswitch;
enum Mode //定义枚举、三种模式
{
DISPLAYDATA,MODIFYDATA,TIMERECORD,NONE
} mode = DISPLAYDATA;
#define RECODE_NUM 12
uchar timerecord[RECODE_NUM][8] = {0};//记录十二组报警时间
void dis_sen_num(u8 num);
void display_alm_state(u8 en);
/*********延时函数***********/
void delay(unsigned int t) //短延时
{
while(t--);
}
/*********延时函数***********/
void delay_ms(unsigned int t) //毫秒延时
{
unsigned int a,b;
for(a=0; a<t; a++)
for(b=0; b<120; b++);
}
/*********对比时间改变***********/
u8 cmp_last_time(void) //对比时间改变
{
u8 i;
for(i=0; i<7; i++)
if(lastTIME[i] != TIME[i])return i;
return 0xff;
}
/*********清除时间,刷新**********/
void clr_last_time(void)
{
u8 i;
for(i=0; i<7; i++)
lastTIME[i] = 0;
}
//扫描传感器状态
void scan_sensor_state(void)
{
static u16 count=0;
u8 n;
u8 r_sen1,r_sen2,r_sen3,r_sen4;
static u8 lastsen1,lastsen2,lastsen3,lastsen4;
if(almswitch==ON) //开启布防
{
r_sen1 = sen1;
r_sen2 = sen2;
r_sen3 = sen3;
r_sen4 = sen4;
if(r_sen1 != lastsen1 && r_sen1 == 1)
status = 1;
if(r_sen2 != lastsen2 && r_sen2 == 1)
status = 2;
if(r_sen3 != lastsen3 && r_sen3 == 1)
status = 3;
if(r_sen4 != lastsen4 && r_sen4 == 1)
status = 4;
lastsen1 = r_sen1;
lastsen2 = r_sen2;
lastsen3 = r_sen3;
lastsen4 = r_sen4;
if(status)
{
//显示报警
LcdClean();
LcdWriteCom(0x80);
LcdWritestr("Alarm!");
dis_sen_num(status);
mode = NONE;
Ds1302ReadTime(); //更新时间
//记录报警
count=60000; //设置报警时间长度
for(n=0; n<7; n++)
{
timerecord[countalm][n] = TIME[n];
}
timerecord[countalm][7] = status; //标志传感器
countalm++;
if(countalm == RECODE_NUM)countalm =0;
status = 0;
}
if(count>0) //报警程序
{
count--;
if(count % 1000 == 999)
beep=!beep;
if(count==0) {
beep = 0;
mode = DISPLAYDATA;
LcdClean();
clr_last_time(); //刷新显示
display_alm_state(1);//显示 ON OFF
}
}
}
}
void display_alm_state(u8 en)
{
static u8 last_al = 0xff;
if(en || last_al != almswitch)
{
LcdWriteCom(0xcd);
if(almswitch==OFF) //显示布防状态
LcdWritestr("OFF");
if(almswitch==ON)
LcdWritestr("ON ");
last_al = almswitch;
}
}
/*********显示温度***********/
void displaytemp(int temp) //显示温度
{
float tp;
static char flag = 1;
if(temp< 0)
{
LcdWriteCom(0xca);
LcdWriteData('-');
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
LcdWriteCom(0xca);
LcdWriteData('+');
tp=temp;
temp=tp*0.0625*100+0.5;
}
if(flag)
{
flag =0;
temp = 2600;
}
if(temp==8500)
return ;
LcdWriteData(temp % 10000 / 1000 + 0x30);
LcdWriteData(temp % 1000 / 100 + 0x30);
LcdWriteData('.');
LcdWriteData(temp % 100 / 10 + 0x30);
LcdWriteData(temp % 10 + 0x30);
}
/********显示日期、时间、星期***********/
void display_mdf(u8 num,u8 disen)
{
if(disen) {
switch(num)
{
case 0:
LcdWriteCom(0xC7);
LcdWriteData(TIME[0]/16+0x30); //秒
LcdWriteData(TIME[0]%16+0x30);
break;
case 1:
LcdWriteCom(0xC4);
LcdWriteData(TIME[1]/16+0x30); //分
LcdWriteData(TIME[1]%16+0x30);
LcdWriteData(':');
break;
case 2:
LcdWriteCom(0xC1);
LcdWriteData(TIME[2]/16+0x30); //时
LcdWriteData(TIME[2]%16+0x30);
LcdWriteData(':');
break;
case 3:
LcdWriteCom(0x87);
LcdWriteData('-');
LcdWriteData(TIME[3]/16+0x30); //日
LcdWriteData(TIME[3]%16+0x30);
break;
case 4:
LcdWriteCom(0x84);
LcdWriteData('-');
LcdWriteData(TIME[4]/16+0x30); //月
LcdWriteData(TIME[4]%16+0x30);
break;
case 5:
LcdWriteCom(0x8C);
switch(TIME[5]) //显示星期
{
case 0:
LcdWritestr("Mon");
break;
case 1:
LcdWritestr("Tue");
break;
case 2:
LcdWritestr("Wed");
break;
case 3:
LcdWritestr("Thu");
break;
case 4:
LcdWritestr("Fri");
break;
case 5:
LcdWritestr("Sat");
break;
case 6:
LcdWritestr("Sun");
break;
}
break;
case 6:
LcdWriteCom(0x80);
LcdWritestr("20");
LcdWriteData(TIME[6]/16+0x30); //年
LcdWriteData(TIME[6]%16+0x30);
break;
case 7:
LcdWriteCom(0xCD);
LcdWritestr(" OK");
break;
case 8:
break;
}
}
else {
switch(num) //选择进入修改参数
{
case 0:
LcdWriteCom(0xc7);
LcdWritestr(" ");
break;
case 1:
LcdWriteCom(0xc4);
LcdWritestr(" ");
break;
case 2:
LcdWriteCom(0xc1);
LcdWritestr(" ");
break;
case 3:
LcdWriteCom(0x88);
LcdWritestr(" ");
break;
case 4:
LcdWriteCom(0x85);
LcdWritestr(" ");
break;
case 5:
LcdWriteCom(0x8c);
LcdWritestr(" ");
break;
case 6:
LcdWriteCom(0x80);
LcdWritestr(" ");
break;
case 7:
LcdWriteCom(0xce);
LcdWritestr(" ");
break;
}
}
}
/*******************************************************************************
* 函 数 名 : get_keyval()
* 函数功能 : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
u8 get_key_val(void)
{
static u8 key_up1=1; //按键松开标志位
static u8 key_up2=1; //按键松开标志位
static u8 key_up3=1; //按键松开标志位
static u8 key_up4=1; //按键松开标志位,
if(k1==0 && key_up1==1)//判断按键是否按下
{
delay_ms(10);//延时消抖
key_up1=0;//按下状态,(防止循环执行按键控制程序)
if(k1==0) //再次判断,排除是松开状态或外界杂波干扰
{
return 1;
}
}
else if(k1==1) key_up1=1;
if(k2==0 && key_up2==1)//判断按键是否按下
{
delay_ms(10);//延时消抖
key_up2=0;//按下状态,(防止循环执行按键控制程序)
if(k2==0) //再次判断,排除是松开状态或外界杂波干扰
{
return 2;
}
}
else if(k2==1) key_up2=1;
if(k3==0 && key_up3==1)//判断按键是否按下
{
delay_ms(10);//延时消抖
key_up3=0;//按下状态,(防止循环执行按键控制程序)
if(k3==0) //再次判断,排除是松开状态或外界杂波干扰
{
return 3;
}
}
else if(k3==1) key_up3=1;
if(k4==0 && key_up4==1)//判断按键是否按下
{
delay_ms(10);//延时消抖
key_up4=0;//按下状态,(防止循环执行按键控制程序)
if(k4==0) //再次判断,排除是松开状态或外界杂波干扰
{
return 4;
}
}
else if(k4==1) key_up4=1;
return 0;
}
/*******************************************************************************
* 函 数 名 : keypros
* 函数功能 : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros() //初始页面按键检测
{
u8 keyval = 0;
keyval = get_key_val();
switch(keyval)
{
case 1:
mode+= 1;
// LcdClean();
display_mdf(7,1); //显示OK
if(mode == NONE)mode = DISPLAYDATA;
break;
case 2:
beep = !beep;
break;
case 3:
lcdled=!lcdled;
break;
case 4:
almswitch = !almswitch;
break;
}
}
/*************修改时间************/
void modify(void)
{
static int time=0;
u8 keyval = 0;
keyval = get_key_val();
time++;
switch(keyval)
{
case 1:
mode+= 1;
LcdClean();//清屏
if(mode == NONE)mode = DISPLAYDATA;
break;
case 2:
display_mdf(ti,1);
ti++;
if(ti == 8)ti=0;
break;
case 3:
{
switch(ti)
{
case 0:
TIME[0]=0;
break;
case 1:
TIME[1]++;
if(TIME[1]%16 == 0x0a)
{
TIME[1] += 16;
TIME[1] &= 0xf0;
}
if(TIME[1]==0x60)TIME[1]=0;
break;
case 2:
TIME[2]++;
if(TIME[2]%16 == 0x0a)
{
TIME[2] += 16;
TIME[2] &= 0xf0;
}
if(TIME[2]==0x24)TIME[2]=0;
break;
case 3:
TIME[3]++;
if(TIME[3]%16 == 0x0a)
{
TIME[3] += 16;
TIME[3] &= 0xf0;
}
if(TIME[3]==0x32)TIME[3]=0;
break;
case 4:
TIME[4]++;
if(TIME[4]%16 == 0x0a)
{
TIME[4] += 16;
TIME[4] &= 0xf0;
}
if(TIME[4]==0x13)TIME[4]=0;
break;
case 5:
TIME[5]++;
if(TIME[5]==7)TIME[5]=0;
break;
case 6:
TIME[6]++;
if(TIME[6]%16 == 0x0a)
{
TIME[6] += 16;
TIME[6] &= 0xf0;
}
if(TIME[6]==0xa0)TIME[6]=0;
break;
case 7:
mode=DISPLAYDATA;
ti=0;
break; //年
}
}
break;
case 4:
{
switch(ti)
{
case 0:
TIME[0]=0;
break;
case 1:
TIME[1]--;
if(TIME[1]%16==0x0f && TIME[1]!=0xff)
{
TIME[1] &= 0xf9;
}
if(TIME[1]==0xff)TIME[1]=0x59;
break;
case 2:
TIME[2]--;
if(TIME[2]%16==0x0f && TIME[2]!=0xff)
{
TIME[2] &= 0xf9;
}
if(TIME[2]==0xff)TIME[2]=0x23;
break;
case 3:
TIME[3]--;
if(TIME[3]%16==0x0f && TIME[3]!=0xff)
{
TIME[3] &= 0xf9;
}
if(TIME[3]==0xff)TIME[3]=0x31;
break;
case 4:
TIME[4]--;
if(TIME[4]%16==0x0f && TIME[4]!=0xff)
{
TIME[4] &= 0xf9;
}
if(TIME[4]==0xff)TIME[4]=0x12;
break;
case 5:
TIME[5]--;
if(TIME[5]==0xff)TIME[5]=6;
break;
case 6:
TIME[6]--;
if(TIME[6]%16==0x0f && TIME[6]!=0xff)
{
TIME[6] &= 0xf9;
}
if(TIME[6]==0xff)TIME[6]=0x99;
break;
case 7:
Ds1302Init(); //时钟初始化
mode = DISPLAYDATA; //返回日期
ti = 0; //还原初始修改
break; //年
}
}
break;
}
if(time == 500)
display_mdf(ti,1);
else if(time == 1000)
display_mdf(ti,0);
else if(time>1000) time=0;
}
void dis_sen_num(u8 num)
{
LcdWriteCom(0xCB);
switch(num)
{
case 0:
LcdWritestr(" ");
break;
case 1:
LcdWritestr("SEN1");
break;
case 2:
LcdWritestr("SEN2");
break;
case 3:
LcdWritestr("SEN3");
break;
case 4:
LcdWritestr("SEN4");
break;
case 5:
LcdWritestr("SEN5");
break;
}
}
/*************报警时间记录****************/
void alarmrecord(void)
{
static char num=0,last_num = 1;
u8 keyval = 0;
keyval = get_key_val();
switch(keyval)
{
case 1:
mode+= 1;
last_num = 0xff;
LcdClean();
display_alm_state(1);//显示 ON OFF
clr_last_time(); //刷新显示
if(mode == NONE)mode = DISPLAYDATA;
return ;
break;
case 2:
break;
case 3:
num--;
if(num == -1)num = 11;
break;
case 4:
num++;
if(num == 12)num = 0;
break;
}
if(last_num != num)
{
if(timerecord[num][7]!=0)
{
LcdWriteCom(0x80);
LcdWritestr("20");
LcdWriteData(timerecord[num][6]/16+0x30); //年
LcdWriteData(timerecord[num][6]%16+0x30);
LcdWriteData('-');
LcdWriteData(timerecord[num][4]/16+0x30); //月
LcdWriteData(timerecord[num][4]%16+0x30);
LcdWriteData('-');
LcdWriteData(timerecord[num][3]/16+0x30); //日
LcdWriteData(timerecord[num][3]%16+0x30);
LcdWritestr(" ");
if((num+1)>9)
{
LcdWriteData('['); //显示编号
LcdWriteData((num+1)/10+0x30);
LcdWriteData((num+1)%10+0x30);
LcdWriteData(']');
}
else
{
LcdWriteData('['); //显示编号
LcdWriteData((num+1)+0x30);
LcdWritestr("] ");
}
LcdWriteCom(0xC0);
LcdWriteData(' ');
LcdWriteData(timerecord[num][2]/16+0x30); //时
LcdWriteData(timerecord[num][2]%16+0x30);
LcdWriteData(':');
LcdWriteData(timerecord[num][1]/16+0x30); //分
LcdWriteData(timerecord[num][1]%16+0x30);
LcdWriteData(':');
LcdWriteData(timerecord[num][0]/16+0x30); //秒
LcdWriteData(timerecord[num][0]%16+0x30);
dis_sen_num(timerecord[num][7]);
}
else
{
LcdClean();
LcdWriteCom(0x80);
LcdWritestr("no data");
LcdWriteCom(0x8c);
if((num+1)>9)
{
LcdWriteData('['); //显示编号
LcdWriteData((num+1)/10+0x30);
LcdWriteData((num+1)%10+0x30);
LcdWriteData(']');
}
else
{
LcdWriteData('['); //显示编号
LcdWriteData((num+1)+0x30);
LcdWritestr("] ");
}
}
}
last_num = num;
}
/*******************************************************************************
* 函 数 名 : Int1Init()
* 函数功能 : 设置外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0Init()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
//设置INT1
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。
EA=1;//打开总中断
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{
u8 dat=0;
int ucount=0,t=0;
beep = 0;
LcdInit(); //lcd初始化
LcdWriteCom(0x80);
LcdWritestr("Wireless Alarm");
LcdWriteCom(0xc0);
LcdWritestr(" System ");
delay_ms(2000);
if(byte_read(0x2001) != TIME_SAVE_ID)
{
SectorErase(0x2001);
byte_write(0x2001,TIME_SAVE_ID); //执行一遍初始化
Ds1302Init(); //时钟初始化
}
Ds18b20Init(); //温度传感器初始化
//Int0Init(); //外部中断0初始化
//Timer0Init(); //定时器初始化
LcdClean();
status = 0; //接收信号标志
while(1)
{
scan_sensor_state();//布防报警扫描
switch(mode) //模式选择
{
case DISPLAYDATA: //时间显示模式
t++;
if(t == 4000)
{
t = 0;
Ds1302ReadTime(); //更新时间
dat = cmp_last_time(); //得到要更新的参数
display_alm_state(0);//显示 ON OFF
// displaytemp(Ds18b20ReadTemp());//显示温度
while(dat != 0xff)
{
display_mdf(dat,1);
lastTIME[dat] = TIME[dat];
dat = cmp_last_time();
}
}
keypros(); //按键检测
break;
case MODIFYDATA: //时间修改模式
modify();
break;
case TIMERECORD: //时间记录模式
// t++;
// if(t == 1000)
// {
// t = 0;
// Ds1302ReadTime(); //更新时间
// }
alarmrecord(); //查看报警记录
break;
}
}
}
/*******************************************************************************
* 函 数 名 : Int1() interrupt 2
* 函数功能 : 外部中断0的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0() interrupt 0 //外部中断0的中断函数
{
delay_ms(5);
if(P3^2==1 && almswitch==ON)
{
status=3;
}
}
void Int1() interrupt 2 //外部中断1的中断函数
{
delay_ms(5);
if(P3^3==1 && almswitch==ON)
{
status=4;
}
}