0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于STM32+华为云IOT实现动态口令密码锁

DS小龙哥-嵌入式技术 来源:DS小龙哥-嵌入式技术 作者:DS小龙哥-嵌入式技 2023-07-13 11:46 次阅读

1. 前言

随机密码锁是一种常见的电子锁系统,它使用数字密码代替传统的物理钥匙来进行身份验证和门锁控制。该项目基于STM32微控制器实现一个安全可靠的随机密码锁系统。

传统的机械锁存在一些安全和便捷性的问题。钥匙可能会丢失、被盗或者被复制,这会给用户带来安全风险。而且,当需要为多个用户提供访问权限时,分发和管理多个物理钥匙变得复杂。为了解决这些问题,随机密码锁系统应运而生。

随机密码锁系统基于STM32微控制器实现,具备以下特点:

  1. 高安全性:系统使用数字密码进行身份验证,密码是随机生成的,并且每次开锁时会自动更换密码。这样可以提高安全性,防止密码被破解或预测。
  2. 多用户支持:系统可以为多个用户分配不同的访问权限和密码。管理员可以轻松添加、删除或修改用户信息,并设置其对应权限。
  3. 多种开锁方式:除了密码输入外,系统还可以支持其他开锁方式,如指纹识别、刷卡等,增加了便捷性和灵活性。
  4. 电池供电:系统采用低功耗设计,可以通过电池供电,避免线路布线的限制,适用于不同的门锁应用场景。
  5. 报警功能:系统能够检测异常操作或入侵,并触发报警,提高安全性。

当前支持的开锁方式:

(1)支持手机APP远程开锁。通过华为云物联网平台实现远程发送指令开锁,设备上的ESP8266通过连接家里路由器,在连接华为云物联网平台,可以在手机APP上对设备端的RTC时间进行校准,设备唯一ID获取,生成随机开锁密码,可以点击APP上的开锁按钮,通过物联网平台提供的API发送指令给STM32设备完成开锁。

(2)随机密码开锁。手机APP与本地设备都采用时间、作为算法种子,采用算法生成开锁密码,每一串的密码有效时间为一分钟。查看手机APP上显示的密码之后,在本地设备上输入完成密码对比开锁。 在这里插入图片描述

image-20220409013820783image-20220409014126096

image-20220409014222568

2. 相关硬件

2.1 WIFI模块

image-20220404180739654

2.2 步进电机模块

image-20220404180810347

2.3 OLED显示屏

image-20220404180915854

2.4 STM32开发板

image-20220404180941848

2.5 矩阵键盘模块

image-20220404181013714

3. 手机APP设计

3.1 开发环境介绍

上位机软件采用Qt框架设计,Qt是一个跨平台的C++图形用户界面应用程序框架。Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单来说,QT可以很轻松的帮你做带界面的软件,甚至不需要你投入很大精力。

QT官网:https://www.qt.io/

image-20220314143105032

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 实现效果

在这里插入图片描述

4. 创建云端设备

4.1 创建设备

登录官网: https://www.huaweicloud.com/

直接搜索物联网,打开页面。

https://www.huaweicloud.com/product/iothub.html
1.png

选择设备接入:

image-20211215174521654

选择免费试用:

1.png

产品页面,点击右上角创建产品:

image-20211215174642960

填上产品信息:

image-20211215174937965

得到产品ID,保存好ID,点击查看详情:

产品ID为:61b9ba3a2b2aa20288c1e7f1.

image-20211215175007908

点击设备页面,注册设备:

image-20211215175814693

填充信息进行注册:

image-20211215180006268

保存设备密匙和设备ID,点击保存关闭会自动下载文件保存,后面生成密码和登录账号需要使用

image-20211215180041077

关闭后就看到创建好的设备了:

image-20211215180732602

点击产品页面,选择刚才创建的产品:

image-20211215180939201

选择自定义模型---创建数据模型服务:

image-20211215181036122

image-20211215181144359

选择新增属性,创建设备的属性

image-20211215181424235

4.2 创建MQTT登录账号和密匙

设备创建完成接来下生成MQTT登录账号、密匙,方便设备登录云端平台。

官网工具地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

image-20211215181625067

打开刚才创建设备时,下载的密匙文件,把内容复制出来对应的填进去,生成即可。

image-20211215181747129

4.3 拼接主题订阅与发布的格式

官方文档介绍: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html

image-20211215182442581

在产品页面可以,看到主题的全部格式:

image-20211215183137006

帮助文档:https://support.huaweicloud.com/iothub/index.html

总结的格式如下:

格式: $oc/devices/{device_id}/sys/messages/down
 //订阅主题: 平台下发消息给设备
 $oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down
 ​
 ​
 格式: $oc/devices/{device_id}/sys/properties/report
 //设备上报数据
 $oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report
 ​
 上属性的数据格式:
 //上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
 {"services": [{"service_id": "lock","properties":{"门锁":1}}]}

上面属性里的服务ID和属性里的名称,在设备页面,影子设备页面查看。

image-20211215184220051

4.4 MQTT客户端模拟设备登录云端

下面使用MQTT客户端模拟设备登录服务器测试,看设备创建的是否OK。

服务器的IP地址是: 121.36.42.100

端口号是: 1883

打开MQTT客户端软件,按照提示,输入相关参数后,点击连接,然后再点击订阅主题,发布主题即可:

image-20211215184435114

查看云端服务器的情况: 可以看到设备已经在线了,并且收到上传的数据。

image-20211215184612394

修改一下锁的状态,上报属性再查看:

image-20211215184712687

发现云端的状态也已经改变,现在设备上报已经OK。

image-20211215184735239

接下来测试命令下发,实现远程开锁关锁的功能:

打开产品页面,新增加命令:

image-20211215185156127

image-20211215185232075

image-20211215185302157

命令添加成功:

image-20211215185325872

在设备页面,选择同步命令下发:

image-20211215185445720

image-20211215185523035

点击确定后,查看MQTT客户端,发现已经收到数据了:

image-20211215185612755

$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497/sys/commands/request_id=88e2626f-290d-405e-962d-51554445a8fd{"paras":{"lock":1},"service_id":"lock","command_name":"lock"}

设备端解析收到的数据,就可以完成多步进电机的控制,完成开锁关锁。

5. STM32设备端代码设计

STM32连接华为云IOT的工程代码Get: https://download.csdn.net/download/xiaolong1126626497/81993720

5.1 硬件相关原理图

image-20220408224849014

image-20220408224909656

image-20220408225637885

image-20220408225751486

5.2 程序下载配置

image-20220409014444075

5.3 硬件接线

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
 -  : GND4. 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

5.4 服务器连接核心代码

//华为物联网服务器的设备信息
 #define MQTT_ClientID "61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510"
 #define MQTT_UserName "61b9ba3a2b2aa20288c1e7f1_QQ1126626497"
 #define MQTT_PassWord "385ce91dfe7da5b7431868d5d87e7998163c493344040935d5a00024d6324242"//订阅与发布的主题
 #define SET_TOPIC  "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down"  //订阅
 #define POST_TOPIC "$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report"  //发布char mqtt_message[200];//上报数据缓存区int main()
 {
    u32 time_cnt=0;
    u32 i;
    u8 key;
    LED_Init();
    BEEP_Init();
    KEY_Init();
    USART1_Init(115200);
    TIMER1_Init(72,20000); //超时时间20ms
    USART2_Init(9600);//串口-蓝牙
    TIMER2_Init(72,20000); //超时时间20ms
    USART3_Init(115200);//串口-WIFI
    TIMER3_Init(72,20000); //超时时间20ms
    USART1_Printf("正在初始化WIFI请稍等.n");
    if(ESP8266_Init())
    {
       USART1_Printf("ESP8266硬件检测错误.n");  
    }
    else
    {
       //非加密端口
       USART1_Printf("WIFI:%dn",ESP8266_STA_TCP_Client_Mode("CMCC-Cqvn","99pu58cb","121.36.42.100",1883,1));
   
    }
    
     //2. MQTT协议初始化  
     MQTT_Init(); 
     //3. 连接华为服务器        
     while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
     {
         USART1_Printf("服务器连接失败,正在重试...n");
         delay_ms(500);
     }
     USART1_Printf("服务器连接成功.n");
     
     //3. 订阅主题
     if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
     {
         USART1_Printf("主题订阅失败.n");
     }
     else
     {
         USART1_Printf("主题订阅成功.n");
     }
     ..................
     ..................
     ...................
 }

5.5 随机密码生成

#include < stdio.h >
 #include < time.h >
 #include < stdlib.h >
 #include < string.h >
 #include < windows.h >char pwdcont[] = "0123456789abcdefghijklmn";
 ​
 char* get_Password(int pwd_size)
 {
     int i;
     int random;
     char *Password = (char *)malloc(pwd_size + 1);
 ​
     //获取时间种子
     srand((unsigned)time(NULL));
 ​
     for (i = 0; i < pwd_size; i++)
     {
         random = rand() % (strlen(pwdcont));
         *(Password + i) = pwdcont[random];
     }
 ​
     *(Password + i) = '�';
     return Password;
 }
 ​
 int main()
 {
     int random;
     char *Password;
     srand((unsigned)time(NULL));
 ​
     for (int i = 0; i < 10; i++)
     {
         Sleep(100);
         random = rand() % 10;//密码的长度范围 (6-63) 
         printf("random = %dn", random);
         Password = get_Password(random);
         printf("Password = %sn", Password);
     }
     free(Password);
     return 0;
 }

5.6 RTC实时时钟代码

#include "rtc.h"//定义RTC标准结构体
 struct RTC_CLOCK rtc_clock;/*
 函数功能: RTC初始化函数
 */
 void RTC_Init(void)
 {
      if(BKP- >DR1!=0xAB) //表示RTC第一次初始化
      {
             //1. 备份寄存器时钟
             RCC- >APB1ENR|=1< < 27; //备份时钟接口
             RCC- >APB1ENR|=1< < 28; //电源时钟接口
             PWR- >CR|=1< < 8;           //允许写入RTC和后备寄存器
           
           //2. 配置RTC时钟源
             RCC- >BDCR|=1< < 0;     //开启外部32.768K时钟
           while(!(RCC- >BDCR&1< < 1)){} //等待时钟就绪
             RCC- >BDCR&=~(0x3< < 8);  //清空时钟配置
             RCC- >BDCR|=0x1< < 8;     //选择外部32.768K时钟
             
             //3. 配置RTC核心寄存器
             RCC- >BDCR|=1< < 15;     //开启RTC时钟
       while(!(RTC- >CRL&1< < 5)){} //判断上一次寄存器是否写完成
             RTC- >CRL|=1< < 4;  //进入配置模式
             RTC- >PRLH=0;      //预分频高位
             RTC- >PRLL=0x7FFF; //32767   预分频低位
             RTC- >CNTH=0;      //计数器高位
             RTC- >CNTL=0;      //计数器低位
             RTC- >ALRH=0;      //闹钟寄存器高位
             RTC- >ALRL=60;      //闹钟寄存器低位
             RTC- >CRL&=~(1< < 4);//退出配置模式  
             while(!(RTC- >CRL&1< < 5)){} //判断上一次寄存器是否写完成
             BKP- >DR1=0xAB;      //表示配置成功了   
         }
 ​
         RTC- >CRH|=1< < 0; //秒中断
         RTC- >CRH|=1< < 1; //闹钟中断
         STM32_SetPriority(RTC_IRQn,2,2); //优先级
         
         RTC_SetTime(2022,4,9,0,36,1);
 }
 ​
 extern void Update_FrameShow(void);
 /*
 函数功能: RTC闹钟中断服务函数
 */
 void RTC_IRQHandler(void)
 {
       u32 SecCnt;
         if(RTC- >CRL&1< < 0)
         {
                 SecCnt=RTC- >CNTH< < 16;//获取高位
                 SecCnt|=RTC- >CNTL;   //获取低位
                 RTC_GetTime(SecCnt); //转换标准时间
                 RTC_GetWeek(SecCnt);
              // printf("%d-%d-%d %d:%d:%d week:%dn",rtc_clock.year,rtc_clock.mon,rtc_clock.day,rtc_clock.hour,rtc_clock.min,rtc_clock.sec,rtc_clock.week);
                 Update_FrameShow(); //更新显示
                 RTC- >CRL&=~(1< < 0); //清除秒中断标志位
         }
         
         if(RTC- >CRL&1< < 1)
         {
 //              printf("闹钟时间到达!....n");
 //            BEEP=1;
 //            DelayMs(500);
 //              BEEP=0;
                 RTC- >CRL&=~(1< < 1); //清除闹钟中断标志位
         }
 }
 ​
 ​
 ​
 //闰年的月份
 static int mon_r[12]={31,29,31,30,31,30,31,31,30,31,30,31};
 //平年的月份
 static int mon_p[12]={31,28,31,30,31,30,31,31,30,31,30,31};
 ​
 ​
 /*
 函数功能: 设置RTC时间
 函数形参:
     u32 year;   2018
       u32 mon;     8
       u32 day;
         u32 hour;
         u32 min;
       u32 sec;
 */
 void RTC_SetTime(u32 year,u32 mon,u32 day,u32 hour,u32 min,u32 sec)
 {
         u32 i;
       u32 SecCnt=0; //总秒数
         /*1. 累加已经过去的年份*/
         for(i=2017;i< year;i++)  //基准年份:20170101000000
       {
                 if(RTC_GetYearState(i))
                 {
                         SecCnt+=366*24*60*60; //闰年一年的秒数
                 }
                 else
                 {
                         SecCnt+=365*24*60*60; //平年一年的秒数
                 }
         }
         /*2. 累加过去的月份*/
         for(i=0;i< mon-1;i++)
         {
               if(RTC_GetYearState(year))
                 {
                         SecCnt+=mon_r[i]*24*60*60; //闰年一月的秒数
                 }
                 else
                 {
                         SecCnt+=mon_p[i]*24*60*60; //平年一月的秒数
                 }   
         }
         
         /*3. 累加过去的天数*/
         SecCnt+=(day-1)*24*60*60;
         
         /*4. 累加过去小时*/
         SecCnt+=hour*60*60;
         
         /*5. 累加过去的分钟*/
         SecCnt+=min*60;
         
         /*6. 累加过去的秒*/
         SecCnt+=sec;
         
         /*7. 设置RTC时间*/
         RCC- >APB1ENR|=1< < 27; //备份时钟接口
         RCC- >APB1ENR|=1< < 28; //电源时钟接口
         PWR- >CR|=1< < 8;           //允许写入RTC和后备寄存器
         while(!(RTC- >CRL&1< < 5)){} //判断上一次寄存器是否写完成
         RTC- >CRL|=1< < 4;           //进入配置模式
         RTC- >CNTH=SecCnt > >16;     //计数器高位
         RTC- >CNTL=SecCnt&0xFFFF;  //计数器低位
         RTC- >CRL&=~(1< < 4);//退出配置模式  
         while(!(RTC- >CRL&1< < 5)){} //判断上一次寄存器是否写完成
 }
 ​
 ​
 /*
 函数功能: 获取RTC时间
 函数参数: u32 sec 秒单位时间
 */
 void RTC_GetTime(u32 sec)
 {
         u32 i;
         rtc_clock.year=2017; //基准年份
         
       /*1. 计算当前的年份*/
       while(1)
         {
               if(RTC_GetYearState(rtc_clock.year))
                 {
                         if(sec >=366*24*60*60) //够一年
                         {
                                 sec-=366*24*60*60;
                                 rtc_clock.year++;
                         }
                         else break;
                 }
                 else
                 {
                         if(sec >=365*24*60*60) //够一年
                         {
                                 sec-=365*24*60*60;
                                 rtc_clock.year++;
                         }
                         else break;
                 }
         }
         
         /*2. 计算当前的月份*/
         rtc_clock.mon=1;
         for(i=0;i< 12;i++)
         {
                 if(RTC_GetYearState(rtc_clock.year))
                 {
                         if(sec >=mon_r[i]*24*60*60)
                         {
                              sec-=mon_r[i]*24*60*60;
                              rtc_clock.mon++;
                         }
                         else break;     
                 }
                 else
                 {
                         if(sec >=mon_p[i]*24*60*60)
                         {
                              sec-=mon_p[i]*24*60*60;
                              rtc_clock.mon++;
                         }
                         else break; 
                 }
         }
         
         /*3. 计算当前的天数*/
         rtc_clock.day=1;
         while(1)
         {
                 if(sec >=24*60*60)
                 {
                         sec-=24*60*60;
                         rtc_clock.day++;
                 }
                 else break;
         }
         
         /*4. 计算当前的小时*/
         rtc_clock.hour=0;
         while(1)
         {
                 if(sec >=60*60)
                 {
                         sec-=60*60;
                         rtc_clock.hour++;
                 }
                 else break;
         }
         
         /*5. 计算当前的分钟*/
         rtc_clock.min=0;
         while(1)
         {
                 if(sec >=60)
                 {
                         sec-=60;
                         rtc_clock.min++;
                 }
                 else break;
         }
         
         /*6. 计算当前的秒*/
         rtc_clock.sec=sec;
 }
 ​
 ​
 /*
 函数功能: 判断年份是否是平年、闰年
 返回值  : 0表示平年 1表示闰年
 */
 u8 RTC_GetYearState(u32 year)
 {
      if((year%4==0&&year%100!=0)||year%400==0)
      {
          return 1;
      }
      return 0;
 }
 ​
 ​
 /*
 函数功能: 获取星期
 */
 void RTC_GetWeek(u32 sec)
 {
     u32 day1=sec/(60*60*24); //将秒单位时间转为天数
     switch(day1%7)
     {
         case 0:
             rtc_clock.week=0;
             break;
         case 1:
             rtc_clock.week=1;
             break;
         case 2:
             rtc_clock.week=2;
             break;
         case 3:
             rtc_clock.week=3;
             break;
         case 4:
             rtc_clock.week=4;
             break;
         case 5:
             rtc_clock.week=5;
             break;
         case 6:
             rtc_clock.week=6;
             break;
     }
 }
 ​
 /*
 将标准时间转为秒单位时间
 思路: 全程加法
 时间基准点: 1970年1月1日0时0分0秒
 返回值: 得到的秒单位时间
 */
 unsigned int TimeToSec(int year, int mon, int mdeay, int hour, int min)
 {
     int i;
     int sec_cnt = 0; //记录秒单位的时间
     /*1. 转换年*/
     for (i = 1970; i < year; i++)
     {
         if (RTC_GetYearState(i)) //闰年
         {
             sec_cnt += 366 * 24 * 60 * 60;
         }
         else
         {
             sec_cnt += 365 * 24 * 60 * 60;
         }
     }
 ​
     /*2. 转换月*/
     for (i = 0; i < mon - 1; i++)
     {
         if (RTC_GetYearState(year)) //闰年
         {
             sec_cnt += mon_r[i] * 24 * 60 * 60;
         }
         else
         {
             sec_cnt += mon_p[i] * 24 * 60 * 60;
         }
     }
 ​
     /*3. 转换天数*/
     sec_cnt += (mdeay - 1) * 24 * 60 * 60;
 ​
     /*4. 转换小时*/
     sec_cnt += hour * 60 * 60;
 ​
     /*5. 转换分钟*/
     sec_cnt += min * 60;
     return sec_cnt;
 }
 ​

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    6809

    浏览量

    147636
  • 物联网
    +关注

    关注

    2869

    文章

    41622

    浏览量

    358372
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348743
  • 密码锁
    +关注

    关注

    6

    文章

    249

    浏览量

    34570
  • 步进电机
    +关注

    关注

    149

    文章

    2929

    浏览量

    146065
  • 开发板
    +关注

    关注

    25

    文章

    4429

    浏览量

    93992
  • Qt
    Qt
    +关注

    关注

    1

    文章

    299

    浏览量

    37339
  • IOT
    IOT
    +关注

    关注

    186

    文章

    3984

    浏览量

    193202
  • 华为云
    +关注

    关注

    3

    文章

    2155

    浏览量

    16807
收藏 人收藏

    评论

    相关推荐

    基于VHDL设计的密码锁论文(2)

    要表达方式,以QuartusⅡ5.1开发软件等为设计工具设计的电子密码锁,由于其能够实现密码输入、密码校验、密码设置和更改等功能,因此,能够
    发表于 02-08 16:47

    基于单片机的红外遥控密码锁的设计与实现

    基于单片机的红外遥控密码锁的设计与实现
    发表于 08-08 00:21

    基于51的密码锁设计

    很好,很强大的密码锁设计
    发表于 08-11 10:44

    电子密码锁设计

    电子密码锁设计
    发表于 09-05 14:31

    电子密码锁

    电子密码锁 挺不错的程序
    发表于 03-28 19:27

    数字密码锁的设计

    基于51的数字密码锁设计
    发表于 05-08 19:28

    数字密码锁设计

    数字密码锁设计
    发表于 05-23 21:18

    基于ATMEGA的密码锁

    基于ATMEGA的密码锁,能够改变密码
    发表于 07-25 20:56

    电子密码锁的设计与实现

    电子密码锁的设计与实现一、实验目的1.进一步掌握键盘扫描和LED显示的程序设计。2.了解按键消抖的方法。3.综合运用微机原理的软硬件知识。二、实验内容与要求1.基本要求(1)具有密码输入功能,
    发表于 11-10 11:43

    基于STM32单片机设计的电子密码锁

    本文档的主要内容介绍了如何基于STM32单片机设计电子密码锁的详细资料概述
    发表于 09-05 16:00

    【uFun试用申请】四键动态密码锁(控制板)

    项目名称:四键动态密码锁(控制板)试用计划:四键动态密码锁可以用来对自助区域的箱柜进行开闭控制,控制板连接有电磁装置,锁具出厂时会对其进行
    发表于 04-12 18:10

    电子密码锁

    想通过multisim实现电子密码锁,请问怎么做
    发表于 09-22 10:27

    怎么实现基于单片机的电子密码锁设计?

    怎么实现基于单片机的电子密码锁设计?
    发表于 11-04 06:13

    使用单片机实现简易密码锁

    基于ATMEGA128的密码锁题目要求题目分析仿真结果主函数代码题目要求密码锁题目要求使用单片机实现简易密码锁,通过输入密码
    发表于 11-23 06:10

    密码锁的工作使用流程

    密码锁:功能介绍:1.可设置1-4位密码2.密码输入显示在数码管上3.密码验证结果显示在数码管上4.显示密码错误次数5.输入可回退6.可更改
    发表于 01-17 06:52