1. 前言
前一版设计了一款物联网的密码锁,采用MQTT协议连接物联网服务器进行交互,这一版是本地动态密码锁。采用局域网方式完成网络连接,与门锁进行交互,通信设置,生成密码种子,进行动态密匙比对。 这款智能电子密码锁,以STM32单片机为主控制器,由触摸矩阵键盘、ESP8266、步进电机等模块组成,具有手机APP控制、随机密码生成等功能。
当前支持的开锁方式:
(1)手机APP远程开锁。支持手机APP远程开锁。手机APP连接上ESP8266创建的WIFI热点和TCP服务器,可以在手机APP上对设备端的RTC时间进行校准,设备唯一ID获取,生成随机开锁密码。
(2)随机密码开锁。手机APP与本地设备采用时间、作为算法种子,采用算法生成开锁密码,每一串的密码有效时间为一分钟。查看手机APP上显示的密码之后,在本地设备上输入完成密码对比开锁。





这里有演示的效果视频:
【基于STM32设计的动态密码锁】 https://www.bilibili.com/video/BV13Y4y1t7Gn?share_source=copy_web&vd_source=347136f3e32fe297fc17177194ce0a8b
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安装包下载
下载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 与服务器通信代码
4. STM32设备端代码设计
如果需要完整的项目源码可以去这里下载: https://download.csdn.net/download/xiaolong1126626497/85895855
4.1 硬件相关原理图




4.2 keil工程

4.3 程序下载配置

4.4 硬件接线
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;
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();
}
char TimeBuff[20];
void Update_FrameShow(void)
{
if(page_show_flag==1)
{
return;
}
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)
{
next=seed;
}
int my_rand(void)
{
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
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);
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();
Moto_Init();
BEEP_Init();
USART3_Init(115200);
TIMER3_Init(72,20000);
Touch_Configuration();
OLED_Init(0xc8,0xa1);
USART1_Printf("正在初始化WIFI请稍等.\r\n");
OLED_Clear(0);
OLED_RefreshGRAM();
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_ShowString(0,0,16,"esp8266 init ok.");
break;
}
else
{
esp8266_state=0;
OLED_Clear(0);
OLED_RefreshGRAM();
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();
OLED_Clear(0x00);
OLED_RefreshGRAM();
DrawTimeFrame();
while(1)
{
key=KEY_Scan();
if(key==1)
{
LED1=0;
time_cnt=0;
Motorcw_ring(1,300);
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);
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);
time_cnt=0;
LED2=!LED2;
}
if(page_show_flag==1 && page_display>200)
{
page_show_flag=0;
OLED_Clear(0x00);
OLED_RefreshGRAM();
DrawTimeFrame();
}
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
printf("UART3收到数据.....\r\n");
for(i=0;i<USART3_RX_CNT;i++)
{
USART1_Printf("%c",USART3_RX_BUFFER[i]);
}
if(USART3_RX_CNT>5)
{
if(strstr((char*)&USART3_RX_BUFFER[5],"open_lock"))
{
LED1=0;
Motorcw_ring(1,300);
OLED_Clear(0);
OLED_ShowString(0,0,16,"open lock.");
page_show_flag=1;
page_display=0;
}
}
char *time;
char *p=strstr((char*)USART3_RX_BUFFER,"+IPD");
if(p!=NULL)
{
p=strstr((char*)USART3_RX_BUFFER,":");
if(p!=NULL)
{
p+=1;
if(*p=='*')
{
p+=1;
time=p;
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
tm_year=(time[0]-48)*1000+(time[1]-48)*100+(time[2]-48)*10+(time[3]-48)*1;
tm_mon=(time[4]-48)*10+(time[5]-48)*1;
tm_mday=(time[6]-48)*10+(time[7]-48)*1;
tm_hour=(time[8]-48)*10+(time[9]-48)*1;
tm_min=(time[10]-48)*10+(time[11]-48)*1;
tm_sec=(time[12]-48)*10+(time[13]-48)*1;
RTC_SetTime(tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
printf("RTC时间设置成功:%d-%d-%d %d:%d:%d\r\n",tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec);
OLED_Clear(0x00);
OLED_RefreshGRAM();
DrawTimeFrame();
}
}
}
USART3_RX_CNT=0;
USART3_RX_FLAG=0;
}
MatrixKey=Touch_KeyScan();
if(MatrixKey!=0)
{
if(MatrixKey_index>10)MatrixKey_index=0;
switch(MatrixKey)
{
case 1: MatrixKey_var[MatrixKey_index++]=1+48;USART1_Printf("输入:1\r\n");break;
case 2: MatrixKey_var[MatrixKey_index++]=2+48;USART1_Printf("输入:2\r\n");break;
case 3: MatrixKey_var[MatrixKey_index++]=3+48;USART1_Printf("输入:3\r\n");break;
case 5: MatrixKey_var[MatrixKey_index++]=4+48;USART1_Printf("输入:4\r\n");break;
case 6: MatrixKey_var[MatrixKey_index++]=5+48;USART1_Printf("输入:5\r\n");break;
case 7: MatrixKey_var[MatrixKey_index++]=6+48;USART1_Printf("输入:6\r\n");break;
case 9: MatrixKey_var[MatrixKey_index++]=7+48;USART1_Printf("输入:7\r\n");break;
case 10: MatrixKey_var[MatrixKey_index++]=8+48;USART1_Printf("输入:8\r\n");break;
case 11: MatrixKey_var[MatrixKey_index++]=9+48;USART1_Printf("输入:9\r\n");break;
case 14: MatrixKey_var[MatrixKey_index++]=0+48;USART1_Printf("输入:0\r\n");break;
}
USART1_Printf("正在输入中:%s\r\n",MatrixKey_var);
if(MatrixKey==15)
{
MatrixKey_var[MatrixKey_index++]='\0';
MatrixKey_index=0;
USART1_Printf("输入的密码:%s\r\n",MatrixKey_var);
if(strcmp(MatrixKey_var,Password)==0)
{
USART1_Printf("密码正确,开锁成功.\r\n");
LED1=0;
Motorcw_ring(1,300);
OLED_Clear(0);
OLED_ShowString(0,0,16,"open lock.");
page_show_flag=1;
page_display=0;
}
else
{
USART1_Printf("密码错误,开锁失败.\r\n");
OLED_Clear(0);
OLED_ShowString(0,0,16,"password error.");
page_show_flag=1;
page_display=0;
}
}
else if(MatrixKey==12)
{
MatrixKey_index=0;
USART1_Printf("清除之前输入的密码,等待重新输入.\r\n");
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
- 360.
- 361.
- 362.
- 363.
- 364.
- 365.
- 366.
- 367.
- 368.
- 369.
- 370.
- 371.
- 372.
- 373.
- 374.
- 375.
- 376.
- 377.
- 378.
- 379.
- 380.
本文正在参加物联网有奖征文活动】,活动链接: https://ost.51cto.com/posts/14758