目录
资料下载地址:基于51单片机蓝牙密码锁-单片机文档类资源-CSDN下载
一、项目需求
1、采用DS1302时钟模块,通过该模块可检测当前的时间;
2、采用AT24C02芯片,存储按键输入的信息;
3、采用DS18B20温度检测模块,通过该模块可检测当前的温度;
4、采用4*4矩阵键盘,按键主要功能有一键关门、显示时间、重新设置密码、取消键、确认键、输入密码;
二、原理图
三、设计思路
本设计以STC89C52单片机为核心控制器,加上其他的模块一起组成蓝牙密码锁的整个系统,其中包含中控部分、输入部分和输出部分。中控部分采用了STC89C52单片机,其主要作用是获取输入部分数据,经过内部处理,控制输出部分。输入由五部分组成,第一部分是DS1302时钟模块,通过该模块可检测当前的时间;第二部分是储存模块,采用AT24C02芯片,存储按键输入的信息;第三部分是DS18B20温度检测模块,通过该模块可检测当前的温度;第四部分是4*4矩阵键盘,按键主要功能有一键关门、显示时间、重新设置密码、取消键、确认键、输入密码;第五部分是供电电路,给整个系统进行供电。输出由三部分组成,第一部分是LCD1602显示模块, 通过该模块可以显示门的开关状态、输入的密码显示、重置密码时的显示等;第二部分是蓝牙模块,通过该模块可连接手机;第三部分是蜂鸣器,当键盘锁定且有按键按下时,蜂鸣器作为按键音提醒。
四、实物
五、代码
主程序代码
#include "main.h"
#include "lcd1602.h"
#include "key.h"
#include "IIC.h"
#include "ds18b20.h"
#include "ds1302.h"
#include "uart.h"
/**********************************
变量定义
**********************************/
extern char time_buf[8];
extern uchar uart_num;
uint temp_value;
uint randdata;
uint randdata1;
uchar TimeOutCounter = 0;
uchar LeftOrRight = 0;
uchar key_bianma = 0; //按键编码标志位变量
uchar key_num = 0; //按键扫描标志位变量
uchar flag_key_en = 1; //按键使能标志位变量
uchar flag_reset_password = 0; //重置密码标志位变量
uchar flag_reset_adminpassword = 0;
uchar flag_stat_door = 0; //门状态标志位
uchar flag_reset_password_num = 0; //重置密码次数标志位变量
uchar flag_error_num = 0; //密码错误次数标志位变量
uchar flag_error_time = 180; //密码错误时间标志位变量
uchar password[6] = {1,2,3,4,5,6}; //初始密码数组
uchar adminpassword[6] = {1,2,3,4,5,6}; //初始管理员密码数组
uchar password_input[6] = {0,0,0,0,0,0}; //输入密码数组
uchar password_reset[6] = {0,0,0,0,0,0}; //重置密码数组
uchar password_num = 0; //密码数量标志位变量
uint time_jishi = 0; //10ms计时变量
/**********************************
函数声明
**********************************/
void Delay_function(uint x); //延时函数
void Key_function(void); //按键函数
void Ensure_function(void); //确定函数
void Reset_password_function(void); //重置密码函数
void Write_init_EEPROM();
void Timer0Init();
/****
******* 主函数
*****/
void main()
{
Timer0Init();
Uart_Init();
Ds1302_Init();
Lcd1602_Init(); //LCD1602初始化
Delay_function(50); //延时50ms
lcd1602_clean(); //清屏
Delay_function(50); //延时50ms
Init_IIC(); //总线初始化,拉高释放总线
Delay_function(50); //延时50ms
//写过一次后关闭,无需重复写初值
// Write_init_EEPROM(); //写入初始密码123456到E2PROM
// ds1302_write_time();
lcd1602_display_str(1,0,"===Coded Lock===");//初始化界面
lcd1602_display_str(2,0,"Password:");
while(1)
{
//将密码从24C02中读出来,包括管理员密码以及使用密码
password[0]=read_add(1);
password[1]=read_add(2);
password[2]=read_add(3);
password[3]=read_add(4);
password[4]=read_add(5);
password[5]=read_add(6);
adminpassword[0]=read_add(7);
adminpassword[1]=read_add(8);
adminpassword[2]=read_add(9);
adminpassword[3]=read_add(10);
adminpassword[4]=read_add(11);
adminpassword[5]=read_add(12);
Key_function(); //按键函数
Reset_password_function(); //重置密码函数
//输入密码三次错误后执行如下程序
if(flag_error_num == 3)
{
flag_key_en = 0;
if(time_jishi % 40 == 0)
{
flag_error_time--;
}
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_time(2,0,flag_error_time);
if(flag_error_time == 0)
{
flag_key_en = 1;
flag_error_time = 180;
flag_error_num = 0;
lcd1602_display_str(2,0,"Password: ");
}
}
if(time_jishi % 50 == 0) //500ms检测一次
{
ds1302_read_time();
temp_value = Ds18b20_Read_Temp();
randdata=rand()%(9999-1000+1)+1000; //获得1000~9999之间的随机数,函数rand()在stdlib.h
randdata1=rand()%(55-33+1)+10;
}
if(uart_num == 1)//一键关门
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," Door Close ");
LeftOrRight = Stop;
RELAY = 1;
LED = 1;
Delay_function(1000);
lcd1602_display_str(2,0,"Password: ");
flag_stat_door = 0;
uart_num=0;
}
if(uart_num == 2)
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," Door Open ");
LeftOrRight = Left;
RELAY = 0;
LED = 0;
flag_error_num = 0;
memset(password_input,0,6);
Delay_function(1000);
lcd1602_display_str(1,0,"==Lock : open===");
lcd1602_display_str(2,0," ");
flag_stat_door = 1;
uart_num=0;
}
if(uart_num == 3)
{
password[0]=randdata/1000%10;
password[1]=randdata/100%10;
password[2]=randdata/10%10;
password[3]=randdata/1%10;
password[4]=randdata1/10%10;
password[5]=randdata1/1%10;
write_add(1,password[0]);
Delay_function(5);
write_add(2,password[1]);
Delay_function(5);
write_add(3,password[2]);
Delay_function(5);
write_add(4,password[3]);
Delay_function(5);
write_add(5,password[4]);
Delay_function(5);
write_add(6,password[5]);
Delay_function(5);
Uart_Sent_Char(read_add(1)+'0');
Uart_Sent_Char(read_add(2)+'0');
Uart_Sent_Char(read_add(3)+'0');
Uart_Sent_Char(read_add(4)+'0');
Uart_Sent_Char(read_add(5)+'0');
Uart_Sent_Char(read_add(6)+'0');
uart_num=0;
}
Delay_function(10); //延时10ms
time_jishi++; //计时变量+1
if(time_jishi == 5000)
{
time_jishi = 0;
}
}
}
/****
******* 延时函数
*****/
void Delay_function(uint x)
{
uint m,n;
for(m=x;m>0;m--)
for(n=110;n>0;n--);
}
/****************************
******初始向EEPROM写数据*****
******************************/
void Write_init_EEPROM()
{
//写入初始密码123456到E2PROM
write_add(1,password[0]);
Delay_function(5);
write_add(2,password[1]);
Delay_function(5);
write_add(3,password[2]);
Delay_function(5);
write_add(4,password[3]);
Delay_function(5);
write_add(5,password[4]);
Delay_function(5);
write_add(6,password[5]);
Delay_function(5);
//写入初始管理员密码123456到E2PROM
write_add(7,adminpassword[0]);
Delay_function(5);
write_add(8,adminpassword[1]);
Delay_function(5);
write_add(9,adminpassword[2]);
Delay_function(5);
write_add(10,adminpassword[3]);
Delay_function(5);
write_add(11,adminpassword[4]);
Delay_function(5);
write_add(12,adminpassword[5]);
Delay_function(5);
}
/****
*******按键函数
*****/
void Key_function(void)
{
uchar i;
key_bianma = matrix_keyboard_scan(); //读按键的位置码
if(key_bianma != 0) //当有按键按下时
{
if(flag_key_en == 0) //按键使能标志为0时,锁3分钟
{
BEEP = 0;
Delay_function(50);
BEEP = 1;
}
else //没有锁定键盘时
{
key_num = matrix_keyboard_coding(key_bianma); //根据按键的位置将其编码,编码值赋值给NUM
{
switch(key_num) //判断按键值
{
case ('C'): //无作用
// flag_reset_adminpassword = 1;
break;
case ('A'): //一键关门
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," Door Close ");
LeftOrRight = Stop;
RELAY = 1;
LED = 1;
Delay_function(1000);
lcd1602_display_str(2,0,"Password: ");
flag_stat_door = 0;
break;
case ('B'): //显示时间
lcd1602_clean();
lcd_display_alltime(time_buf);
lcd1602_display_temp(2,10,temp_value);
Delay_function(1000);
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0,"Password: ");
break;
case ('D'): //重新设置密码
flag_reset_password = 1;
lcd1602_clean();
break;
case ('*'): //取消键
if(password_num != 0)
{
password_num--;
lcd1602_display_char(2,9+password_num,' ');
}
break;
case ('#'): //确认键
if(flag_reset_password_num >= 1)
flag_reset_password_num++;
Ensure_function();
break;
default: //如果不是功能键按下时,就是数字键按下
lcd1602_display_str(1,0," ");
lcd1602_display_str(2,0," ");
if(flag_reset_password == 0)
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0,"Password: ");
}
if(password_num < 6) //当输入的密码少于6位时,接受输入并保存,大于6位时则无效。
{
for(i = 0;i < password_num+1;i++)
lcd1602_display_char(2,9+i,'*');
if(flag_reset_password == 0 || flag_reset_password_num == 1 || flag_reset_password_num == 0)
password_input[password_num++] = key_num; //将数字键的码赋值给password_input[]数组暂存
else if(flag_reset_password_num == 2)
password_reset[password_num++] = key_num; //将数字键的码赋值给password_reset[]数组暂存
}
else //输入数据位数大于6后,忽略输入
{
password_num = 6;
lcd1602_display_str(2,9,"******");
}
break;
}
}
}
}
}
/****
*******确认函数
*****/
void Ensure_function(void)
{
lcd1602_display_str(1,0," ");
lcd1602_display_str(2,0," ");
//不在设置密码时,并且门是关着在执行如下函数
if(flag_reset_password == 0 && flag_stat_door == 0)
{
//键入密码进行比对将输入密码与存储的密码对比,正确则开门
if((password[0] == password_input[0]) && (password[1] == password_input[1]) &&
(password[2] == password_input[2]) && (password[3] == password_input[3]) &&
(password[4] == password_input[4]) && (password[5] == password_input[5]))
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," Door Open ");
LeftOrRight = Left;
RELAY = 0;
LED = 0;
flag_error_num = 0;
memset(password_input,0,6);
Delay_function(1000);
lcd1602_display_str(2,0,"Password: ");
flag_stat_door = 1;
}
//键入密码进行比对将输入密码与存储的密码对比,错误则不开门,显示密码错误。
else
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," password error ");
memset(password_input,0,6);
flag_error_num++;
Delay_function(1000);
lcd1602_display_str(2,0,"Password: ");
}
}
//不在设置密码时,并且门是开着在执行如下函数
if(flag_reset_password == 0 && flag_stat_door == 1)
{
lcd1602_display_str(1,0,"==Lock : open===");
lcd1602_display_str(2,0," ");
}
//当设置密码时执行如下程序
if((flag_reset_password == 1 && flag_reset_password_num == 0))
{
//对比管理员密码与输入密码
if((adminpassword[0] == password_input[0]) && (adminpassword[1] == password_input[1]) &&
(adminpassword[2] == password_input[2]) && (adminpassword[3] == password_input[3]) &&
(adminpassword[4] == password_input[4]) && (adminpassword[5] == password_input[5]))
{
if(flag_reset_password)
flag_reset_password_num++;
}
else
{
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0," password error ");
memset(password_input,0,6);
flag_error_num++;
Delay_function(1000);
lcd1602_display_str(2,0,"Password: ");
}
}
password_num = 0;
}
/****
*******重置密码函数
*****/
void Reset_password_function(void)
{
uchar i;
if(flag_reset_password == 1 && flag_reset_password_num == 0)
{
lcd1602_display_str(1,0,"=Reset Password=");
lcd1602_display_str(2,0,"adm_Pswd:");
}
if(flag_reset_password_num == 1)
{
lcd1602_display_str(1,0,"=Reset Password=");
lcd1602_display_str(2,0,"New_Pswd:");
}
if(flag_reset_password_num == 2)
{
lcd1602_display_str(1,0,"=Reset Password=");
lcd1602_display_str(2,0,"Ned_Pswd:");
}
if(flag_reset_password_num == 3)
{
//对比两次输入的密码
if((password_input[0] == password_reset[0]) && (password_input[1] == password_reset[1]) &&
(password_input[2] == password_reset[2]) && (password_input[3] == password_reset[3]) &&
(password_input[4] == password_reset[4]) && (password_input[5] == password_reset[5]))
{
for(i=0;i<6;i++)
{
password[i] = password_reset[i];
//写入更改后密码密码到E2PROM
write_add(i+1,password[i]);
Delay_function(5);
}
lcd1602_display_str(1,0,"=Reset Password=");
lcd1602_display_str(2,0," reset ok ");
Delay_function(1000);
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0,"Password: ");
flag_reset_password = 0;
flag_reset_password_num = 0;
}
else
{
lcd1602_display_str(1,0,"=Reset Password=");
lcd1602_display_str(2,0," reset fail ");
Delay_function(1000);
lcd1602_display_str(1,0,"===Coded Lock===");
lcd1602_display_str(2,0,"Password: ");
flag_reset_password = 0;
flag_reset_password_num = 0;
}
}
}
/****
*******定时器1初使化函数
*****/
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TL0 = 0xAE; //设置定时初值
TH0 = 0xFB; //设置定时初值
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void Time0(void) interrupt 1 //3:为定时器1的中断号; 1:定时器0的中断号; 0:外部中断1的中断号; 2 外部中断2的中断号; 4 串口中断的中断号;
{
TL0 = 0xAE; //设置定时初值
TH0 = 0xFB; //设置定时初值
TimeOutCounter ++;
switch ( LeftOrRight )
{
case 0 : //为0时,舵机归位,脉宽1.5ms
{
if( TimeOutCounter <= 2 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 1 : //为1时,舵机左转,脉宽1ms(理论值),实际可以调试得出
{
if( TimeOutCounter <= 1 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
default : break;
}
if( TimeOutCounter == 30 ) //周期20ms(理论值)
{
TimeOutCounter = 0;
}
}
六、资料清单