如何低成本DIY一把智能门锁
基于DX-BT121模块的智能门锁设计
主控芯片:STM32F103C8T6
指纹模块:ZW101半导体指纹模组
蓝牙模块:大夏龙雀DX-BT121
控制终端:微信小程序
机械结构:3D打印外壳 + 全金属锁芯
一、前言
在上一篇《基于大夏龙雀DX-BT04-E蓝牙模块的智能安防设备设计》中,我们分享了蓝牙+指纹双模控制的方案框架。本文是该方案的实际落地应用——一台完整的智能门锁。

与方案阶段不同的是,本次项目做了三项关键升级:
- 指纹模块升级为ZW101——支持PS_AutoEnroll一站式注册和PS_AutoIdentify自动验证,开发更简洁
- 蓝牙模块升级为DX-BT121——BLE 5.2协议+2.4G私有协议双模,通信距离提升至200m,且2.4G模式为后续智能家居中枢预留
- 控制端升级为微信小程序——通过BLE直连BT121,无需独立APP,用户扫码即用
同时,门锁机械结构采用3D打印外壳+全金属锁芯的混合设计,兼顾外观定制自由度与物理安全性。
二、系统总体设计
系统总体架构图

系统以STM32F103C8T6为核心,通过两路独立UART分别连接指纹模块和蓝牙模块:
| 子系统 | 模块 | 接口 | 功能 |
|---|---|---|---|
| 指纹认证 | ZW101 | USART1 (57600bps) | 指纹录入/删除/验证/清空 |
| 蓝牙通信 | DX-BT121 | USART2 (9600bps) | BLE透传(微信小程序) + 2.4G扩展 |
| 状态显示 | LCD SPI屏 | SPI | 实时显示门锁状态 |
| 锁舌驱动 | SG90舵机 | TIM3_CH4 (PB1) | PWM控制开门/关门 |
| 触摸唤醒 | 指纹传感器触摸 | PB0 (外部中断) | 低功耗唤醒 |
| 状态指示 | LED | PB10(红)/PB11(绿) | 成功/错误指示 |
三、硬件设计
3.1 ZW101指纹模块

ZW101是一款半导体指纹模组,采用标准UART通信,支持PS_AutoEnroll一站式注册和PS_AutoIdentify自动验证指令,大幅简化开发流程。
通信协议:
| 字段 | 包头 | 设备地址 | 包标识 | 包长度 | 指令/数据 | 校验和 |
|---|---|---|---|---|---|---|
| 字节数 | 2B | 4B | 1B | 2B | N B | 2B |
| 内容 | 0xEF01 | 0xFFFFFFFF | 01/02/07/08 | N | 指令码+参数 | sum |
核心指令集:
| 指令 | 代码 | 功能 | 说明 |
|---|---|---|---|
| PS_AutoEnroll | 31H | 自动注册模板 | 一站式录入,含采图/特征/合并/存储/查重 |
| PS_AutoIdentify | 32H | 自动验证指纹 | 一站式验证,含采图/特征/搜索/返回ID |
| PS_DeletChar | 0cH | 删除指纹 | 删除指定ID开始的N个模板 |
| PS_Empty | 0dH | 清空指纹库 | 删除所有指纹模板 |
| PS_Cancel | 30H | 取消操作 | 终止正在执行的自动注册/验证 |
| PS_ReadSysPara | 0fH | 读取系统参数 | 获取指纹库容量/模板大小/注册次数等 |
| PS_Sleep | 33H | 休眠 | 进入低功耗模式 |
| PS_HandShake | 35H | 握手 | 检测模组是否正常 |
ZW101上电初始化后会发送0x55握手信号,主控可通过此信号确认模组就绪。
3.2 DX-BT121蓝牙模块

DX-BT121支持蓝牙5.2协议和专有2.4G协议,三种工作模式通过AT+MODE指令设置:
| 模式 | 值 | 蓝牙 | 2.4G | 适用场景 |
|---|---|---|---|---|
| BLE模式 | 0 | 开启 | 关闭 | 微信小程序控制 |
| 2.4G模式 | 1 | 关闭 | 开启 | 智能家居中枢通信(后续进行开发) |
| BLE+2.4G模式 | 2 | 开启 | 开启 | 双通道并行 |
模式切换机制:

- BLE模式:未连接时为命令模式,连接后自动进入透传模式
- 2.4G/BLE+2.4G模式:默认透传,发送
AT+OPEN1进入命令模式,AT+OPEN0退出
引脚连接:
| BT121引脚 | 功能 | STM32引脚 |
|---|---|---|
| Pin 1 (UART-TX) | 串口输出 | PA3 (USART2_RX) |
| Pin 2 (UART-RX) | 串口输入 | PA2 (USART2_TX) |
| Pin 24 (WORK) | 工作状态 | PA4 (GPIO输入) |
| Pin 25 (AUX) | 射频状态 | PA5 (GPIO输入) |
| Pin 12 (VCC) | 电源 | 3.3V |
3.3 舵机驱动

使用SG90舵机驱动锁舌伸缩,通过TIM3_CH4 (PB1)输出PWM信号:
- 0°对应关门 -- 锁舌伸出
- 180°对应开门 -- 锁舌缩回
四、机械结构设计
门锁机械结构剖面示意图

机械结构设计图

门锁机械结构采用分层混合设计:
4.1 外层:3D打印外壳

- 材料:PLA或PETG,壁厚3mm以上
- 作用:包裹电子元件,提供外观造型和安装结构
- 设计自由度:可根据门体厚度、安装方式自由定制外形
- 非承力部件:外壳不承担防撬功能,仅起保护和美观作用
4.2 内层:全金属锁芯

- 材料:304不锈钢,关键部位厚度≥2mm
- 作用:锁舌、锁体导向槽、固定安装板均为金属,保证物理抗破坏能力
- 安全设计:锁舌行程、防撬卡扣等核心结构全部金属件,电子驱动仅替代旋钮/把手功能
4.3 设计原则

五、指纹管理功能设计
5.1 指纹录入流程
指纹录入流程图

指纹录入采用PS_AutoEnroll一站式指令,由小程序触发,整个流程在ZW101模块内部自动完成:
// 指纹录入指令包构造
// PS_AutoEnroll: 指令码31H, 参数: ID号 + 录入次数 + 控制参数
void ZW101_AutoEnroll(uint16_t finger_id, uint8_t count)
{
uint16_t checksum = 0;
uint8_t cmd[17] = {
0xEF, 0x01, // 包头
0xFF, 0xFF, 0xFF, 0xFF, // 设备地址
0x01, // 包标识
0x00, 0x08, // 包长度
0x31, // 指令码
(finger_id >> 8) & 0xFF, // ID号高字节
finger_id & 0xFF, // ID号低字节
count, // 录入次数
0x00, 0x02, // 控制参数
0x00, 0x00 // 校验和
};
// 计算校验和: 从包标识到校验前所有字节之和
for(int i = 6; i < 15; i++) {
checksum += cmd[i];
}
cmd[15] = (checksum >> 8) & 0xFF;
cmd[16] = checksum & 0xFF;
// 通过USART1发送
ZW101_SendData(cmd, 17);
}
录入过程解析:
- 小程序发送
ENROLL:3:8266\r\n(录入3号指纹,密码8266) - MCU校验密码后调用
ZW101_AutoEnroll(3, 3)(3次录入) - ZW101自动执行:采图 → 生成特征 → 等待手指离开 → 重复N次 → 合并模板 → 查重 → 存储
- 每个关键步骤ZW101返回进度应答
- MCU将进度实时透传至小程序,用户看到"请再次按压指纹"等提示
- 最终返回
OK:ENROLL_SUCCESS\r\n或ERR:ENROLL_FAILED\r\n
5.2 指纹验证流程
指纹验证采用PS_AutoIdentify指令,由触摸唤醒触发,完全本地执行:
// PS_AutoIdentify: 指令码32H, 参数: 分数等级 + ID号 + 控制参数
// ID=0xFFFF表示1:N搜索
void ZW101_AutoIdentify(void)
{
uint16_t checksum = 0;
uint8_t cmd[17] = {
0xEF, 0x01,
0xFF, 0xFF, 0xFF, 0xFF,
0x01,
0x00, 0x08,
0x32, // 指令码
0x03, // 分数等级(Level 3)
0xFF, 0xFF, // ID=0xFFFF → 1:N搜索
0x00, 0x00, // 控制参数
0x00, 0x00 // 校验和
};
for(int i = 6; i < 15; i++) checksum += cmd[i];
cmd[15] = (checksum >> 8) & 0xFF;
cmd[16] = checksum & 0xFF;
ZW101_SendData(cmd, 17);
}
验证成功后,ZW101返回匹配的指纹ID和得分,MCU控制舵机开门。
5.3 指纹删除
// PS_DeletChar: 指令码0cH, 参数: PageID + 删除数量N
void ZW101_DeleteFinger(uint16_t page_id, uint16_t count)
{
uint16_t checksum = 0;
uint8_t cmd[16] = {
0xEF, 0x01,
0xFF, 0xFF, 0xFF, 0xFF,
0x01,
0x00, 0x07,
0x0C, // 指令码
(page_id >> 8) & 0xFF, // 起始ID高字节
page_id & 0xFF, // 起始ID低字节
(count >> 8) & 0xFF, // 删除数量高字节
count & 0xFF, // 删除数量低字节
0x00, 0x00 // 校验和
};
for(int i = 6; i < 14; i++) checksum += cmd[i];
cmd[14] = (checksum >> 8) & 0xFF;
cmd[15] = checksum & 0xFF;
ZW101_SendData(cmd, 16);
}
小程序发送 DEL:3:8266\r\n 删除3号指纹,或 DEL:0:8266\r\n 删除全部(count=0表示全部删除)。
5.4 清空指纹库
// PS_Empty: 指令码0dH, 无参数
void ZW101_EmptyAll(void)
{
uint8_t cmd[12] = {
0xEF, 0x01,
0xFF, 0xFF, 0xFF, 0xFF,
0x01,
0x00, 0x03,
0x0D, // 指令码
0x00, 0x11 // 校验和
};
ZW101_SendData(cmd, 12);
}
六、微信小程序蓝牙控制
微信小程序控制流程图

6.1 BLE通信架构
微信小程序通过蓝牙BLE直接连接BT121模块,无需独立APP。连接后BT121自动进入透传模式,小程序发送的指令通过BLE透传至MCU的USART2。

6.2 指令协议设计
目前,使用AI辅助开发软硬件已经逐步形成规模,我们现在本次的智能门锁项目中也使用AI进行小程序外观的美化,使之更加美观和具备科技感,电量测量方面我这次没有在本文章中写具体的实现方法,大家可以参考ADC测量电池电压法进行电量的估算(相关电路思路已经非常成熟,大家可以着重参考在软件设置采样频率与功耗之间平衡的方法)。

所有控制指令需携带密码认证,格式为 CMD:PARAM1:PARAM2:PASSWORD\r\n:
| 指令 | 格式 | 功能 | 需密码 |
|---|---|---|---|
| 录入指纹 | ENROLL:<ID>:<PASS> |
录入指定ID指纹 | 是 |
| 删除指纹 | DEL:<ID>:<PASS> |
删除指定ID指纹(ID=0删除全部) | 是 |
| 远程开门 | OPEN:<PASS> |
蓝牙远程开门 | 是 |
| 远程关门 | CLOSE:<PASS> |
蓝牙远程关门 | 是 |
| 查询状态 | STATUS |
查询门锁状态+指纹数量 | 否 |
| 查询信息 | INFO |
查询设备信息 | 否 |
| 清空指纹 | CLEAR:<PASS> |
清空所有指纹(管理员) | 是 |
MCU响应格式:
| 响应 | 说明 |
|---|---|
OK:ENROLL_SUCCESS\r\n |
指纹录入成功 |
OK:ENROLL_PROGRESS:<n>\r\n |
录入进度 |
OK:DELETE_SUCCESS\r\n |
删除成功 |
OK:UNLOCK\r\n |
开门成功 |
OK:LOCK\r\n |
关门成功 |
OK:STATUS=LOCKED,COUNT=<n>\r\n |
状态:已锁,指纹数n |
OK:STATUS=UNLOCKED,COUNT=<n>\r\n |
状态:已开,指纹数n |
OK:CLEAR_SUCCESS\r\n |
清空成功 |
ERR:WRONG_PASSWORD\r\n |
密码错误 |
ERR:FP_FULL\r\n |
指纹库已满 |
ERR:FP_EXIST\r\n |
指纹已存在 |
6.3 小程序端核心逻辑
微信小程序端使用 wx.createBLEConnection 连接BT121,通过特征值写入发送指令:
// 小程序发送指纹录入指令
function enrollFinger(fingerId, password) {
const cmd = `ENROLL:${fingerId}:${password}\r\n`;
const buffer = stringToBuffer(cmd);
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: SERVICE_UUID, // 0xFFE0
characteristicId: WRITE_UUID, // 0xFFE1
value: buffer,
success(res) {
console.log('check successfully');
}
});
}
// 监听BT121返回数据
wx.onBLECharacteristicValueChange(function(res) {
const response = bufferToString(res.value);
if (response.startsWith('OK:ENROLL_PROGRESS')) {
// 更新UI: "请第n次按压指纹"
updateEnrollProgress(response);
} else if (response.startsWith('OK:ENROLL_SUCCESS')) {
wx.showToast({ title: 'input successfully' });
} else if (response.startsWith('ERR:')) {
wx.showToast({ title: 'input fail', icon: 'error' });
}
});
七、2.4G模式智能家居扩展规划
2.4G扩展架构图

7.1 设计思路

BT121的2.4G私有协议模式是本方案的前瞻性设计。当前阶段门锁以BLE模式运行(模式0),与微信小程序通信;2.4G模式为后续构建家庭管理中枢预留接口。
7.2 扩展架构
| 阶段 | 内容 | 状态 |
|---|---|---|
| 阶段一 | 智能门锁(2.4G发送端) | 已完成 |
| 阶段二 | 家庭管理中枢(2.4G接收端) | 规划中 |
| 阶段三 | 多设备联动(灯控/窗帘/传感器) | 规划中 |
未来场景设想:
- 门锁事件上报:门锁开关/指纹验证结果通过2.4G实时上报至中枢
- 语音联动:中枢收到开门事件后,语音播报"欢迎回家",联动开灯
- 安全告警:连续指纹验证失败,中枢推送告警至手机
- 场景模式:指纹识别不同用户ID,中枢执行个性化场景(如孩子回家自动通知家长)
7.3 2.4G通信预留
当前阶段,MCU通过AT指令将BT121设置为BLE模式(AT+MODE0),2.4G功能关闭。未来切换为BLE+2.4G模式(AT+MODE2)后:
- BLE通道:维持微信小程序控制
- 2.4G通道:与家庭中枢通信
// 未来切换为双模模式的预留代码
void BT121_SetDualMode(void)
{
// 进入命令模式
BT_SendString("AT+OPEN1\r\n");
delay_ms(100);
// 设置为BLE+2.4G模式
BT_SendString("AT+MODE2\r\n");
delay_ms(100);
// 退出命令模式,恢复透传
BT_SendString("AT+OPEN0\r\n");
}
八、核心代码实现
8.1 ZW101指纹模块驱动
// zw101.h - 核心定义
#define ZW101_UART USART1
#define ZW101_BAUD 57600
#define ZW101_RX_BUF_SIZE 64
// 指纹模块状态
typedef enum {
FP_IDLE = 0,
FP_ENROLLING, // 录入中
FP_IDENTIFYING, // 验证中
FP_DELETING, // 删除中
FP_SUCCESS,
FP_ERROR
} FP_State;
// 确认码定义
#define FP_OK 0x00
#define FP_NO_FINGER 0x02
#define FP_IMG_FAIL 0x03
#define FP_NOT_MATCH 0x08
#define FP_NOT_FOUND 0x09
#define FP_ID_OUT_RANGE 0x0B
#define FP_DB_FULL 0x1F
#define FP_ALREADY_EXIST 0x27
#define FP_TIMEOUT 0x26
#define FP_DB_EMPTY 0x24
// 核心函数
void ZW101_Init(void);
void ZW101_AutoEnroll(uint16_t id, uint8_t count);
void ZW101_AutoIdentify(void);
void ZW101_DeleteFinger(uint16_t id, uint16_t count);
void ZW101_EmptyAll(void);
void ZW101_Cancel(void);
void ZW101_Sleep(void);
uint8_t ZW101_ParseResponse(uint16_t* match_id, uint16_t* score);
8.2 双模控制状态机
// 主循环中的双模控制逻辑
void Process_MainLoop(void)
{
switch(sys_mode) {
case MODE_IDLE:
// 优先检查指纹触摸唤醒
if(GPIO_ReadInputDataBit(WAKE_PORT, WAKE_PIN) == Bit_SET) {
delay_ms(20); // 防抖
if(GPIO_ReadInputDataBit(WAKE_PORT, WAKE_PIN) == Bit_SET) {
sys_mode = MODE_FP_IDENTIFY;
ZW101_AutoIdentify();
Display_Status("Scanning Finger...");
}
}
// 检查蓝牙指令
BT_ProcessCommand();
if(bt_result == BT_RESULT_UNLOCK) {
sys_mode = MODE_BT_UNLOCK;
Execute_Unlock("Bluetooth");
// ... 处理蓝牙开门
}
break;
case MODE_FP_IDENTIFY:
// 等待ZW101验证结果
if(ZW101_ResponseReady()) {
uint16_t id, score;
uint8_t result = ZW101_ParseResponse(&id, &score);
if(result == FP_OK) {
Display_FingerID(id);
Execute_Unlock("Finger");
} else {
Display_Status("Auth Failed");
led_err();
}
sys_mode = MODE_IDLE;
}
break;
case MODE_FP_ENROLL:
// 录入过程由ZW101自动执行
// MCU解析进度应答并透传至小程序
if(ZW101_ResponseReady()) {
ZW101_ForwardProgressToBT(); // 透传进度
if(ZW101_EnrollComplete()) {
sys_mode = MODE_IDLE;
}
}
break;
default:
sys_mode = MODE_IDLE;
break;
}
}
8.3 蓝牙指令解析
// 蓝牙指令解析
BT_CmdType BT_ParseCommand(void)
{
char* str = (char*)bt_rx_buffer;
char cmd[16] = {0}, p1[16] = {0}, pass[16] = {0};
// 解析格式: CMD:PARAM:PASSWORD
int parsed = sscanf(str, "%[^:]:%[^:]:%s", cmd, p1, pass);
if(parsed >= 3) {
// 校验密码
if(strcmp(pass, BT_PASSWORD) != 0) return BT_CMD_WRONG_PASS;
if(strcmp(cmd, "ENROLL") == 0) {
bt_param = atoi(p1); // 指纹ID
return BT_CMD_ENROLL;
}
if(strcmp(cmd, "DEL") == 0) {
bt_param = atoi(p1); // 删除的ID
return BT_CMD_DELETE;
}
if(strcmp(cmd, "OPEN") == 0) return BT_CMD_UNLOCK;
if(strcmp(cmd, "CLOSE") == 0) return BT_CMD_LOCK;
if(strcmp(cmd, "CLEAR") == 0) return BT_CMD_CLEAR;
} else if(parsed >= 1) {
if(strcmp(cmd, "STATUS") == 0) return BT_CMD_QUERY_STATUS;
if(strcmp(cmd, "INFO") == 0) return BT_CMD_QUERY_INFO;
}
return BT_CMD_UNKNOWN;
}
8.4 低功耗管理
// 空闲时进入低功耗模式
void Enter_LowPower(void)
{
// 1. ZW101进入休眠
ZW101_Sleep();
// 2. BT121可设置低功耗模式
AT+PWRM0
// 3. STM32进入Stop模式,由PB0外部中断唤醒
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// 4. 初始化时钟
SystemClock_Config();
ZW101_Init();
}
九、智能门锁功能清单

| 功能 | 触发方式 | 执行模块 | 状态 |
|---|---|---|---|
| 指纹开锁 | 触摸传感器 | ZW101验证 → 舵机开门 | 已实现 |
| 指纹录入 | 小程序发送 | ZW101 AutoEnroll | 已实现 |
| 指纹删除 | 小程序发送 | ZW101 DeletChar | 已实现 |
| 清空指纹 | 小程序发送 | ZW101 Empty | 已实现 |
| 蓝牙无感开门 | 小程序发送 | 舵机控制 | 已实现 |
| 蓝牙无感关门 | 小程序发送 | 舵机控制 | 已实现 |
| 状态查询 | 小程序发送 | 返回门锁状态+指纹数 | 已实现 |
| LCD状态显示 | 自动 | SPI屏 | 已实现 |
| LED指示 | 自动 | 成功绿灯/失败红灯 | 已实现 |
| 低功耗休眠 | 空闲超时 | ZW101 Sleep+STM32 Stop | 已实现 |
| 2.4G中枢通信 | 预留 | BT121模式切换 | 规划中 |
| 开锁记录上报 | 2.4G | 上报至中枢 | 规划中 |
| 多用户场景联动 | 中枢 | ID识别+场景触发 | 规划中 |
十、总结

本项目将前期方案落地为一台完整的智能门锁,我完成了:
-
ZW101一站式指令:PS_AutoEnroll/PS_AutoIdentify将指纹录入和验证的复杂流程封装在模块内部,MCU仅需发送一条指令即可完成全流程,大幅降低开发难度
-
BT121双模式的使用:当前BLE模式连接微信小程序实现远程控制,2.4G模式为未来家庭管理中枢预留接口,一次硬件设计支持两阶段功能演进
-
微信小程序控制:无需独立APP,用户扫码即用,BLE透传模式下指令直达MCU,响应实时
-
3D打印+金属锁芯混合结构:外壳3D打印保证外观定制自由度,内部全金属锁芯确保物理安全性,兼顾了开发原型的灵活性和产品的安全要求
-
完整指纹管理闭环:录入、验证、删除、清空、查重、查状态,覆盖智能门锁全部核心功能
后续我将围绕2.4G模式开发家庭管理中枢,实现门锁与其他智能设备的联动控制,打造完整的低成本智能家居安防生态。
更多推荐


所有评论(0)