10 KiB
10 KiB
STM32 固件端文档
1. STM32 在系统中做什么
STM32 是整套考勤机的主控。它不做人脸识别,人脸识别由 K210 完成。STM32 负责把 K210 的识别结果变成“是否允许签到”的业务判断,并控制硬件反馈。
它主要做这些事:
- 初始化 OLED、蜂鸣器、LED、串口、RTC、光敏传感器、补光灯等硬件。
- 接收 K210 通过 USART3 发来的识别结果。
- 判断识别置信度是否足够。
- 判断当前时间是否在服务端配置的签到时间段内。
- 判断当前学生在本时间段是否已经签过。
- 生成签到记录。
- 使用 AES-128-CBC 加密签到 JSON。
- 通过 ESP8266 发送 HTTP 请求到服务端。
- 网络异常时把记录留在本地,后续自动重试。
2. 相关文件
| 文件 | 作用 |
|---|---|
User/main.c |
主程序入口、初始化流程、主循环、联网和同步调度 |
Hardware/Attendance.c |
考勤业务逻辑:时间段、重复判断、本地记录、同步状态 |
Hardware/Attendance.h |
考勤数据结构和函数声明 |
Hardware/K210_USART.c |
解析 K210 串口识别结果 |
Hardware/esp8266.c |
ESP8266 AT 指令、HTTP GET/POST、对时、查重 |
Hardware/Crypto.c |
AES-128-CBC 加密和 Base64 编码 |
Hardware/DS1302.c |
DS1302 RTC 时钟读写 |
Hardware/LightSensor.c |
光敏电阻 ADC 和补光灯控制 |
Hardware/Buzzer_LED.c |
蜂鸣器、成功 LED、状态 LED |
Hardware/OLED.c |
OLED 显示 |
System/Delay.c |
延时和毫秒计时 |
System/Debug.c |
调试串口输出 |
Project.uvprojx |
Keil 工程文件 |
3. 硬件连接
| 外设 | STM32 引脚 | 说明 |
|---|---|---|
| ESP8266 TX/RX | PA10 / PA9 | USART1,波特率 115200 |
| K210 TX/RX | PB11 / PB10 | USART3,波特率 115200 |
| 调试串口 | PA3 / PA2 | USART2,波特率 115200 |
| OLED SCL/SDA | PB8 / PB9 | I2C |
| 成功 LED | PB4 | 高电平点亮 |
| 蜂鸣器 | PB5 | 低电平触发 |
| 光敏传感器 | PB0 | ADC1 通道 8 |
| 补光灯 | PB1 | 高电平点亮 |
| DS1302 CLK/DAT/RST | PA4 / PA5 / PA6 | 软件 GPIO 时序 |
| 板载状态 LED | PC13 | 低电平点亮,初始化中亮,就绪后灭 |
4. 代码中的主要配置
位置:User/main.c
| 配置 | 当前值 | 说明 |
|---|---|---|
WIFI_SSID |
yzfh |
ESP8266 要连接的 WiFi |
WIFI_PASSWORD |
yzfhroot |
WiFi 密码 |
HTTP_SERVER_IP |
27.106.113.205 |
服务端 IP |
HTTP_SERVER_PORT |
8082 |
服务端 HTTP 端口 |
HTTP_API_TOKEN |
atk_nKfVWLhMjL0RGSfRll3R_sdJS6IrIjuV |
API Token |
CLASS_ID |
1 |
当前 STM32 设备所属班级编号 |
TIME_SYNC_INTERVAL_MS |
3600000 |
每小时对时一次 |
TIMESLOT_DOWNLOAD_INTERVAL_MS |
30000 |
每 30 秒检查一次时间段配置 |
WIFI_RECONNECT_INTERVAL_MS |
30000 |
WiFi 断开后每 30 秒重连 |
RECONNECT_INTERVAL_MS |
5000 |
服务端连接不可用后每 5 秒尝试重连 |
MIN_CONFIDENCE_THRESHOLD |
0.75 |
最低识别置信度 |
MAX_ATTENDANCE_RECORDS |
100 |
STM32 本地最多缓存 100 条记录 |
MAX_TIME_SLOT_COUNT |
10 |
最多支持 10 个签到时间段 |
5. 启动流程
STM32 上电后按下面顺序执行:
- 初始化调试串口。
- 初始化延时模块。
- 初始化 OLED。
- 初始化蜂鸣器和 LED。
- 初始化 USART1,用于连接 ESP8266。
- 初始化 USART3,用于接收 K210 数据。
- 初始化考勤模块。
- 初始化 AES 加密模块。
- 初始化 DS1302,并尝试读取时间。
- 初始化光敏传感器和补光灯。
- 初始化 ESP8266。
- 连接 WiFi。
- 从服务端获取当前时间。
- 连接 HTTP 服务端。
- 下载签到时间段配置。
- 下载今日当前时段已签到记录。
- 进入主循环。
如果 WiFi 或服务端连接失败,程序不会停机,而是进入离线或重连状态。后续主循环会自动重试。
6. 主循环每次做什么
User/main.c 的主循环大致如下:
while (1) {
ProcessBeep();
UpdateCurrentTime();
CheckServerConnection();
SyncPendingRecords();
UpdateTimeSlotConfig();
LightSensor_Update();
if (K210_GetRxFlag()) {
Attendance_ProcessFaceResult(&K210_FaceResult);
}
}
逐项解释:
| 函数 | 作用 |
|---|---|
ProcessBeep |
非阻塞处理蜂鸣器和成功 LED |
UpdateCurrentTime |
从 DS1302 或软件时钟维护当前时间,并定期网络对时 |
CheckServerConnection |
检查当前 HTTP/TCP 连接状态,连接不可用时按需重连 |
SyncPendingRecords |
把本地未同步记录加密上传 |
UpdateTimeSlotConfig |
定期下载服务端签到时间段 |
LightSensor_Update |
根据环境光自动开关补光灯 |
K210_GetRxFlag |
看是否收到 K210 的新识别结果 |
注意:当前 STM32 HTTP 请求和服务端响应都使用 Connection: close,所以它不是长期保持一个 TCP 长连接,而是在每次请求前检查连接状态,并在需要时重新建立连接。
7. K210 发给 STM32 的数据格式
K210 通过 UART1 发送文本,STM32 通过 USART3 接收。
识别成功:
ID:20240001,NAME:Zhang_San,CONF:0.95
字段说明:
| 字段 | 含义 |
|---|---|
ID |
学号或 K210 同步后的身份编号 |
NAME |
显示名,K210 代码中会用下划线代替空格 |
CONF |
置信度,范围一般是 0.0 到 1.0 |
未识别:
UNKNOWN
STM32 收到 UNKNOWN 后不会签到。
8. 签到判断逻辑
STM32 对一次识别结果的判断顺序如下:
- 判断 K210 是否识别成功。
- 判断置信度是否低于
0.75。 - 判断当前是否在启用的时间段内。
- 判断当前时段本地记录中是否已经有该学生。
- 判断从服务端下载的今日缓存中是否已经有该学生。
- 如果服务端在线,再调用服务端查重接口确认。
- 通过所有检查后,生成一条本地考勤记录。
- 如果服务端在线,后续同步任务会加密上传。
当前默认没有任何时间段。必须由 Qt 管理端新增并保存时间段,否则第 3 步会失败,OLED 会显示不在签到时间。
9. 时间段同步
STM32 调用:
GET /api/v1/sync/state?client=stm32&last_version=<本地版本>
服务端返回示例:
{
"version": 5,
"changed": true,
"client": "stm32",
"server_time": "2026-05-01 10:00:00",
"state": {
"time_slots": [
{
"name": "上午签到",
"start_time": "08:00",
"end_time": "09:30",
"enabled": true
}
]
}
}
如果 time_slots 是空数组,STM32 会清空本地时间段配置。
10. 今日记录缓存
STM32 为了减少重复签到,会在开机连接服务端后下载今日当前时间段的已签到学号:
GET /api/v1/attendance/today?slot_start=08:00&slot_end=09:30
返回:
{
"date": "2026-05-01",
"records": ["20240001", "20240002"]
}
下载后,STM32 会把这些学号放进缓存。之后如果同一个学生在同一个时段再次识别,会被判定为重复签到。
11. 加密上传
STM32 上传签到记录时使用:
POST /api/v1/attendance/checkins
X-Api-Token: <Token>
X-Encrypted: AES128-CBC
Content-Type: application/octet-stream
请求体是 Base64 编码后的 AES 密文。明文 JSON 类似:
{
"student_id": "20240001",
"name": "Zhang San",
"confidence": 0.95,
"status": "success",
"class_id": "1"
}
服务端解密成功后写入 attendance.db。
12. 本地记录和同步状态
STM32 的本地记录结构体:
typedef struct {
char student_id[20];
char student_name[32];
float confidence;
uint32_t timestamp;
uint8_t time_slot;
SyncStatus sync_status;
uint8_t retry_count;
uint32_t last_retry_time;
} AttendanceRecord;
同步状态:
| 状态 | 含义 |
|---|---|
SYNC_PENDING |
新记录,等待上传 |
SYNC_SYNCING |
正在上传 |
SYNC_SYNCED |
上传成功 |
SYNC_FAILED |
上传失败,后续重试 |
13. OLED 和声光反馈
| 情况 | OLED | 蜂鸣器/LED |
|---|---|---|
| 初始化中 | 显示 ESP/WiFi/HTTP 状态 | PC13 状态灯亮 |
| 服务端在线 | System Ready / Online Mode |
成功提示 |
| WiFi 在线但服务端断开 | System Ready / Reconnecting.. |
后台重连 |
| WiFi 正在重连 | System Ready / WiFi retry... |
后台重连 |
| ESP8266 不可用 | System Ready / Offline Mode |
错误提示 |
| 签到成功 | Check-in OK! |
成功提示 |
| 重复签到 | Already Signed! |
错误提示 |
| 置信度低 | Low Confidence |
错误提示 |
| 不在时间段 | Not Check Time |
错误提示 |
14. 编译与烧录
使用 Keil 打开:
Project.uvprojx
一般步骤:
- 安装 Keil MDK 和 STM32F10x 支持包。
- 打开
Project.uvprojx。 - 确认芯片型号和启动文件与实际开发板一致。
- 修改
User/main.c中的 WiFi、服务端 IP、班级编号和 Token。 - 编译工程。
- 使用 ST-Link 或串口 Bootloader 烧录。
- 打开调试串口查看日志。
15. 调试建议
15.1 先看调试串口
调试串口会输出:
- 硬件初始化状态。
- ESP8266 AT 指令结果。
- WiFi 连接结果。
- HTTP 服务端连接结果。
- 时间同步结果。
- 时间段下载结果。
- K210 原始数据和解析结果。
- 加密上传结果。
15.2 常见问题
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 一直显示 WiFi retry | SSID/密码错误、ESP8266 没接好、供电不足 | 检查 WIFI_SSID、WIFI_PASSWORD、供电和串口 |
| HTTP connection failed | 服务端 IP/端口错误、防火墙拦截、服务端没启动 | 用电脑访问健康检查接口 |
| Not Check Time | 没有配置时间段,或当前时间不在时间段内 | Qt 新增时间段并保存,检查 DS1302/NTP |
| Already Signed | 当前时段已经签过 | 换时间段或清空记录 |
| Low Confidence | K210 比对分数偏低 | 调整光线、重新录入人脸 |
| Qt 看不到记录 | STM32 未同步成功或服务端地址不一致 | 看服务端日志和 Qt 服务端地址 |
16. 修改配置时要同步修改哪里
| 你修改了什么 | 需要同步修改 |
|---|---|
| 服务端 IP | User/main.c、k210/main.py、Qt 配置中心 |
| API Token | 服务端环境变量或代码、User/main.c、k210/main.py、Qt 环境变量 |
| AES Key/IV | Hardware/Crypto.c、server/server_encrypted.cpp、QT/src/CryptoUtils.cpp |
| 班级编号 | 每块 STM32 对应修改 CLASS_ID |
| WiFi | User/main.c 和 k210/main.py |