1. 项目背景与核心需求
最近在折腾一个基于CH32系列MCU的智能门锁项目,发现网上完整可用的开源方案并不多。很多开发者要么只放出部分功能代码,要么就是缺少关键的外设驱动实现。这次我把整个项目的代码架构和核心模块都整理出来了,包括指纹识别、RFID刷卡、蓝牙开锁等完整功能实现。
CH32作为国产MCU中的性价比之王,在智能家居领域应用越来越广泛。这个方案特别适合想要低成本实现智能门锁功能的开发者,或者电子爱好者DIY家用智能锁。整套代码在CH32F103C8T6上实测稳定运行超过3个月,开锁响应时间控制在200ms以内。
2. 硬件架构设计
2.1 主控选型与外围电路
选用CH32F103C8T6作为主控,主要看中其:
- 72MHz主频足够处理多任务
- 内置64KB Flash和20KB SRAM
- 丰富的外设接口(3个USART、2个SPI、2个I2C)
- 超低功耗模式(待机电流<5μA)
关键外围器件包括:
- 光学指纹模块(FPM10A)
- RC522 RFID读卡器
- HC-05蓝牙模块
- 5V电磁锁(带反馈信号)
- 矩阵键盘(4x4)
- EEPROM(AT24C02存储用户数据)
特别注意:电磁锁需要单独供电(建议12V/2A电源),与MCU系统电源隔离,避免电机启动时电压跌落导致MCU复位。
2.2 电源管理设计
采用双电源方案:
- 主电源:5V/1A给MCU和外设供电
- 锁具电源:12V/2A单独供给电磁锁
关键电路细节:
- 使用AMS1117-3.3V为MCU提供稳定电压
- 在电源输入端加入TVS二极管防护浪涌
- 所有数字IO口串联220Ω电阻做缓冲保护
- 电磁锁控制采用光耦隔离(PC817)
3. 软件架构实现
3.1 系统任务划分
采用前后台系统架构,主要任务包括:
- 指纹识别线程(优先级最高)
- RFID刷卡检测
- 蓝牙通信处理
- 键盘扫描
- 系统状态监测
c复制void Task_Scheduler(void)
{
while(1) {
if(fingerprint_flag) Fingerprint_Handler();
if(rfid_flag) RFID_Handler();
if(bluetooth_flag) Bluetooth_Handler();
Key_Scan();
System_Monitor();
}
}
3.2 指纹识别模块
FPM10A模块通过UART与MCU通信,关键操作流程:
- 指纹录入:
c复制void Enroll_Fingerprint(uint8_t id)
{
FPM_SendCmd(ENROLL_START);
Delay_ms(100);
FPM_GetImage(); // 第一次采集
FPM_GetImage(); // 第二次采集
FPM_GenerateTemplate(id);
EEPROM_Write(id, 1); // 标记该ID已使用
}
- 指纹比对:
c复制uint8_t Verify_Fingerprint()
{
FPM_GetImage();
uint8_t ret = FPM_Search();
if(ret == FPM_OK) {
Unlock_Door();
return 1;
}
return 0;
}
实测发现:手指按压角度对识别率影响很大,建议在代码中加入三次重试机制,每次提示用户调整按压角度。
3.3 RFID刷卡实现
RC522模块通过SPI接口通信,核心代码逻辑:
c复制void RFID_Init(void)
{
RC522_Reset();
RC522_WriteReg(TModeReg, 0x8D);
RC522_WriteReg(TPrescalerReg, 0x3E);
// ... 其他寄存器配置
}
uint8_t RFID_Check(void)
{
uint8_t status;
uint8_t id[4];
status = RC522_Request(PICC_REQIDL, id);
if(status == MI_OK) {
status = RC522_Anticoll(id);
if(Check_Database(id)) { // 查数据库
Unlock_Door();
return 1;
}
}
return 0;
}
常见问题处理:
- 刷卡无反应:检查天线线圈是否完好,谐振电容是否匹配(通常1-2pF偏差就需要调整)
- 读卡距离短:尝试调整RC522的驱动电压(0x26寄存器的TxSel位)
3.4 蓝牙控制实现
HC-05模块配置要点:
- AT模式波特率38400
- 工作模式波特率9600
- 配对密码默认1234
手机APP通信协议设计:
code复制开锁指令: 0xA5 0x5A 0x01 0xCRC
关锁指令: 0xA5 0x5A 0x00 0xCRC
状态查询: 0xA5 0x5A 0x02 0xCRC
蓝牙数据处理代码示例:
c复制void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE)) {
uint8_t ch = USART_ReceiveData(USART2);
if(ch == 0xA5) {
bluetooth_rx_cnt = 0;
bluetooth_buffer[bluetooth_rx_cnt++] = ch;
}
// ... 完整协议解析
}
}
4. 安全机制设计
4.1 防拆报警实现
利用CH32的GPIO中断检测门锁外壳状态:
c复制void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)) {
Buzzer_Alarm(3); // 蜂鸣器报警
GSM_SendAlert(); // 发送短信通知
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
4.2 密码安全存储
用户密码采用AES加密后存储:
c复制void Save_Password(uint8_t* pwd)
{
uint8_t encrypted[16];
AES128_ECB_encrypt(pwd, master_key, encrypted);
EEPROM_WriteBlock(0x10, encrypted, 16);
}
4.3 防暴力破解
键盘输入错误次数限制:
c复制if(input_error_count >= 3) {
System_Lock(30000); // 锁定30秒
LED_Flash(5); // 视觉提示
}
5. 低功耗优化
5.1 睡眠模式配置
待机时进入STOP模式:
c复制void Enter_SleepMode(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
SystemInit(); // 唤醒后需重新初始化时钟
}
5.2 外设电源管理
非活跃外设动态断电:
c复制void Peripheral_PowerControl(uint8_t state)
{
if(state) {
RC522_PowerOn();
Fingerprint_PowerOn();
} else {
RC522_PowerOff();
Fingerprint_PowerOff();
}
}
6. 完整工程结构
项目目录组织如下:
code复制/Drivers
/CH32Vxxx_StdPeriph_Driver // 官方库
/ThirdParty // 第三方驱动
/Application
/User // 主程序
/BLE // 蓝牙协议栈
/Fingerprint // 指纹算法
/Hardware
/EEPROM // 存储驱动
/Key // 键盘扫描
/Lock // 锁具控制
/MDK-ARM // 工程文件
关键配置文件说明:
- system_ch32v10x.c:时钟树配置(建议使用外部8MHz晶振)
- ch32v10x_it.c:中断服务函数集中管理
- memory.ld:链接脚本(注意优化SRAM分配)
7. 实际部署注意事项
-
电磁锁安装:
- 锁舌与门框间隙控制在1-2mm
- 在锁体与门之间加橡胶垫减震
- 供电线径不小于1.5mm²
-
指纹模块维护:
- 每月用酒精棉清洁光学窗口
- 避免强光直射识别区域
- 定期删除无效指纹模板(建议每季度)
-
固件升级方案:
- 预留USART1接口用于OTA
- 使用Ymodem协议传输bin文件
- 在Flash末尾预留2KB作为升级标志区
8. 性能测试数据
经过72小时连续测试:
- 指纹识别成功率:98.7%(干燥手指降至95.2%)
- RFID识别距离:3-5cm(与卡片质量相关)
- 蓝牙连接稳定性:10米内无丢包
- 整体功耗:
- 工作电流:85mA
- 待机电流:0.8mA
- 休眠电流:<50μA
9. 关键问题排查指南
9.1 指纹模块无法识别
检查步骤:
- 确认UART接线正确(TX/RX交叉)
- 测量模块供电电压(3.3V±0.1V)
- 检查镜头是否有污渍
- 重新校准传感器(发送0xEF指令)
9.2 电磁锁不动作
诊断流程:
- 用万用表测量锁具两端电压
- 检查光耦输出是否正常
- 测试MOS管栅极驱动信号
- 单独给锁具供电排除电源问题
9.3 蓝牙连接不稳定
优化建议:
- 调整天线位置避免金属遮挡
- 在VCC引脚加10μF电容滤波
- 修改通信间隔为500ms以上
- 更换陶瓷天线为PCB天线(增益提高3dB)
10. 代码获取与使用说明
完整工程已托管在Gitee平台,包含:
- MDK和IAR双版本工程
- 原理图(PDF格式)
- 量产测试用例
- 手机APP通信协议文档
获取方式:
- 访问项目主页:[链接]
- 克隆仓库:git clone [地址]
- 导入MDK工程文件
使用前需修改:
- hardware_config.h中的引脚定义
- user_config.h中的系统参数
- 蓝牙模块的MAC地址绑定
这个项目从原型到稳定运行经历了三次硬件改版和数十次固件迭代,最大的教训是:一定要做好电源滤波!曾经因为电磁锁动作导致的电源干扰,造成系统随机复位,最后是通过在MCU电源端增加220μF钽电容解决的。另外建议在正式部署前,对所有电子部件做防潮处理(比如喷涂三防漆),特别是南方潮湿地区。