51单片机项目设计:基于51单片机 无线防盗报警器设计

2023-12-23 18:35:15


哔哩哔哩视频链接: 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设计

接收设备
5YyW5L2c5bCY,size_20,color_FFFFFF,t_70,g_se,x_16)
发送设备
在这里插入图片描述

五、程序设计

/**************************************************************************************
*项目名称:无线防盗系统主机
作者:化作尘
版本: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;
    }
}





文章来源:https://blog.csdn.net/mbs520/article/details/134686707
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。