基于STM32单片机的智能门禁系统设计
摘要:随着科学技术的不断革新和信息时代集成电路的爆炸式发展,门禁系统在智能家居和安全防范领域扮演着至关重要的角色。本文设计了一种基于STM32F103C8T6单片机的智能门禁系统,该系统整合了AS608指纹模块、RC522 RFID识别模块、ESP8266 WiFi模块、继电器控制电磁锁模块、蜂鸣器模块、独立按键模块以及0.96寸OLED显示屏模块,实现了多重身份验证方式和远程控制功能,提高了门禁系统的安全性和便捷性。
关键词:STM32单片机;门禁系统;指纹识别;RFID识别;WiFi远程控制
一、引言
门禁系统作为现代建筑安全的重要组成部分,已经由传统的机械门锁发展成为具备多种身份验证方式和远程控制功能的智能系统。随着生物识别技术、无线通信技术以及微电子技术的飞速发展,门禁系统的安全性和便捷性得到了显著提升。本文设计了一种基于STM32单片机的智能门禁系统,旨在满足现代建筑对门禁系统的高要求。
二、系统硬件设计
2.1 主控模块
本系统采用STM32F103C8T6单片机作为主控芯片。STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,具有高性能、低功耗、易于开发等优点。该单片机具有丰富的外设接口,包括USART、I2C、SPI等,可以满足本系统中各种外设的连接需求。
2.2 指纹模块
本系统采用AS608指纹模块进行指纹识别。AS608指纹模块具有识别速度快、准确率高、体积小巧等优点,适用于各种门禁系统。该模块通过串口与STM32单片机进行通信,可以完成指纹的录入、存储、识别等功能。
2.3 RFID模块
本系统采用RC522 RFID识别模块进行IC卡的识别。RC522模块支持Mifare S50、S70等IC卡的读写操作,具有读写速度快、识别准确率高、抗干扰能力强等优点。该模块通过SPI接口与STM32单片机进行通信,可以完成IC卡的读取、验证等功能。
2.4 WiFi模块
本系统采用ESP8266 WiFi模块实现远程控制功能。ESP8266是一款低功耗的WiFi SoC,支持TCP/IP协议栈,可以通过WiFi网络与智能手机、电脑等终端设备进行通信。该模块通过串口与STM32单片机进行通信,可以完成远程开锁、密码设置等操作。
2.5 继电器控制电磁锁模块
本系统采用继电器控制电磁锁模块实现门禁的开关功能。继电器模块通过控制电磁锁的通断电来实现门禁的开关操作。该模块通过GPIO接口与STM32单片机进行连接,可以接收单片机的控制信号来完成门禁的开关动作。
2.6 蜂鸣器模块
本系统采用蜂鸣器模块实现开锁识别报警功能。当门禁系统成功识别指纹、IC卡或接收到远程开锁信号时,蜂鸣器会发出提示音;当验证失败或发生非法操作时,蜂鸣器会发出报警声。该模块通过GPIO接口与STM32单片机进行连接,可以接收单片机的控制信号来发出提示音或报警声。
2.7 独立按键模块
本系统采用独立按键模块实现密码输入和重置密码功能。用户可以通过按键输入预设的密码来解锁门禁;同时,管理员可以通过按键进入密码重置模式来重新设置密码。该模块通过GPIO接口与STM32单片机进行连接,可以接收按键的输入信号来完成密码输入和重置密码操作。
2.8 显示模块
本系统采用0.96寸OLED显示屏模块实现实时信息显示功能。该显示屏可以显示门禁系统的设置信息、指纹录入状态、指纹识别结果、密码设置和识别结果、IC卡识别结果以及远程开锁状态等信息。该模块通过I2C接口与STM32单片机进行通信,可以接收单片机的控制信号来显示相关信息。
三、系统软件设计
3.1 开发环境
本系统采用STM32CubeMX软件进行初始化配置,使用Keil uVision或STM32CubeIDE进行代码的编写、调试和下载。STM32CubeMX是一款图形化的软件配置工具,可以方便地配置STM32单片机的外设和时钟等参数;Keil uVision和STM32CubeIDE则是两款常用的STM32单片机开发环境,支持C语言的编写和调试。
3.2 主程序设计
本系统的主程序包括系统初始化、外设初始化、主循环等部分。在系统初始化阶段,主要完成单片机的时钟配置、GPIO口配置、USART接口配置、I2C接口配置等;在外设初始化阶段,主要完成指纹模块、RFID模块、WiFi模块、显示模块等外设的初始化配置;在主循环阶段,主要完成各种身份验证方式的处理、远程控制命令的接收和处理以及门禁开关动作的控制等。
3.3 指纹识别程序设计
指纹识别程序主要负责指纹的录入、存储和识别。当用户进行指纹录入操作时,程序会控制指纹模块采集指纹图像并进行处理;当用户进行指纹识别操作时,程序会控制指纹模块读取指纹图像并与存储的指纹模板进行比对,根据比对结果输出指纹识别结果。
3.4 RFID识别程序设计
RFID识别程序主要负责IC卡的读取和验证。当用户将IC卡靠近RFID模块时,程序会控制RFID模块读取IC卡的信息并进行处理;然后程序会将读取到的IC卡信息与存储的合法IC卡信息进行比对,根据比对结果输出IC卡识别结果。
3.5 WiFi远程控制程序设计
WiFi远程控制程序主要负责接收和处理来自智能手机、电脑等终端设备的远程控制命令。当终端设备发送远程开锁或密码设置等命令时,程序会通过WiFi模块接收命令并进行解析;然后根据命令的类型和内容执行相应的操作,如控制门禁开关、更新密码等。
3.6 显示程序设计
显示程序主要负责在OLED显示屏上显示门禁系统的相关信息。程序会根据当前的系统状态和用户操作实时更新显示屏上的内容,如显示指纹录入状态、指纹识别结果、密码设置和识别结果、IC卡识别结果以及远程开锁状态等信息。
3.7 报警程序设计
报警程序主要负责在验证失败或发生非法操作时发出报警声。当门禁系统检测到验证失败或发生非法操作时,程序会控制蜂鸣器模块发出报警声以提醒用户和管理员注意。
四、系统测试与验证
在系统设计和实现完成后,进行了系统的测试和验证工作。测试内容主要包括指纹识别测试、RFID识别测试、WiFi远程控制测试、门禁开关测试以及报警功能测试等。测试结果表明,本系统能够准确地识别指纹和IC卡信息,实现远程开锁和密码设置等功能;同时,在验证失败或发生非法操作时能够及时发出报警声提醒用户和管理员注意。此外,本系统还具有操作简单、稳定性好、功耗低等优点。
五、结论
本文设计了一种基于STM32单片机的智能门禁系统,该系统整合了指纹识别、RFID识别、WiFi远程控制等多种身份验证方式和远程控制功能。测试结果表明,本系统具有较高的安全性和便捷性,能够满足现代建筑对门禁系统的高要求。未来,可以进一步优化系统的算法和硬件设计,提高系统的识别速度和准确性;同时,可以扩展系统的功能和应用场景,如增加人脸识别、语音识别等身份验证方式以及与其他智能家居系统的联动控制等。
#include "iic.h"
#include "usart.h"
uint8_t ack;
void IIC_GPIO_INIT(void)
{
#if hardware
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB,&GPIO_InitStruct);
RCC_APB1PeriphClockCmd(IIC_CLK, ENABLE);
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; /* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
I2C_InitStructure.I2C_OwnAddress1 = 0X0a;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* I2C的寻址模式 */
I2C_InitStructure.I2C_ClockSpeed = IIC_CLK_Hz; /* 通信速率 */
I2C_Init(IIC_PORT, &I2C_InitStructure); /* IIC_PORT 初始化 */
I2C_Cmd(IIC_PORT, ENABLE); /* 使能 IIC_PORT */
#else
RCC_APB2PeriphClockCmd(IIC_SCL_CLK | IIC_SDA_CLK,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD ;
GPIO_InitStruct.GPIO_Pin = IIC_SCL_GPIO_Pin;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_SCL_PORT,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = IIC_SDA_GPIO_Pin;
GPIO_Init(IIC_SDA_PORT,&GPIO_InitStruct);
#endif
}
#if hardware
void IIC_Write_Byte(uint8_t device_addr,uint8_t register_addr,uint8_t data)
{
I2C_GenerateSTART(IIC_PORT, ENABLE);
while(!I2C_CheckEvent(IIC_PORT, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(IIC_PORT, device_addr, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(IIC_PORT, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(IIC_PORT, register_addr);
while(!I2C_CheckEvent(IIC_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(IIC_PORT, data);
while(!I2C_CheckEvent(IIC_PORT, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(IIC_PORT, ENABLE);
}
uint8_t IIC_Read_Byte(uint8_t device_addr,uint8_t register_addr)
{
uint8_t data;
I2C_GenerateSTART(IIC_PORT,ENABLE);
while(!I2C_CheckEvent(IIC_PORT,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(IIC_PORT,device_addr,I2C_Direction_Transmitter);
while(!I2C_CheckEvent(IIC_PORT,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(IIC_PORT,register_addr);
while(!I2C_CheckEvent(IIC_PORT,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTART(IIC_PORT,ENABLE);
while(!I2C_CheckEvent(IIC_PORT,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(IIC_PORT,device_addr,I2C_Direction_Receiver);
while(!I2C_CheckEvent(IIC_PORT,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(IIC_PORT,DISABLE);
while(I2C_GetFlagStatus(IIC_PORT,I2C_FLAG_RXNE) == RESET);
data=I2C_ReceiveData(IIC_PORT);
I2C_GenerateSTOP(IIC_PORT ,ENABLE);
return data;
}
#else
void IIC_Delay(void)
{
uint8_t i=6; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入
while(i--);
}
void IIC_Start(void)
{
IIC_SCL_1;
IIC_SDA_1;//启始信号建立时间 0.6us 400KHz
IIC_Delay();
IIC_SDA_0;
IIC_Delay();//启始信号保持时间0.6us
IIC_SCL_0;
IIC_Delay();//时钟低电平时间1.3us
}
void IIC_Stop(void)
{
IIC_SDA_0;
IIC_SCL_1;
IIC_Delay();//结束信号建立时间0.6us
IIC_SDA_1;
IIC_Delay();//总线空闲时间时间1.3us
}
void IIC_Send_Byte(uint8_t byte)
{
uint8_t i;//先发送高位
for(i=0;i<8;i++)
{
if(byte & 0x80)
{
IIC_SDA_1;
}
else
{
IIC_SDA_0;
}
IIC_Delay();
IIC_SCL_1;
IIC_Delay();
IIC_SCL_0;
IIC_Delay();
byte<<=1;
}
IIC_SDA_1;
IIC_Delay();
IIC_SCL_1;
IIC_Delay();
if(IIC_SDA_READ)
{
ack=1;
}
else
{
ack=0;
}
IIC_SCL_0;
IIC_Delay();
}
uint8_t IIC_Receive_Byte(void)
{
uint8_t receive=0;
uint8_t i;//置数据线为输入方式
for(i=0;i<8;i++)
{
receive<<=1;
IIC_SCL_1;//置时钟线为高使数据线上数据有效
IIC_Delay();
if(IIC_SDA_READ)
{
receive++;//读数据位,接收的数据位放入retc中
}
IIC_SCL_0;
IIC_Delay();
}
return receive;
}
uint8_t IIC_Write_Byte(uint8_t device_addr,uint8_t register_addr,uint8_t data)
{
IIC_Start();
IIC_Send_Byte(device_addr+0);
if (ack == 1)return 0;
IIC_Send_Byte(register_addr);
if (ack == 1)return 0;
IIC_Send_Byte(data);
if (ack == 1)return 0;
IIC_Stop();
return 1;
}
void I2C_Ack(uint8_t a)
{
if(a)
{
IIC_SDA_1; //非应答
IIC_Delay();
IIC_SCL_1;
IIC_Delay();
IIC_SCL_0;
IIC_Delay();
}
else
{
IIC_SDA_0; //应答
IIC_Delay();
IIC_SCL_1;
IIC_Delay();
IIC_SCL_0;
IIC_Delay();
IIC_SDA_1;
}
}
uint8_t IIC_Read_Byte(uint8_t device_addr,uint8_t register_addr)
{
uint8_t read_data;
IIC_Start();
IIC_Send_Byte(device_addr+0);
if (ack == 1)return 0;
IIC_Send_Byte(register_addr);
if (ack == 1)return 0;
IIC_Start();
IIC_Send_Byte(device_addr+1);
if (ack == 1)return 0;
read_data = IIC_Receive_Byte();
I2C_Ack(1);
IIC_Stop();
return read_data;
}
uint8_t IIC_Write_Array(uint8_t device_addr,uint16_t register_addr,u8 *Data,uint16_t Num)
{
uint16_t i;
IIC_Start();
IIC_Send_Byte(device_addr+0);
if (ack == 1)return 0;
IIC_Send_Byte(register_addr);
if (ack == 1)return 0;
IIC_Start();
IIC_Send_Byte(device_addr+1);
if (ack == 1)return 0;
for(i=0;i<Num;i++)
{
IIC_Send_Byte(*Data++);
if (ack == 1)return 0;
}
IIC_Stop();
return 1;
}
uint8_t IIC_Read_Array(uint8_t device_addr,uint16_t register_addr,uint8_t *Data,uint16_t Num)
{
uint16_t i;
IIC_Start();
IIC_Send_Byte(device_addr+0);
if (ack == 1)return 0;
IIC_Send_Byte(register_addr);
if (ack == 1)return 0;
IIC_Start();
IIC_Send_Byte(device_addr+1);
if (ack == 1)return 0;
for(i=0;i<Num;i++)
{
*Data++ = IIC_Receive_Byte();
if(i==Num-1)
I2C_Ack(1);
else
I2C_Ack(0);
}
IIC_Stop();
return 1;
}
#endif