用 ESP32 模拟 Wiegand 刷卡器:开发门禁系统必备的小工具
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
- 前言
- 应用场景举个例子
- 项目目标
- 完整的功能流程长这样:
- 场景实战:用 ESP32 模拟“刷卡器”发卡号
- 举个例子:
- 连接示意:
- 代码解读:一步步拆给你看
- 应用主程序:发数据这一步怎么写的?
- 底层逻辑:两个定时器配合完成整个数据发送流程
- 小结
- 实战建议和注意事项
- 可以扩展成什么?
- 写在最后
前言
在做门禁相关项目的时候,Wiegand 协议是一种特别常见的数据通信方式。你如果用过门禁卡,大概率你刷卡那一瞬间,读卡器和控制器之间就是靠 Wiegand 协议在通信。
这次我们用 ESP32 实现一个简易的“Wiegand 模拟发卡器”,也可以叫“刷卡模拟器”。通过这套代码,你可以模拟发一段刷卡数据,验证接收端的反应。对于做硬件联调或者自动化测试特别有用。
应用场景举个例子
假设你现在在开发一个刷卡开门的控制器,但还没有卡、没有读卡器,那你怎么测试这个控制器有没有响应“刷卡”?
答案就是:用 ESP32 模拟一个“刷卡器”发出刷卡数据(比如模拟卡号),假装有人刷了卡,然后你观察控制器的反应(比如是否开门、是否打日志),就可以验证系统了。
项目目标
我们要用 ESP32,基于两个 GPIO 引脚,按照 Wiegand 协议的格式,发一段“卡号数据”,这个数据是我们自己设定的,发送方式用两个定时器(脉冲定时器和间隔定时器)配合完成。
完整的功能流程长这样:
- 配置两个 GPIO(模拟 Wiegand 的 DATA0 和 DATA1)
- 初始化定时器,精确控制发每一位 bit 的节奏
- 按照协议格式,从高位到低位依次发出数据
- 发完一段数据后,恢复空闲状态
场景实战:用 ESP32 模拟“刷卡器”发卡号
举个例子:
我们设定一个卡号:0x5a5a5a5a
,用 Wiegand 的 26 位格式发送。你连上逻辑分析仪,就可以看到数据一个 bit 一个 bit 地从 GPIO0 / GPIO2 交替输出了,像极了真实刷卡时的波形。
连接示意:
ESP32 GPIO0 ——> 接收设备的 DATA0
ESP32 GPIO2 ——> 接收设备的 DATA1
GND ——> 接收设备的 GND
代码解读:一步步拆给你看
下面我们分段解读一下这套代码,看看背后到底是怎么实现的。
应用主程序:发数据这一步怎么写的?
#define DATA_PIN0_GPIO GPIO_NUM_0
#define DATA_PIN1_GPIO GPIO_NUM_2
uint64_t wiegand_data = 0x5a5a5a5a;
我们定义了两个 GPIO,一个负责发“0”,一个负责发“1”。
wiegand_io_config_t wiegand_io_config = {.data_pin0 = DATA_PIN0_GPIO,.data_pin1 = DATA_PIN1_GPIO,.pulse_width_us = 50, // 每个脉冲的低电平持续 50us.interval_width_us = 1000, // 每个位之间的间隔是 1ms
};
这是我们整个模拟器的节奏:50 微秒的“拉低”,1 毫秒一个节奏位。
ESP_ERROR_CHECK(wiegand_new_io(&wiegand_io_config, &wiegand_io_handle));
ESP_ERROR_CHECK(wiegand_io_send(wiegand_io_handle, &wiegand_data, 26));
第一行是初始化接口,第二行开始“发数据”。注意这里只发了 26 位(Wiegand 26 是最常见的格式)。
底层逻辑:两个定时器配合完成整个数据发送流程
间隔定时器的任务是啥?
→ 每隔一段时间(1ms)发送下一位。
脉冲定时器的任务是啥?
→ 控制当前 bit 拉低多久(比如 50 微秒),然后立刻拉高,形成脉冲。
if (*wiegand_io->current_data & wiegand_io->bit_mask) {gpio_set_level(wiegand_io->data_pin1, 0); // 当前位是 1,拉低 DATA1
} else {gpio_set_level(wiegand_io->data_pin0, 0); // 当前位是 0,拉低 DATA0
}
看清楚了吧?真正决定发哪一根线的,是 current_data
当前位的值。
if (!(wiegand_io->bit_mask >>= 1)) {xSemaphoreGiveFromISR(wiegand_io->sem, &task_woken); // 发完所有 bit
}
当所有 bit 都发完,就释放信号量告诉主程序结束了。
小结
模块名 | 干了什么事 |
---|---|
wiegand_new_io | 初始化 GPIO 和定时器 |
wiegand_io_send | 设置要发的数据和 bit 数,启动定时器 |
interval_timer_cb | 控制每一位的发送节奏,判断发 0 还是 1 |
pulse_timer_cb | 控制信号拉低多久后再拉高,形成 Wiegand 脉冲 |
实战建议和注意事项
- 信号默认要拉高,因为 Wiegand 是低电平脉冲,所以空闲状态必须是高电平。
- Wiegand 的时间非常敏感,建议用定时器控制节奏,不要自己
vTaskDelay
那种不精确的方法。 - 接收端要注意防抖,不然可能误读。
- 数据位数必须匹配,Wiegand 有 26、34、37、44 位等格式,收发两端必须一致。
可以扩展成什么?
你可以把这套“刷卡模拟器”继续扩展,做出更多有趣的玩法:
- 加个按键或触摸屏,刷不同的卡号
- 加个蓝牙/WiFi,远程控制刷卡
- 联动门禁控制器做自动化测试(比如连跑 100 次,测系统稳定性)
写在最后
这个项目看起来小,但它真的很适合练手,特别是对初学者来说:
你可以熟悉 GPIO、定时器、信号节奏控制这些关键技能,还能模拟真实场景做系统测试。