1.项目接线
接线示意图和实物图
示意图:
实物图:
信号传输路线
路线1: 433遥控信号 ——> 433接收模块D0引脚以及D1引脚 ——> 单片机P1^2引脚以及P1^3引脚 ——> 单片机P1^1引脚 ——> 继电器IN引脚 ——> 继电器COM口和NO口 ——> 高功率喇叭(负载)所在电路
路线2:振动信号 ——> 振动传感器DO引脚 ——> 单片机P3^3引脚 ——> 单片机P1^1引脚 ——> 继电器IN引脚 ——> 继电器COM口和NO口 ——> 高功率喇叭(负载)所在电路
2.项目实现流程
基本控制逻辑
- 业务需求:
功能1:遥控器按下按键,上锁,并长响一声示意。
功能2:上锁后,如果振动传感器检测到振动后(被人骑走,被人推倒),导通继电器,继电器控制高功率喇叭开始报警。
功能3:遥控器按下按键,解锁,并短响一声示意,之后发生振动也不会报警。
功能4:电动车被人偷走,手机app打开地图显示电动车位置(高阶功能,现在不考虑
- 控制逻辑: 可以看出本简易项目包含两种模式。
- 警报模式
- 振动后报警
- 强制解除报警
- 解除警报模式
Debug成功,完事
代码心得:
- 本代码使用查询法,查询法中加入警报标志位alarmFlag。(也可以不定义警报标志位)
- I/O口连得一多(负载多的时候),我的51单片机中间那部分VCC和GND引脚如果出于连接状态好像会阻止程序烧录,所以需要停止下载,然后拔掉那部分杜邦线,等到程序烧录完成后再接回去。
可以优化的地方:
- 假如你多次重复按下同一个按键,提示音不会继续响。
- BUG:我们面对“警报模式中一直受到振动后无法用按键立马解除警报模式”这一问题,也就是信号丢失问题,我们以下代码的解决方法对从STC-ISP的程序延时计算器中拷贝来的延时函数进行修改,加一个判断。更好的解决方法是用中断的方法,因为一直振动导致的结果不就是程序一直在数数嘛,那么我们遇到变故后先把数数这段代码挂起,强制去执行别的代码。我们以后会学到。
-
思路:
宏定义: #define remote_ON 1 //根据433接收模块信号表现,高电平代表接收到信号,代表按键按下 #define alarm_ON 1 //代表进入警报模式 #define alarm_OFF 0 //代表关闭警报模式 全局变量: 1.sbit指令找到P3这个I/O口组的第3位,将p3.3口作为输入口,接入振动传感器的DO口,变量名vibrate 2.sbit指令找到P1这个I/O口组的第2位,将p1.2口作为输入口,接入433接收模块的DO口,这个口对应遥控器的按键A,变量名是remote433_D0 3.sbit指令找到P1这个I/O口组的第3位,将p1.3口作为输入口,接入433接收模块的D1口,这个口对应遥控器的按键B,变量名是remote433_D1 4.sbit指令找到P1这个I/O口组的第1位,将P1.1口作为输出口,接上继电器的IN引脚,变量名是relay f1. 延时函数,用于进入警报模式后长响2s: void Delay2000ms(); f2. 延时函数,用于进入警报模式后长响1s: void Delay1000ms(); f3. 延时函数,用于警报模式下受到振动后长响5s: int Delay5000ms(); //针对BUG对其进行了修改 1. while死循环,查询法, /* 如果按下遥控器的A按键,设定为报警模式 */ 1.1 判断是否按下按键A: 判据是 remote433_D0 == remote_ON 1.1.1 如果是,则说明按下 修改代表警报是否开启的标志位循环变量alarmFlag: alarmFlag = alarm_ON; 接通继电器: relay = 0; 让喇叭响两秒,作为提示音: Delay2000ms(); 断开继电器: relay = 1; 1.1.2 否则,就啥也不干 /* 如果按下遥控器的B按键,设定为关闭报警模式 */ 1.2 判断是否按下按键B: 判据是 remote433_D1 == remote_ON 1.2.1 如果是,则说明按下 修改代表警报是否开启的标志位循环变量alarmFlag: alarmFlag = alarm_OFF; 接通继电器: relay = 0; 让喇叭响一秒,作为提示音: Delay1000ms(); 断开继电器: relay = 1; 1.2.2 否则,就啥也不干(不管有没有受到振动) /* 如果警报模式下发生振动,喇叭响 */ 1.3 通过alarmFlag判断是否处于报警状态 1.3.1 如果是, 1.3.1.1 接着判断是否感应到振动: 判据是 vibrate == 0 1.3.1.1.1 如果是,则说明需要警报 接通继电器: relay = 0; 让喇叭响五秒: Delay5000ms(); 让喇叭响五秒: Delay5000ms(); 1.2.1.1.2 否则,说明没有受到振动 断开继电器: relay = 1; 1.3.2 否则,就啥也不干
-
代码:
#include "reg52.h" #include "intrins.h" #define remote_ON 1 //根据433接收模块信号表现,高电平代表接收到信号,代表按键按下 #define alarm_ON 1 //代表进入警报模式 #define alarm_OFF 0 //代表关闭警报模式 sbit vibrate = P3^3; //p3.3口作为输入口,接入振动传感器的DO口 sbit remote433_D0 = P1^2; //P1.2口作为输入口,接入433接收模块的DO口,这个口对应遥控器的按键A sbit remote433_D1 = P1^3; //P1.3口作为输入口,接入433接收模块的D1口,这个口对应遥控器的按键B sbit relay = P1^1; //P1.1口作为输出口,将电平信号输出给继电器(低电平触发) /* API1: 延时函数,用于进入警报模式后长响1s */ void Delay2000ms(); /* API2: 延时函数,用于解除警报模式后短响0.5s */ void Delay1000ms(); /* API3: 延时函数,用于警报模式下受到振动后长响4s */ int Delay5000ms(); int main(void) { char alarmFlag = alarm_OFF; /* 查询法 */ while(1){ /* 如果按下遥控器的A按键,设定为报警模式 */ if(remote433_D0 == remote_ON){ alarmFlag = alarm_ON; relay = 0; Delay2000ms(); relay = 1; } /* 如果按下遥控器的B按键,设定为关闭报警模式 */ if(remote433_D1 == remote_ON){ alarmFlag = alarm_OFF; relay = 0; Delay1000ms(); relay = 1; } /* 如果警报模式下发生振动,喇叭响 */ if(alarmFlag == alarm_ON){ if(vibrate == 0){ relay = 0; Delay5000ms(); relay = 1; }else{ relay = 1; } } } return 0; } void Delay2000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 15; j = 2; k = 235; do { do { while (--k); } while (--j); } while (--i); } void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 8; j = 1; k = 243; do { do { while (--k); } while (--j); } while (--i); } int Delay5000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 36; j = 5; k = 211; do { if(remote433_D1 == remote_ON){ return 0; } do { while (--k); } while (--j); } while (--i); }