基于STM32F103设计的智能门锁(支持多种开锁解锁方式)

简介: 基于STM32F103设计的智能门锁(支持多种开锁解锁方式)

一、环境介绍

编程软件: keil5


主控MCU: STM32F103ZET6


射频卡读写器: RFID-RC522


步进电机: 28BYJ4  4相5线


蓝牙:  ATK-HC05


WIFI: ATK-ESP8266


物联网云平台: 采用腾讯云物联网平台,直接支持微信小程序和手机独立APP控制


完整项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/19101807



二、功能介绍

这是基于STM32设计的智能锁模型,支持多种开锁方式,详情如下:


1.  门禁卡刷卡开锁:使用RC522射频卡读卡器,读取IC卡卡号和内部数据,验证身份,开锁。


2. 蓝牙自动开锁:  业主的手机蓝牙在范围内,自动开锁(通过连接蓝牙地址确认业主身份),范围是通过蓝牙断开与连接上为准。


3. 微信小程序开锁、关锁:通过ESP8266连接腾讯云物联网平台,业主可以通过微信小程序“腾讯连连” 进行远程开锁和关锁。


如果没有使用过腾讯云物联网平台的,可以看这里:https://blog.csdn.net/xiaolong1126626497/article/details/116902653


4. 按键开锁、关锁: 可以通过开发板上的按键进行开锁和关锁(模拟物理钥匙而已)


开锁和关锁使用步进电机正转一圈、反转一圈模拟。

image.png

image.png

三、使用的相关硬件介绍

3.1  STM32F103ZET6系统板

image.png

3.2 HC05蓝牙模块

image.png

3.3 WIFI模块

image.png

3.4 RFID-RC522模块

image.png

3.5 步进电机

image.png

四、腾讯物联网平台

没有使用过物联网云平台的参考这里: https://blog.csdn.net/xiaolong1126626497/article/details/116902653

image.png

image.png

image.png

image.png

五、设备核心源码

#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 "mqtt.h"
#include "hc05_Bluetooth.h"
#include "RFID_RC522.h"
#include "motor.h"
/*
硬件连接方式:
ATK-HC-05串口蓝牙模块与STM32的串口2相连接。
PA1--LED 配对状态输出; 配对成功输出高电平,未配对则输出低电平。
PA4---KEY 用于进入 AT 状态;高电平有效(悬空默认为低电平)。
PA2--RXD 模块接收脚
PA3--TXD 模块发送脚
GND---GND 地
VCC---VCC 电源(3.3V~5.0V)
ATK-ESP8266串口WIFI模块与STM32的串口3相连接。
PB10--RXD 模块接收脚
PB11--TXD 模块发送脚
GND---GND 地
VCC---VCC 电源(3.3V~5.0V)
RC522射频模块外部的接口:    
*1--SDA <----->PB5--片选脚
*2--SCK <----->PB4--时钟线
*3--MOSI<----->PA12--输出
*4--MISO<----->PA11--输入
*5--悬空
*6--GND <----->GND
*7--RST <----->PA8--复位脚
*8--VCC <----->VCC
ULN2003控制28BYJ-48步进电机接线:
ULN2003接线:
IN4: PC9   d
IN3: PC8   c
IN2: PC7   b
IN1: PC6   a
+  : 5V
-  : GND
*/
//腾讯物联网服务器的设备信息
#define MQTT_ClientID "3XM7FNOG4Llock"
#define MQTT_UserName "3XM7FNOG4Llock;12010126;W5WOU;1624006004"
#define MQTT_PassWord "209f8dfc3079a54540aeb4263e99be24c5b0212141d8067e6348036383535941;hmacsha256"
//订阅与发布的主题
#define SET_TOPIC  "$thing/down/property/3XM7FNOG4L/lock"  //订阅
#define POST_TOPIC "$thing/up/property/3XM7FNOG4L/lock"  //发布
#define CONNECT_WIFI  "CMCC-Cqvn"   //将要连接的路由器名称 --不要出现中文、空格等特殊字符
#define CONNECT_PASS "99pu58cb"     //将要连接的路由器密码
#define CONNECT_SERVER_IP "106.55.124.154"  //服务器IP地址
#define CONNECT_SERVER_PORT 1883            //服务器端口号
char mqtt_message[200];//上报数据缓存区
unsigned char SN[4]; //存放读出的卡号
unsigned char CheckSN[4]={71,151,114,179}; //用于验证的卡号--业主的卡号用于开锁
char SendBuff[10];
/*
函数功能: 打印卡号
*/
void print_info(unsigned char *p,int cnt)
{
  int i;
  for(i=0;i<cnt;i++)
  {
    printf("%d ",p[i]);
  }
  printf("\r\n");
}
/*
函数功能: 读卡号--电子标签的卡号
返回值: 1成功 0失败
*/
int ReadCardNumber(void)
{
    unsigned char CT[2];//卡类型
  u8 status=1;
  status=RC522_PcdRequest(PICC_REQIDL ,CT);//(寻卡模式,卡类型),成功返回0
  if(status==MI_OK)//寻卡成功
  {
     status=MI_ERR;
     status=RC522_PcdAnticoll(SN);  //防冲撞,成功返回0,SN是读到卡号的地址
    printf("卡类型:");
    print_info(CT,2);//打印类型
    printf("卡号:");
      print_info(SN,4);//打印卡号 
        return 1;
  }
    return 0;
}
int main()
{
    u8 esp8266_state=0;
    u8 key;
    u8 i;
    u32 time_cnt=0;
    u8 ble_connect_flag=0;
    u8 Motor=0; //电机状态
    LED_Init();
    KEY_Init();
    USART1_Init(115200);
    RC522_Init();    //RC522 
    Moto_Init();  //步进电机初始化
    USART3_Init(115200);//串口-WIFI
    TIMER3_Init(72,20000); //超时时间20ms
    USART1_Printf("正在初始化WIFI请稍等.\r\n");
    for(i=0;i<5;i++)
    {
        if(ESP8266_Init()==0)
        {
           esp8266_state=1;
           break;
        }
        else
        {
            esp8266_state=0;
            USART1_Printf("ESP8266硬件检测错误.\n");  
        }
    }
   if(esp8266_state)
   {
       printf("准备连接服务器....\r\n");
        //非加密端口
        USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode(CONNECT_WIFI,CONNECT_PASS,CONNECT_SERVER_IP,CONNECT_SERVER_PORT,1));
        //2. MQTT协议初始化  
        MQTT_Init(); 
        //3. 连接服务器  
        for(i=0;i<5;i++)
        {
            if(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord)==0)
            {
                esp8266_state=1;
                break;
            }
            esp8266_state=0;
            USART1_Printf("服务器连接失败,正在重试...\n");
            delay_ms(500);
        }
        USART1_Printf("服务器连接成功.\n");
        //3. 订阅主题
        if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
        {
           USART1_Printf("主题订阅失败.\n");
        }
        else
        {
           USART1_Printf("主题订阅成功.\n");
        } 
   }
    /*4. 初始化HC05串口蓝牙*/
    printf("蓝牙正在初始化.........\r\n");
    USART2_RX_FLAG=0;
    while(HC05_Bluetooth_Init()){}
    /*设置当前蓝牙为从机模式---这里设置从机的代码只需要设置一次,后面就可以屏蔽掉了*/
//    HC05_Bluetooth_SetCmd((u8*)"AT+ROLE=0\r\n"); //设置为从机模式
//    if(HC05_Bluetooth_GetRoleStatus()==0)printf("当前蓝牙处于从机状态!\r\n");
//    else if(HC05_Bluetooth_GetRoleStatus()==1)printf("当前蓝牙处于主机状态!\r\n");
//    HC05_Bluetooth_SetCmd((u8*)"AT+RESET\r\n"); //复位ATK-HC05模块
    DelayMs(1000);      //等待蓝牙模块稳定
    /*2. 查询蓝牙主从状态*/
    if(HC05_Bluetooth_GetRoleStatus()==0)printf("2 当前蓝牙处于从机状态!\r\n");
    else if(HC05_Bluetooth_GetRoleStatus()==1)printf("2 当前蓝牙处于主机状态!\r\n");
    else printf("2 当前蓝牙主从状态查询失败!\r\n");
    /*3. 查看蓝牙连接状态*/
    if(HC05_LED)printf("3 当前蓝牙连接成功!\r\n");
    else printf("3 当前蓝牙未连接!\r\n");
//    /*4. 设置蓝牙的名称*/
//    if(HC05_Bluetooth_SetCmd((u8*)"AT+NAME=WBYQ_HC-05\r\n"))printf("4 蓝牙名称设置失败!\r\n");
//    else printf("4 蓝牙名称设置为 WBYQ_HC-05! \r\n");
//    /*5. 设置蓝牙配对密码*/
//    if(HC05_Bluetooth_SetCmd((u8*)"AT+PSWD=1234\r\n"))printf("5 蓝牙配对密码设置失败!\r\n"); //密码必须是4位
//    else printf("5 蓝牙配对密码设置为 1234 \r\n");
   while(1)
   {
         //按键可以测试开锁和关锁
        key=KEY_Scan(0);
        if(key==1)
        {
            LED1=0;  //亮灯--表示开锁
            time_cnt=0;
            Motorcw_ring(1,300);   //电机正转1圈
            Motor=1;
            //更新微信小程序
            sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"Motor\":%d}}",Motor);
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            USART1_Printf("更新门锁状态:开锁\r\n");
        }
        else if(key==2)
        {
            LED1=1;  //灭灯--表示关锁
            time_cnt=0;
            Motorccw_ring(1,300);  //电机反转1圈
             Motor=0;
            //更新微信小程序
            sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"Motor\":%d}}",Motor);
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            USART1_Printf("更新门锁状态:关锁\r\n");   
        } 
        DelayMs(10);
        time_cnt++;
        if(time_cnt>=50)
        {
            time_cnt=0;
            LED2=!LED2;
        }
        //微信小程序开锁方式: 接收WIFI返回的数据
        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],"\"Motor\":1"))
                {
                    LED1=0;  //亮灯--表示开锁
                     //开锁
                    //执行开锁代码--电机正转
                    Motorcw_ring(1,300);   //电机正转1圈
                     Motor=1;
                }
                //关锁
                else if(strstr((char*)&USART3_RX_BUFFER[5],"\"Motor\":0"))
                {
                    LED1=1;  //灭灯--表示关锁
                    //关锁
                    //执行开锁代码--电机反转
                   Motorccw_ring(1,300);  //电机反转1圈  
                   Motor=0;
                }
            }
            USART3_RX_CNT=0;
            USART3_RX_FLAG=0;
        }
     //RC522开锁方式:  读取IC卡号
        if(ReadCardNumber())
        {
            sprintf(SendBuff,"%x%x%x%x\r\n",SN[0],SN[1],SN[2],SN[3]);
            //比较卡号是否是业主的卡号,决定是否需要开锁
            int i=0;
            for(i=0;i<4;i++)
            {
                if(CheckSN[i]!=SN[i])break;
            }
            //如果是业主,就开锁
            if(i==4)
            {
                 LED1=0;  //亮灯--表示开锁
                //更新微信小程序
                sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"Motor\":%d}}",Motor);
                MQTT_PublishData(POST_TOPIC,mqtt_message,0);
                USART1_Printf("更新门锁状态:开锁\r\n");
                 Motor=1;
                 //执行开锁代码--电机正转
                 Motorcw_ring(1,300);   //电机正转1圈    
            }
        }
        if(USART2_RX_FLAG)
        {
            USART2_RX_BUFFER[USART2_RX_CNT]='\0';
            USART1_Printf("蓝牙:%s\r\n",USART2_RX_BUFFER);
            USART2_RX_CNT=0;
            USART2_RX_FLAG=0;
        }
        //蓝牙解锁方式: 离开范围就自动关锁   连接上就自动解锁
        // 区分业主身份方式: 使用蓝牙的配对密码区分.
        if(HC05_LED==1 && Motor==0) //关锁状态才需要开始
        {
            LED1=0;  //亮灯--表示开锁
            ble_connect_flag=1; //表示蓝牙已经连接过
            printf("蓝牙已经连接.\r\n");
             Motor=1;
            //更新微信小程序
            sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"Motor\":%d}}",Motor);
            MQTT_PublishData(POST_TOPIC,mqtt_message,0);
            USART1_Printf("更新门锁状态:开锁\r\n");
              //开锁
            //执行开锁代码--电机正转
            Motorcw_ring(1,300);   //电机正转1圈
        }      
        else
        {
            //之前蓝牙连接过
            if(ble_connect_flag)
            {
                ble_connect_flag=0; //清除标记
                LED1=1;  //关灯--表示上锁
                printf("蓝牙已经断开.\r\n");
                Motor=0;
                //关锁
                //执行开锁代码--电机反转
                Motorccw_ring(1,300);  //电机反转1圈
                //更新微信小程序
                sprintf(mqtt_message,"{\"method\":\"report\",\"clientToken\":\"123\",\"params\":{\"Motor\":%d}}",Motor);
                MQTT_PublishData(POST_TOPIC,mqtt_message,0);
                USART1_Printf("更新门锁状态:关锁\r\n");
            }   
        }
   }
}


相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
2月前
|
安全 物联网 数据安全/隐私保护
基于STM32的智能门锁
基于STM32的智能门锁
106 41
|
6月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
474 2
|
5月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
791 0
|
7月前
|
传感器
STM32标准库ADC和DMA知识点总结-1
STM32标准库ADC和DMA知识点总结
|
6月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
537 4
|
6月前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
801 2
|
6月前
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
269 1
|
6月前
|
开发者
【经典案例】使用HAL库配置STM32F407的SPI外设
在嵌入式系统开发中,STM32F407是一款广泛应用的微控制器,而SPI(Serial Peripheral Interface)是一种常用的通信接口。本文将详细介绍如何使用STM32的硬件抽象层(HAL)库配置STM32F407的SPI外设,并提供完整的代码示例。
648 1
|
5月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
207 0
下一篇
DataWorks