51单片机实战训练——红外遥控电子密码锁(含项目源码)
开发软件:Keil4(编写程序)、STC-ISP(烧录下载)
目标效果:用户可以通过红外遥控器上的数字输入密码(0-9)。密码输入正确,驱动舵机旋转90°(模拟门锁开启);密码错误则蜂鸣器发出警报。
一、HS0038红外接收模块
在51单片机模块学习中,我们对HS0038红外接收模块已经有了一定的了解,在这里我们做一个更加全面的学习。
1-1.HS0038基本参数
- 工作电压:2.7V ~ 5.5V(兼容3.3V和5V系统)
- 载波频率:中心频率38kHz(允许偏差±1kHz,如37kHz~39kHz)
- 接收距离:典型值约10米(实际受环境光、发射功率影响)
- 输出信号:数字信号(低电平有效),无信号时输出高电平,接收到信号时输出低电平脉冲。
- 引脚定义:3个引脚,通常从左到右依次为OUT/GND/VCC(不同厂家可能引脚顺序不同,需以实际模块标注为准)
1-2.工作原理
1-2-1.HS0038硬件工作流程
- 信号接收:HS0038 持续接收环境中的红外信号,通过内部电路滤除非38kHz的干扰信号。当检测到38kHz调制的红外信号(如遥控器按键按下)时,其OUT引脚输出低电平脉冲。
- 信号输出特性:无信号时OUT引脚保持高电平。有信号时OUT引脚输出与调制信号反相的低电平波形(如NEC协议信号)。
1-2-2.结合代码讲解HS0038工作流程
1. 初始化
IR_Init() 调用 Timer0_Init() 和 Int0_Init():
- 定时器0:用于精确测量脉冲时间间隔。
- 外部中断0:配置为下降沿触发(IT0=1),当HS0038的OUT引脚电平从高变低时触发中断。
2. 中断触发与状态机控制
- 中断入口:红外信号到来时,HS0038的OUT引脚产生下降沿,触发 Int0_Routine() 中断函数。
- 通过状态机(IR_State) 分阶段处理信号。
3. 时间测量与协议解析
- 定时器关键作用
使用定时器0记录相邻两个下降沿之间的时间(单位:定时器计数),用于判断信号类型:
- 数据位存储
通过 IR_Data[4] 数组存储32位数据(4字节):
字节0:地址码
字节1:地址码反码(校验用)
字节2:命令码
字节3:命令码反码(校验用)
4. 数据验证与应用
- 校验逻辑:检查地址和命令的反码是否正确
- 用户接口:通过 IR_GetDataFlag() 和 IR_GetCommand() 等函数获取解码后的地址和命令。
二、SG90舵机模块
SG90 是一款常见的微型舵机(伺服电机),广泛应用于机器人、遥控模型、DIY项目等场景。
2-1.基本参数
2-2.工作原理
2-2-1.内部结构
SG90舵机内部包含以下核心组件:
- 直流电机:提供动力。
- 减速齿轮组:降低转速并增加扭矩。
- 电位器(位置传感器):检测输出轴角度,形成闭环反馈。
- 控制电路:接收PWM信号并驱动电机转动至目标角度。
2-2-2.控制逻辑
-
PWM信号解析:
舵机通过信号线接收PWM信号,其脉冲宽度决定目标角度: -
0.5ms脉冲 → 对应0°位置。
-
1.5ms脉冲 → 对应90°中间位置。
-
2.5ms脉冲 → 对应180°位置。
-
闭环控制:
-
控制电路将PWM脉冲宽度转换为目标角度。
-
电位器实时检测输出轴的实际角度
-
控制电路比较目标角度与实际角度,驱动电机转动直至两者一致(误差趋近于零)。
2-2-3.运动流程
PWM信号输入 → 控制电路解码目标角度 → 电机转动 → 齿轮减速 → 输出轴转动
↑反馈调整↓
电位器检测当前角度
2-2-4.代码测试
在这里我们不妨写一个代码,实现以下的功能:按下独立按键1(模拟输入正确密码),舵机旋转90°(开锁),五秒后舵机复位。
#include <reg52.h>
#include <intrins.h>
sbit Servo_PWM = P1^0; // 舵机信号线接P1.0
sbit Key1 = P3^1; // 独立按键1接P3.1
unsigned int PWM_Count = 0; // PWM周期计数器
unsigned char PWM_Duty = 11; // 初始占空比(对应0°)
bit Key_Pressed = 0; // 按键按下标志
unsigned int Delay_Cnt = 0; // 延时计数器
/* 定时器0初始化(用于PWM生成) */
void Timer0_Init() {
TMOD &= 0xF0; // 设置定时器模式为模式1(16位)
TMOD |= 0x01;
// 11.0592MHz下,定时器每加1耗时1.085us
// 目标中断周期:50us → 计数值 = 50 / 1.085 ≈ 46
TH0 = (65536 - 46) / 256; // 重装初值
TL0 = (65536 - 46) % 256;
ET0 = 1; // 允许定时器0中断
EA = 1; // 开启总中断
TR0 = 1; // 启动定时器0
}
/* 定时器0中断服务函数 */
void Timer0_ISR() interrupt 1 {
TH0 = (65536 - 46) / 256; // 重装初值
TL0 = (65536 - 46) % 256;
PWM_Count++;
if (PWM_Count <= PWM_Duty) {
Servo_PWM = 1; // 高电平阶段
} else {
Servo_PWM = 0; // 低电平阶段
}
// 20ms周期计算:50us * 400 = 20ms
if (PWM_Count >= 400) {
PWM_Count = 0;
}
}
/* 定时器1初始化(用于精确延时) */
void Timer1_Init() {
TMOD &= 0x0F; // 设置定时器模式为模式1(16位)
TMOD |= 0x10;
// 11.0592MHz下,50ms中断一次
// 计数值 = 50000us / 1.085us ≈ 46082
TH1 = (65536 - 46082) / 256;
TL1 = (65536 - 46082) % 256;
ET1 = 1; // 允许定时器1中断
TR1 = 1; // 启动定时器1
}
/* 定时器1中断服务函数(50ms触发一次) */
void Timer1_ISR() interrupt 3 {
static unsigned int sec_cnt = 0;
TH1 = (65536 - 46082) / 256; // 重装初值
TL1 = (65536 - 46082) % 256;
sec_cnt++;
if (sec_cnt >= 100) { // 100*50ms = 5秒
// 5秒到,恢复舵机角度
PWM_Duty = 11; // 返回0°
sec_cnt = 0;
Key_Pressed = 0; // 清除按键标志
}
}
/* 按键消抖延时(粗略延时) */
void DelayMs(unsigned int ms) {
unsigned int i, j;
// 11.0592MHz下,调整为约1ms延时
for (i = ms; i > 0; i--)
for (j = 120; j > 0; j--); // 调整循环次数
}
/* 主函数 */
void main() {
Timer0_Init(); // 初始化定时器0(PWM)
Timer1_Init(); // 初始化定时器1(延时)
while (1) {
// 检测按键1是否按下(带消抖)
if (Key1 == 0) {
DelayMs(10); // 消抖延时
if (Key1 == 0) { // 确认按键按下
Key_Pressed = 1; // 标记按键已按下
PWM_Duty = 33; // 设置舵机为90°(1.5ms高电平)
TR1 = 1; // 启动定时器1开始5秒计时
}
while (!Key1); // 等待按键释放
}
}
}
整合了一下,舵机模块代码如下
//SG90.c
#include <reg52.h>
#include <intrins.h>
sbit Servo_PWM = P1^0;
unsigned char PWM_Duty = 10; // 默认初始位置(90度)
unsigned char Init_Duty = 10; // 可根据需要调整
/* 角度转占空比 */
unsigned char AngleToDuty(unsigned char angle) {
if(angle > 180) angle = 180;
return 10 + (angle * 40) / 180; // 0.5ms~2.5ms对应10~50
}
/* 简化版角度控制 */
void SG90_rotate(unsigned char angle) {
PWM_Duty = AngleToDuty(angle);
}
/* 定时器0中断(保持PWM生成) */
void Timer0_ISR() interrupt 1 {
static unsigned int pwm_counter = 0;
TH0 = (65536 - 50) >> 8; // 50us中断
TL0 = (65536 - 50) & 0xFF;
if(++pwm_counter >= 400) pwm_counter = 0; // 20ms周期
Servo_PWM = (pwm_counter < PWM_Duty) ? 1 : 0;
}
/* 高精度阻塞延时 */
void SG90_Delay(unsigned int ms) {
unsigned int i, j;
for(i=0; i<ms; i++) {
for(j=0; j<112; j++) { // 11.0592MHz校准值
_nop_();
}
}
}
/* 系统初始化 */
void System_Init() {
EA = 1;
TMOD = 0x01; // 定时器0模式1
TH0 = (65536 - 50) >> 8;
TL0 = (65536 - 50) & 0xFF;
ET0 = 1;
TR0 = 1;
}
因为单片机上定时器资源紧张,我这里去掉了一个负责舵机回位的定时器,换用Delay
主函数中只要按照初始化-舵机转动-舵机延时-舵机转动的步骤就可以驱动舵机了
三、实操步骤
3-1.LCD屏幕设计
计划一行一列显示Password:,二行二列显示红外遥控对应数字;密码输入完毕后点击确认进行判断,如果和Password一致,则清空第二行,密码错误则在第一行第11列开始闪烁Error!
3-2.红外遥控接收数字调试
结合51单片机模块学习中有关红外遥控的内容,我们可以写出以下代码
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char location=0;
unsigned char Address;
unsigned char Command;
void main() {
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
while(1)
{
if(IR_GetDataFlag() ) //如果收到数据帧或者收到连发帧
{
Address=IR_GetAddress(); //获取遥控器地址码
Command=IR_GetCommand(); //获取遥控器命令码
switch(Command)
{
case IR_1:location++;LCD_ShowNum(2,location,1,1);break;
case IR_2:location++;LCD_ShowNum(2,location,2,1);break;
case IR_3:location++;LCD_ShowNum(2,location,3,1);break;
case IR_4:location++;LCD_ShowNum(2,location,4,1);break;
case IR_5:location++;LCD_ShowNum(2,location,5,1);break;
case IR_6:location++;LCD_ShowNum(2,location,6,1);break;
case IR_7:location++;LCD_ShowNum(2,location,7,1);break;
case IR_8:location++;LCD_ShowNum(2,location,8,1);break;
case IR_9:location++;LCD_ShowNum(2,location,9,1);break;
case IR_0:location++;LCD_ShowNum(2,location,0,1);break;
}
}
}
}
这串代码实现了基本的输入密码展示。
3-3.设定密码并进行确认
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char location=0;
unsigned char Address;
unsigned char Command;
unsigned char password=0;
unsigned char PW=1012;//设定密码
void main() {
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
while(1)
{
if(IR_GetDataFlag() ) //如果收到数据帧或者收到连发帧
{
Address=IR_GetAddress(); //获取遥控器地址码
Command=IR_GetCommand(); //获取遥控器命令码
switch(Command)
{
case IR_1:password=password*10+1;location++;LCD_ShowNum(2,location,1,1);break;
case IR_2:password=password*10+2;location++;LCD_ShowNum(2,location,2,1);break;
case IR_3:password=password*10+3;location++;LCD_ShowNum(2,location,3,1);break;
case IR_4:password=password*10+4;location++;LCD_ShowNum(2,location,4,1);break;
case IR_5:password=password*10+5;location++;LCD_ShowNum(2,location,5,1);break;
case IR_6:password=password*10+6;location++;LCD_ShowNum(2,location,6,1);break;
case IR_7:password=password*10+7;location++;LCD_ShowNum(2,location,7,1);break;
case IR_8:password=password*10+8;location++;LCD_ShowNum(2,location,8,1);break;
case IR_9:password=password*10+9;location++;LCD_ShowNum(2,location,9,1);break;
case IR_0:password=password*10+0;location++;LCD_ShowNum(2,location,0,1);break;
case IR_USD:if(password==PW){LCD_ShowString(2,1," ");location=0;password=0;}
else{LCD_ShowString(1,11,"ERROR!");Delay(3000);location=0;LCD_ShowString(1,11," ");LCD_ShowString(2,1," ");password=0;} break;
}
}
}
}
注意到上述密码有个限制,即密码开头必须是1-9,不可以是0.
怎么改进呢?我们可以设定密码为字符串,感兴趣的同学可以自己动手试一试
3-4.密码输入正确时,舵机工作
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char location=0;
unsigned char Address;
unsigned char Command;
unsigned int password=0;
unsigned int PW=1012;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
System_Init();
while(1)
{
if(IR_GetDataFlag() ) //如果收到数据帧或者收到连发帧
{
Address=IR_GetAddress(); //获取遥控器地址码
Command=IR_GetCommand(); //获取遥控器命令码
switch(Command)
{
case IR_1:password=password*10+1;LCD_ShowNum(2,++location,1,1);break;
case IR_2:password=password*10+2;LCD_ShowNum(2,++location,2,1);break;
case IR_3:password=password*10+3;LCD_ShowNum(2,++location,3,1);break;
case IR_4:password=password*10+4;LCD_ShowNum(2,++location,4,1);break;
case IR_5:password=password*10+5;LCD_ShowNum(2,++location,5,1);break;
case IR_6:password=password*10+6;LCD_ShowNum(2,++location,6,1);break;
case IR_7:password=password*10+7;LCD_ShowNum(2,++location,7,1);break;
case IR_8:password=password*10+8;LCD_ShowNum(2,++location,8,1);break;
case IR_9:password=password*10+9;LCD_ShowNum(2,++location,9,1);break;
case IR_0:password=password*10+0;LCD_ShowNum(2,++location,0,1);break;
case IR_USD:if(password==PW)
{LCD_ShowString(1,11,"OPEN! ");
LCD_ShowString(2,1," ");
SG90_rotate(0); // 舵机动作
Delay(1000);
SG90_rotate(90);
}
else
{LCD_ShowString(1,11,"ERROR!");
LCD_ShowString(2,1," ");
Delay(3000);
}
LCD_ShowString(1,11," ");LCD_ShowString(2,1," ");
location=0;password=0;
break;
}
}
}
}
写到这里时,会发现舵机并不能很好的运动。用单片机的IO口给舵机供电还是太勉强了,给舵机单独供电效果更佳。
四、拓展提高
完成第三章后,我们的红外遥控电子密码锁已经可以工作了。但它还有许多可提升的地方
4-1.显示优化(报错时闪烁、不显示正在输入的密码)
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char location=0;
unsigned char i;
unsigned char Command;
unsigned int password=0;
unsigned int PW=1012;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
System_Init();
while(1)
{
if(IR_GetDataFlag() ) //如果收到数据帧或者收到连发帧
{
Command=IR_GetCommand(); //获取遥控器命令码
switch(Command)
{
case IR_1:password=password*10+1;LCD_ShowString(2,++location,"*");break;
case IR_2:password=password*10+2;LCD_ShowString(2,++location,"*");break;
case IR_3:password=password*10+3;LCD_ShowString(2,++location,"*");break;
case IR_4:password=password*10+4;LCD_ShowString(2,++location,"*");break;
case IR_5:password=password*10+5;LCD_ShowString(2,++location,"*");break;
case IR_6:password=password*10+6;LCD_ShowString(2,++location,"*");break;
case IR_7:password=password*10+7;LCD_ShowString(2,++location,"*");break;
case IR_8:password=password*10+8;LCD_ShowString(2,++location,"*");break;
case IR_9:password=password*10+9;LCD_ShowString(2,++location,"*");break;
case IR_0:password=password*10+0;LCD_ShowString(2,++location,"*");break;
case IR_USD:if(password==PW)
{LCD_ShowString(1,11,"OPEN! ");
LCD_ShowString(2,1," ");
SG90_rotate(0); // 舵机动作
Delay(1000);
SG90_rotate(90);
}
else
{
LCD_ShowString(2,1," ");
for(i=0;i<3;i++){LCD_ShowString(1,11,"ERROR!");Delay(500);LCD_ShowString(1,11," ");Delay(500);}
}
LCD_ShowString(1,11," ");LCD_ShowString(2,1," ");
location=0;password=0;
break;
}
}
}
}
4-2.密码输入时退位
有时密码输入错误,我们需要删除刚刚输入的那位密码,我们可以用以下代码实现
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char location=0;
unsigned char i;
unsigned char Command;
unsigned int password=0;
unsigned int PW=1012;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
System_Init();
while(1)
{
if(IR_GetDataFlag() ) //如果收到数据帧或者收到连发帧
{
Command=IR_GetCommand(); //获取遥控器命令码
if(Command==IR_1)
{
password=password*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
password=password*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
password=password*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
password=password*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
password=password*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
password=password*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
password=password*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
password=password*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
password=password*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
password=password*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
if(password==PW)
{
LCD_ShowString(1,11,"OPEN! ");
LCD_ShowString(2,1," ");
SG90_rotate(0); // 舵机动作
Delay(1000);
SG90_rotate(90);
}
else
{
LCD_ShowString(2,1," ");
for(i=0;i<3;i++)
{
LCD_ShowString(1,11,"ERROR!");
Delay(500);
LCD_ShowString(1,11," ");
Delay(500);
}
}
LCD_ShowString(1,11," ");
LCD_ShowString(2,1," ");
location=0;
password=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
password=password/10;
location--;
}
}
}
}
4-3.修改密码
我们再添加一个修改密码锁密码
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
unsigned char mode=0;
unsigned char location=0;
unsigned char i;
unsigned char Command;
unsigned int password=0;
unsigned int PW=1012;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
System_Init();
while(1)
{
if(IR_GetDataFlag()&&mode==0 ) //输入密码
{
Command=IR_GetCommand();
if(Command==IR_1)
{
password=password*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
password=password*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
password=password*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
password=password*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
password=password*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
password=password*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
password=password*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
password=password*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
password=password*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
password=password*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
if(password==PW)
{
LCD_ShowString(1,11,"OPEN! ");
LCD_ShowString(2,1," ");
SG90_rotate(0); // 舵机动作
Delay(1000);
SG90_rotate(90);
}
else
{
LCD_ShowString(2,1," ");
for(i=0;i<3;i++)
{
LCD_ShowString(1,11,"ERROR!");
Delay(500);
LCD_ShowString(1,11," ");
Delay(500);
}
}
LCD_ShowString(1,11," ");
LCD_ShowString(2,1," ");
location=0;
password=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
password=password/10;
location--;
}
if(Command==IR_EQ)
{
LCD_ShowString(1,1,"PW test ");
LCD_ShowString(2,1," ");
location=0;
password=0;
mode=1;
}
}
if(IR_GetDataFlag()&&mode==1 )//修改密码前确认密码
{
Command=IR_GetCommand();
if(Command==IR_1)
{
password=password*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
password=password*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
password=password*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
password=password*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
password=password*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
password=password*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
password=password*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
password=password*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
password=password*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
password=password*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
if(password==PW)
{
LCD_ShowString(1,1,"New Password");
LCD_ShowString(2,1," ");
PW=0;
mode++;
}
else
{
LCD_ShowString(1,1,"Password:");
LCD_ShowString(2,1," ");
mode--;
}
LCD_ShowString(2,1," ");
location=0;
password=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
password=password/10;
location--;
}
}
if(IR_GetDataFlag()&&mode==2 ) //输入新密码
{
Command=IR_GetCommand(); //获取遥控器命令码
if(Command==IR_1)
{
PW=PW*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
PW=PW*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
PW=PW*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
PW=PW*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
PW=PW*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
PW=PW*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
PW=PW*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
PW=PW*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
PW=PW*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
PW=PW*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
for(i=0;i<3;i++)
{
LCD_ShowString(1,13,"OK!");
Delay(500);
LCD_ShowString(1,13," ");
Delay(500);
}
LCD_ShowString(1,1,"Password: ");
LCD_ShowString(2,1," ");
location=0;
password=0;
mode=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
PW=PW/10;
location--;
}
}
}
}
4-4.蜂鸣器报警
我们再添加一下蜂鸣器报警部分
#include <REGX52.H>
#include "SG90.h"
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"
#include "Buzzer.h"
unsigned char mode=0;
unsigned char location=0;
unsigned char i;
unsigned char Command;
unsigned int password=0;
unsigned int PW=1012;
void main()
{
LCD_Init();
LCD_ShowString(1,1,"Password:");
IR_Init();
System_Init();
while(1)
{
if(IR_GetDataFlag()&&mode==0 ) //输入密码
{
Command=IR_GetCommand();
if(Command==IR_1)
{
password=password*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
password=password*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
password=password*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
password=password*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
password=password*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
password=password*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
password=password*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
password=password*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
password=password*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
password=password*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
if(password==PW)
{
LCD_ShowString(1,11,"OPEN! ");
LCD_ShowString(2,1," ");
SG90_rotate(0); // 舵机动作
Delay(1000);
SG90_rotate(90);
}
else
{
LCD_ShowString(2,1," ");
for(i=0;i<3;i++)
{
LCD_ShowString(1,11,"ERROR!");
Buzzer_Time(500);
LCD_ShowString(1,11," ");
Delay(500);
}
}
LCD_ShowString(1,11," ");
LCD_ShowString(2,1," ");
location=0;
password=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
password=password/10;
location--;
}
if(Command==IR_EQ)
{
LCD_ShowString(1,1,"PW test ");
LCD_ShowString(2,1," ");
location=0;
password=0;
mode=1;
}
}
if(IR_GetDataFlag()&&mode==1 )//修改密码前确认密码
{
Command=IR_GetCommand();
if(Command==IR_1)
{
password=password*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
password=password*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
password=password*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
password=password*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
password=password*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
password=password*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
password=password*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
password=password*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
password=password*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
password=password*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
if(password==PW)
{
LCD_ShowString(1,1,"New Password");
LCD_ShowString(2,1," ");
PW=0;
mode++;
}
else
{
LCD_ShowString(1,1,"Password:");
LCD_ShowString(2,1," ");
mode--;
}
LCD_ShowString(2,1," ");
location=0;
password=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
password=password/10;
location--;
}
}
if(IR_GetDataFlag()&&mode==2 ) //输入新密码
{
Command=IR_GetCommand(); //获取遥控器命令码
if(Command==IR_1)
{
PW=PW*10+1;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_2)
{
PW=PW*10+2;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_3)
{
PW=PW*10+3;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_4)
{
PW=PW*10+4;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_5)
{
PW=PW*10+5;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_6)
{
PW=PW*10+6;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_7)
{
PW=PW*10+7;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_8)
{
PW=PW*10+8;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_9)
{
PW=PW*10+9;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_0)
{
PW=PW*10+0;
LCD_ShowString(2,++location,"*");
}
if(Command==IR_USD)
{
for(i=0;i<3;i++)
{
LCD_ShowString(1,13,"OK!");
Buzzer_Time(500);
LCD_ShowString(1,13," ");
Delay(500);
}
LCD_ShowString(1,1,"Password: ");
LCD_ShowString(2,1," ");
location=0;
password=0;
mode=0;
}
if(Command==IR_RPT)
{
LCD_ShowString(2,location," ");
PW=PW/10;
location--;
}
}
}
}
/
/
/
/
/
作者才开始在CSDN上分享学习内容,写的不好请多多包涵。
欢迎大家在评论区和作者讨论。
码字不易,求各位看官点个关注/赞/收藏,新人博主真的很需要助力~~