基于STM32并能实时上传云平台开关状态的智能门禁警报系统 - 学习笔记

一、项目简介

本项目是一个结合物联网通信与嵌入式控制的智能门禁警报系统,核心目标是实现用户身份验证(密码/指纹)后控制门锁状态,并能将门锁状态通过ESP8266上传至云平台,达到实时同步与远程管理的效果。

项目主要功能如下:

  • 支持6位数字密码或指纹登录
  • 指纹登录显示指纹ID
  • 登录失败3次启动报警(LED闪烁或蜂鸣器报警)
  • 继电器控制报警装置
  • 登录成功后通过串口控制ESP8266同步门锁状态到云平台
  • 支持:
    • 新增指纹(双次按压、选择ID、最多100个)
    • 删除指纹(指定ID或全部清除)
    • 修改密码
    • 退出登录并同步云平台状态
  • 云平台状态实时回传,判断是否允许进入登录流程

二、使用硬件清单

硬件名称 说明
STM32F103C8T6 主控单片机
ESP8266 从控通信模块,用于云平台数据上传
ESP32 从控通信模块,用于获取当前城市天气信息
AS608 指纹识别模块
继电器 + LED灯 模拟开锁
有缘蜂鸣器 模拟警报系统
4x4矩阵键盘 用于密码输入
OLED显示屏 信息反馈显示
RC522 射频卡验证模块

三、接线说明

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
stm32_PB11(RX)->AS608_TXD
stm32_PB10(TX)->AS608_RXD
AS608接3.3V电源

stm32_PA10(RX)->ESP8266_TX
stm32_PA9(TX)->ESP8266_RX
ESP8266接3.3V电源

stm32_PB8->OLED_SCL
stm32_PB9->OLED_SDA
OLED接3.3V电源

4*4矩阵键盘
C4->A0;C3->A1;C2->A11;C1->A12;R1->A4;R2->A5;R3->A6;R4->A7

RC522
RST->A8
SDA->B12
SCK->B13
MOSI->B15
MISO->B14

stm32_PB3>继电器_IN
继电器接5V电源

有源蜂鸣器
I/O->B4

ESP32
D17->A3
D16->A2

四、功能流程描述

  1. 开机进入登录界面:
    • 选择密码登录或指纹登录
    • 登录失败信息在OLED上提示
    • 失败3次触发报警(LED闪烁),锁定所有功能
  2. 解锁成功后:
    • 继电器打卡模拟开锁
    • 同时STM32通过串口发送命令给ESP8266
    • ESP8266接收后上传云平台,更新开门状态
  3. 云平台状态变化时:
    • ESP8266接收并返回数据给STM32
    • STM32据此允许/阻止登录流程
  4. 登录成功界面可执行:
    • 新增指纹(双次比对、手动输入ID)
    • 删除指纹(单个或全部删除)
    • 更改六位密码(双次输入比对)
    • 退出并关闭门(舵机转回0°)

五、遇到的问题与解决

问题一描述:舵机驱动冲突导致无法响应

在项目中,SG90舵机使用PWM信号控制,最初配置为TIM4的通道输出,但后来在项目中引入了另一个模块(如通用定时器或按键消抖),也使用了TIM4,导致定时器资源冲突。

具体表现:

  • 舵机单独模块测试可运行
  • 加入完整工程后失效
  • OLED正常、按键响应正常,仅舵机无动作

解决方案:

  • 修改舵机驱动文件,将原本使用的 TIM4_CH2 改为 TIM2_CH2
  • 对应引脚从原 PB7 更换为 PA1,并修改 PWM_Init() 中的初始化配置
  • 避免与其他定时器冲突,确保一个定时器只服务一个功能模块

修改代码片段示例:

1
2
3
4
5
6
7
8
9
10
11
12
// pwm.c
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // PA1 对应 TIM2_CH2
...
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);

修改后舵机恢复正常响应,问题成功解决。


问题二描述:定时器中断函数为何无需手动调用

在项目中,TIM2_IRQHandler 函数定义在 timer.c 中,但并未看到在代码中手动调用它,这让人疑惑它是怎么被执行的。

原因:这是由中断向量表 + 弱符号机制自动完成的

中断向量与弱符号覆盖机制

1. 中断向量表(Interrupt Vector Table)

  • 位于启动文件 startup_stm32f10x_xx.s 中。
  • 每条中断都有一个对应的处理函数名,如:
    1
    2
    .weak   TIM2_IRQHandler
    .thumb_set TIM2_IRQHandler, Default_Handler
    • .weak:将 TIM2_IRQHandler 标记为弱符号(weak)
    • .thumb_set:默认指向通用空处理函数 Default_Handler

2. 弱符号(Weak Symbol)与强符号(Strong Symbol)

  • 弱符号(weak)
    • 如果用户代码中没有提供同名实现,链接器会使用默认的空函数。
  • 强符号(strong)
    • 用户在任意 C 源文件中直接定义同名函数(不带 .weak),即成为强符号。
    • 链接时会优先使用强符号,覆盖原有弱符号。

3. 覆盖中断处理函数

  • 步骤:在用户代码(如 timer.c)中写下:
    1
    2
    3
    void TIM2_IRQHandler(void) {
    // 用户自定义的中断处理逻辑
    }
  • 链接阶段:链接器检测到强符号,自动替换启动文件中弱符号的默认空实现。
  • 运行时:当 TIM2 产生中断,NVIC 根据向量表自动跳转到你在 timer.c 中定义的 TIM2_IRQHandler

4. 文件路径示例

1
2
3
4
5
6
7
8
9
Libraries/
CMSIS/
Device/
ST/
STM32F10x/
Source/
Templates/
TrueSTUDIO/ ← 或 Keil、GCC 目录
startup_stm32f10x_md.s

5. 小结

  • 中断函数 不需手动调用,只需定义同名强符号即可覆盖。
  • 模块化:启动文件中只做弱声明,用户代码中负责实现具体逻辑。
  • 自动跳转:硬件 + NVIC + 向量表协作让中断处理透明高效。

六、总结

本项目通过STM32和ESP8266协作实现了一个功能完善的智能门禁系统,不仅具备多种身份验证方式,还能通过网络实时同步开关状态,实现远程数据监控。项目过程中也积累了丰富的嵌入式调试经验,如定时器资源冲突的排查处理,为后续更复杂系统开发提供了良好实践基础。

tip

1
2
//具体项目文件可访问本人github仓库
https://github.com/hjnb1314/STM32_ESP8266_AccessControl.git

以下为实物演示视频

1
2
由于功能较多,演示视频较长,如需要查看可进入以下网址进行下载查看
https://www.123684.com/s/TOZATd-OJ1Bh