基于STM32设计的动态密码锁
Posted DS小龙哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于STM32设计的动态密码锁相关的知识,希望对你有一定的参考价值。
1. 前言
随着人们生活水平的提高及科学技术的发展,个人信息保护显得至关重要,设计了一款智能电子密码锁,以STM32单片机为主控制器,由触摸矩阵键盘、ESP8266、步进电机等模块组成,具有远程控制、随机密码生成等功能。经软硬件测试,系统响应迅速,灵敏度高,实时性好,系统识别准确率高达99%,该系统运行稳定,安全可靠,功耗低及具有较好的扩展性。
当前支持的开锁方式:
(1)手机APP远程开锁。支持手机APP远程开锁。手机APP连接上ESP8266创建的WIFI热点和TCP服务器,可以在手机APP上对设备端的RTC时间进行校准,设备唯一ID获取,生成随机开锁密码。
(2)随机密码开锁。手机APP与本地设备采用时间、作为算法种子,采用算法生成开锁密码,每一串的密码有效时间为一分钟。查看手机APP上显示的密码之后,在本地设备上输入完成密码对比开锁。
2. 相关硬件
2.1 WIFI模块
2.2 步进电机模块
2.3 OLED显示屏
2.4 STM32开发板
2.5 矩阵键盘模块
3. 手机APP设计
3.1 开发环境介绍
上位机软件采用Qt框架设计,Qt是一个跨平台的C++图形用户界面应用程序框架。Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单来说,QT可以很轻松的帮你做带界面的软件,甚至不需要你投入很大精力。
QT官网: https://www.qt.io/
3.2 学习教程
QT入门实战专栏: https://blog.csdn.net/xiaolong1126626497/category_11400392.html
QT5环境安装教程:https://xiaolong.blog.csdn.net/article/details/120654599
下载QT5.12.6下载地址:
https://download.qt.io/archive/qt/5.12/5.12.6/
打开链接后选择:
qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
软件安装时断网安装,否则会提示输入账户。
安装的时候,勾选一个mingw 32编译器即可。
3.3 实现效果
3.4 与服务器通信代码
/*
功能: 连接服务器
*/
void Widget::on_pushButton_connect_clicked()
if(ui->pushButton_connect->text()=="连接")
//开始连接服务器
NewClinet();
else
if(LocalTcpClientSocket)
LocalTcpClientSocket->close();
//客户端模式:创建客户端
void Widget::NewClinet()
if(LocalTcpClientSocket)
LocalTcpClientSocket->close();
delete LocalTcpClientSocket;
LocalTcpClientSocket=nullptr;
/*1. 创建本地客户端TCP套接字*/
LocalTcpClientSocket = new QTcpSocket;
/*2. 设置服务器IP地址*/
QString Ipaddr=ui->lineEdit_ip->text();
QHostAddress FarServerAddr(Ipaddr);
/*3. 连接客户端的信号槽*/
connect(LocalTcpClientSocket,SIGNAL(connected()),this,SLOT(LocalTcpClientConnectedSlot()));
connect(LocalTcpClientSocket,SIGNAL(disconnected()),this,SLOT(LocalTcpClientDisconnectedSlot()));
connect(LocalTcpClientSocket,SIGNAL(readyRead()),this,SLOT(LocalTcpClientReadDtatSlot()));
/*4. 尝试连接服务器主机*/
int prot=ui->lineEdit_port->text().toInt();
LocalTcpClientSocket->connectToHost(FarServerAddr,prot);
/*
功能: 时间更新
*/
void Widget::time_update()
QDateTime time = QDateTime::currentDateTime(); //获取系统现在的时间
QString text;
text = time.toString("yyyy/MM/dd hh:mm:ss ddd"); //设置显示格式
ui->label_time->setText(text);
char Password[10];
//更新密码
GeneratePassword(Password,6);
ui->label_password->setText(Password);
//客户端模式:响应连接上服务器之后的操作
void Widget::LocalTcpClientConnectedSlot()
ui->pushButton_connect->setText("断开");
Log_Text_Display("成功连接服务器...\\n");
ServerConnectStat=1; //标记连接上服务器
//客户端模式:断开服务器
void Widget::LocalTcpClientDisconnectedSlot()
ui->pushButton_connect->setText("连接");
QMessageBox::information(this,"提示","与服务器断开连接...",QMessageBox::Ok);
Log_Text_Display("与服务器断开连接...\\n");
ServerConnectStat=0; //标记断开服务器
//读取服务器发来的数据
//$update,2022/02/22 13:15,2022/02/23 12:17,吃饭,5
void Widget::LocalTcpClientReadDtatSlot()
QByteArray text=LocalTcpClientSocket->readAll();
QTextCodec *tc = QTextCodec::codecForName("GBK");
QString array = tc->toUnicode(text);
qDebug()<<"array:"<<array;
4. STM32设备端代码设计
如果需要完整的项目源码可以去这里下载: https://download.csdn.net/download/xiaolong1126626497/85895855
4.1 硬件相关原理图
4.2 keil工程
4.3 程序下载配置
4.4 硬件接线
1. 板载ESP8266串口WIFI模块与STM32的串口3相连接。
PB10--RXD 模块接收脚
PB11--TXD 模块发送脚
PB8---CH-PD---悬空
PB9---RST---悬空
GND---GND 地
VCC---VCC 电源(3.3V~5.0V)
2. 触摸按键使用TTP229型号的驱动芯片
SCL接PC11
SDA-OUT接PC10
电源接VCC-3.3
GND接GND
3. ULN2003控制28BYJ-48步进电机接线:
ULN2003接线:
IN4: PC9 d
IN3: PC8 c
IN2: PC7 b
IN1: PC6 a
+ : 5V
- : GND
4. OLED显示屏
D0----SCK-----PB14
D1----MOSI----PB13
RES—复位(低电平有效)—PB12
DC---数据和命令控制管脚—PB1
CS---片选引脚-----PA7
5. 板载按键
KEY1---PA0
KEY2---PC13
6.板载LED灯
LED1---PB5
LED2---PB0
LED3---PB1
7. 板载蜂鸣器
BEEP---PA8
4.5 设备初始化打印的信息
4.6 main.c 代码
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "esp8266.h"
#include "RFID_RC522.h"
#include "motor.h"
#include "oled.h"
#include "rtc.h"
#include <stdio.h>
#include <stdlib.h>
char mqtt_message[200];//上报数据缓存区
char SendBuff[10];
//存放矩阵键盘的值
char MatrixKey_var[20];
int MatrixKey_index=0;
//当前显示的页面
u8 page_show_flag=0; //1时钟页面
/*
函数功能: 绘制时钟表盘框架
*/
void DrawTimeFrame(void)
u8 i;
OLED_Circle(32,32,31);//画外圆
OLED_Circle(32,32,1); //画中心圆
//画刻度
for(i=0;i<60;i++)
if(i%5==0)OLED_DrawAngleLine(32,32,6*i,31,3,1);
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
/*
函数功能: 更新时间框架显示,在RTC中断里调用
*/
char TimeBuff[20];
void Update_FrameShow(void)
//如果正在显示其他提示文字,就不显示时钟
if(page_show_flag==1)
return;
/*1. 绘制秒针、分针、时针*/
OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-6-90,27,0);//清除之前的秒针
OLED_DrawAngleLine2(32,32,rtc_clock.sec*6-90,27,1); //画秒针
OLED_DrawAngleLine2(32,32,rtc_clock.min*6-6-90,24,0);
OLED_DrawAngleLine2(32,32,rtc_clock.min*6-90,24,1);
OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-6-90,21,0);
OLED_DrawAngleLine2(32,32,rtc_clock.hour*30-90,21,1);
//绘制电子钟时间
sprintf(TimeBuff,"%d",rtc_clock.year);
OLED_ShowString(65,16*0,16,TimeBuff); //年份字符串
OLED_ShowChineseFont(66+32,16*0,16,4); //显示年
sprintf(TimeBuff,"%d/%d",rtc_clock.mon,rtc_clock.day);
OLED_ShowString(75,16*1,16,TimeBuff); //月
if(rtc_clock.sec==0)OLED_ShowString(65,16*2,16," "); //清除多余的数据
sprintf(TimeBuff,"%d:%d:%d",rtc_clock.hour,rtc_clock.min,rtc_clock.sec);
OLED_ShowString(65,16*2,16,TimeBuff); //秒
//显示星期
OLED_ShowChineseFont(70,16*3,16,5); //星
OLED_ShowChineseFont(70+16,16*3,16,6); //期
OLED_ShowChineseFont(70+32,16*3,16,rtc_clock.week+7); //具体的值
static unsigned long next=1;//静态全局变量,作为种子
void my_srand(unsigned long seed)//通过传不同的参数更改种子值,一般传time(NULL)
next=seed;
int my_rand(void)//将srand更改过的种子值通过公式计算出结果作为随机值
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
//根据时间基准获取6位数随机开锁密码
char pwdcont[] = "0123456789";
void GeneratePassword(char *Password,int pwd_size)
int i;
int random;
unsigned int sec=TimeToSec(rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min);
//printf("sec=%d\\r\\n", sec);
//获取时间种子
my_srand(sec);
for (i = 0; i < pwd_size; i++)
random = my_rand() % (strlen(pwdcont));
*(Password + i) = pwdcont[random];
*(Password + i) = '\\0';
int main()
u8 esp8266_state=0;
u8 key;
u8 i;
u32 time_cnt=0;
u8 MatrixKey=0; //矩阵键盘值
u32 page_display=0; //页面显示时间刷新
char Password[10];
LED_Init();
KEY_Init();
USART1_Init(115200);
RC522_Init(); //RC522
Moto_Init(); //步进电机初始化
BEEP_Init();
USART3_Init(115200);//串口-WIFI
TIMER3_Init(72,20000); //超时时间20ms
Touch_Configuration(); //触摸按键配置
//OLED初始化
OLED_Init(0xc8,0xa1); //OLED显示屏初始化--正常显示;
USART1_Printf("正在初始化WIFI请稍等.\\r\\n");
//清屏
OLED_Clear(0);
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
OLED_ShowString(0,0,16,"init esp8266.");
for(i=0;i<5;i++)
if(ESP8266_Init()==0)
esp8266_state=1;
OLED_Clear(0);
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
OLED_ShowString(0,0,16,"esp8266 init ok.");
break;
else
esp8266_state=0;
OLED_Clear(0);
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
OLED_ShowString(0,0,16,"esp8266 init error.");
USART1_Printf("ESP8266硬件检测错误.\\n");
if(esp8266_state)
printf("ESP8266 WIFI 配置状态:%d\\r\\n",ESP8266_AP_TCP_Server_Mode("esp8266_xl","12345678",8089));
USART1_Printf("正在初始化RTC实时时钟请稍等.\\r\\n");
RTC_Init();//RTC初始化,一定要初始化成功
OLED_Clear(0x00); //清屏
OLED_RefreshGRAM(); //刷新数据到OLED屏幕
DrawTimeFrame(); //画时钟框架
while(1)
//按键可以测试开锁和关锁
key=KEY_Scan();
if(key==1)
LED1=0; //亮灯--表示开锁
time_cnt=0;
Motorcw_ring(1,300); //电机正转1圈
page_show_flag=1;
page_display=0;
//清屏
OLED_Clear(0);
OLED_ShowString(0,0,16,"open lock.");
else if(key==2)
LED1=1; //灭灯--表示关锁
time_cnt=0;
Motorccw_ring(1,300); //电机反转1圈
page_show_flag=1;
page_display=0;
//清屏
OLED_Clear(0);
OLED_ShowString(0,0,16,"close lock.");
DelayMs(10);
page_display++;
time_cnt++;
if(time_cnt>=50)
//获取开锁密码
GeneratePassword(Password,6);
// printf("Password = %s\\r\\n", Password);
time_cnt=0;
LED2=!LED2;
//判断显示时间是否到达,到达之后恢复正常时钟显示页面
if(page_show_flag==1 && page_display>以上是关于基于STM32设计的动态密码锁的主要内容,如果未能解决你的问题,请参考以下文章
基于STM32F103设计的智能门锁(支持多种开锁解锁方式)