ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EM4095 + STM32F103 低频RFID读卡方案:从曼彻斯特解码到门禁应用

EM4095 + STM32F103 低频RFID读卡方案:从曼彻斯特解码到门禁应用 简介这是一份基于EM4095芯片与STM32F103的125kHz RFID阅读器项目资料适合嵌入式入门者或物联网开发者学习低频RFID读写方案。资源围绕RFID读写器设计展开包含原理图GIF格式与硬件实拍图片JPG以及ATtiny85/ATtiny13的固件源码与hex烧录文件还有工程文件cproj/c/atsln和说明文档txt可帮助读者快速理解125kHz射频识别系统从硬件搭建、天线匹配到固件解析的完整流程。压缩包共12个文件大小仅374KB内容紧凑但覆盖了读写器核心模块。目前已有903人学习适合需要快速上手EM4095与STM32F103协作开发、或参考低功耗RFID项目框架的开发者。通过阅读原理图和源代码可掌握EPC Class 1协议处理、中断响应及数据解析等关键技能是一份兼具参考价值与实操性的入门资料。1. 为什么还在折腾 125kHz RFIDEM4095 STM32F103 是套可复现的读卡方案门禁卡掉了手头只剩 125kHz 低频卡与其买成品读卡器不如用压缩包里这套现成的 EM4095 方案。项目里包含原理图、ATtiny85/ATtiny13 固件和实测图片不是只给个 PDF 让人“看图想象”。它把从天线谐振、EM4095 解调到曼彻斯特解码、串口输出整条链路都打通了适合做门禁、动物芯片读取、资产盘点等场景。对想理解低频 RFID 时序的嵌入式工程师来说这也是一个能动手复现的样板。下面按链路原理、硬件搭建、固件解码、调试扩展的顺序拆开讲。2. 125kHz RFID 链路与 EM4095 工作方式从线圈耦合到曼彻斯特码2.1 低频电磁耦合125kHz 为什么还没被淘汰125kHz 属于 LF 频段读写器与标签之间通过线圈耦合磁场交换能量。标签进入读写器天线产生的交变磁场后内部 LC 谐振回路从磁场取电再通过改变负载电阻来调制反射回来的信号这个过程叫负载调制。相比 13.56MHz 的高频 RFID低频信号对水、金属等介质没那么敏感读取距离虽然近但稳定性好所以门禁、门锁、动物电子标识到今天还在大量使用。这个项目里的 EM4095 就是一颗专门的 125kHz RFID 读写前端芯片它承担了载波产生、天线驱动、信号解调和比较输出的工作。后级单片机只需要读取 DATA 引脚上的数据流再按 EM4100 或兼容标签的帧格式解出 ID 即可。因此理解整条链路的关键不是“读卡”而是把载波、谐振、解调、编码四个环节串起来。如果改成用分立元件搭天线驱动和包络检波电路会复杂得多而且比较器门限难调。EM4095 的优势在于把发射桥、接收放大器和比较器全部集成开发者只需要关心天线谐振和输出时序这也是这套原理图能压到几十行元件的原因。2.2 EM4095 数据通路与比较器配置EM4095 的内部可以简化成几个模块天线差分驱动器、接收放大器、带比较器的解调输出。它通过 ANT1 和 ANT2 驱动外部 LC 谐振回路同时在 DEMOD_IN 上拾取天线端被标签负载调制后的信号经过放大后送进比较器。比较器的跳变沿就是标签数据流。比较器的参考电压可以通过 VREF 引脚外接电阻分压设置参考电压调得越高抗干扰越好但小信号可能被判丢调得越低读取距离变远但容易误触发。常见做法是设置在两倍信号幅度的中间位置实际要用示波器看 DATA 波形。下面这张引脚表是后续接线的基础。引脚名方向功能典型接法VCC/GNDP芯片供电3.3V 或 5V就近 100nF 去耦ANT1 / ANT2O驱动天线接 LC 谐振回路两端DEMOD_INI解调输入从天线上取交流信号隔直后接入VREFI比较器参考外接电阻分压设置灵敏度DATAO解调后数字输出接 MCU 的 GPIO或经串口转接RDY/CLKO时钟/状态输出接 MCU 外部时钟输入也可悬空注意EM4095 的 DATA 输出是数字电平但它的时序不是 UART而是和标签编码一致的曼彻斯特流。如果跳过 ATtiny 直接把 DATA 接 STM32F103就不能用串口接收必须用定时器捕获或 GPIO 中断去测量脉冲宽度。2.3 EM4100 帧格式与曼彻斯特解码基础压缩包里读取的标签大概率是 EM4100 兼容卡。EM4100 数据区固定 64 bit其中前 9 bit 是引导头全部是 1用来让读写器同步随后是 10 组 4 bit 数据每组后面带 1 bit 行偶校验最后还有 4 bit 列校验和 1 bit 结束位。整帧长度 64 bit实际用户 ID 落在中间的 10 组 4 bit 数据里共 40 bit。曼彻斯特编码的规则是每个 bit 周期内必定发生一次电平跳变跳变方向表示 0 或 1从低到高表示 1从高到低表示 0。拿 125kHz 载波做基准EM4100 内部把 64 个载波周期编码成一个数据位所以 bit 率大约是 1953 bps半位脉宽约 256us。这个数字后面写定时器参数时直接用到。可以用一段 Python 验证曼彻斯特转换逻辑方便在看 DATA 波形时对照。def manchester_to_bits(pairs): bits [] for level_a, level_b in pairs: # 每个 bit 周期内取两个采样中心跳变决定 bit 值 if level_a 0 and level_b 1: bits.append(1) elif level_a 1 and level_b 0: bits.append(0) else: raise ValueError(invalid manchester: no mid-bit transition) return bits这里pairs是每个 bit 周期内前后两个半周期的电平采样。以中心跳变为准前半周期为 0、后半为 1判定为 bit 1反之判定为 bit 0。波形采集时最好在 bit 周期的 1/4 和 3/4 处采样避开边沿抖动。EM4095 的 DATA 输出极性可能和芯片内部比较器设置有关如果发现实测 ID 是全 0 或全 1只需要把判定条件反过来即可。3. 硬件搭建原理图里的天线匹配、电平适配与 STM32F103 最小系统3.1 原理图快速拆解打开压缩包里的 125kHz_RFID_reader_schem.GIF可以看到典型的结构左侧是天线线圈 L1 谐振电容 C1中间是 EM4095右侧是 ATtiny85 或 ATtiny13 单片机最后是 9600bps 的串口输出。原项目把解码放在 AVR 上ATtiny85 在 8MHz 下跑ATtiny13 在 9.6MHz 下跑两个固件都是 9600bps。对 STM32F103 的处理方式我一般是两种要么让 STM32F103 直接接 EM4095 的 DATA 解码要么让 ATtiny 先解码再把 ID 通过串口发给 STM32F103。前者省一颗芯片后者调试方便。原理图里最重要的几个节点EM4095 的 ANT1、ANT2 到天线C1 电容跨接在两端形成谐振回路VREF 上的分压电阻决定了比较器灵敏度DATA 到单片机的中断脚单片机 UART TX 经过一个三极管或电阻分压输出。注意 ATtiny85 的系统时钟来源如果是内部 RC熔丝位必须和 hex 匹配否则串口波特率会偏。3.2 天线谐振计算与 PCB 布局天线线圈直接决定了读卡距离。125kHz 谐振频率由电感和并联电容共同决定公式是 f 1 / (2π√(LC))。如果绕了一个电感量 1mH 的天线要谐振在 125kHz需要的电容约 1.6nF。我一般直接用 Python 算import math L 1.0e-3 # 天线电感单位 H实测后替换 f 125e3 # 目标频率单位 Hz C 1 / (4 * math.pi**2 * f**2 * L) print(f{C*1e12:.0f} pF) # 输出约 1621 pF参数说明L是实测的线圈电感不是标称值。自制线圈最好用电桥或带电感表的万用表量一下因为匝数、线圈直径和绕线间距都会影响电感量。C是理论谐振电容实际取标称值 1.5nF 或 1.8nF再用一个 10-30pF 可调电容并联做微调。如果读卡距离很短先用示波器看 DATA 输出脉冲包络通常就是谐振偏了。线圈电感理论谐振电容常见取值0.5mH3242 pF3.3nF0.8mH2026 pF2.0nF 微调1.0mH1621 pF1.5nF 微调1.5mH1081 pF1.0nF 微调PCB 布局上天线线圈尽量远离 MCU 的高速走线和晶振不然天线本身的强磁场会窜到数字部分。EM4095 的 VREF 分压电阻应靠近芯片引脚DEMOD_IN 的采样线要短。STM32F103 最小系统板通常把 PA11、PA12 留作 USB如果你不用 USB 也要小心PA11 和 PA12 在 AFIO 复位后可能被配置为 USB 引脚悬空时容易受到干扰表现为 GPIO 读数跳变。最稳妥的办法是改用 PB0/PB1 做 EM4095 的 DATA 输入。注意自制线圈时不要用太细的漆包线125kHz 电流不大但线圈电阻会降低 Q 值读卡距离会明显缩水。3.3 EM4095 与 STM32F103 的连接与电平匹配如果直接用 STM32F103 读取建议按下面这张配置表接线。EM4095 引脚STM32F103 引脚说明VCC3.3VEM4095 可工作在 3.3V避免电平差GNDGND必须共地ANT1天线线圈一端线圈另一端接 ANT2DEMOD_IN天线分压点从天线端隔直后引入VREF10k 到 VCC10k 到 GND参考电压设为 VCC/2 左右DATAPB0配置为浮空输入或上拉输入RDY/CLK悬空不需要时钟输出来解码这里有个容易踩的坑EM4095 的 DATA 输出电平直接跟 VCC 走。如果给 EM4095 供 5VDATA 高电平也是 5V直接接 STM32F103 的 3.3V 引脚就不安全。常见做法是让 EM4095 用 3.3V 供电或者加一个 10k10k 分压电阻再到 PB0。原项目里 ATtiny85 用 5V 供电串口 TX 到 STM32F103 时也要同样处理STM32F103 的串口 RX 如果是 5V 容忍引脚可以直接接普通 GPIO 就需要分压。4. 固件实战STM32F103 解码 EM4095 输出的 EM4100 数据4.1 用定时器输入捕获测量曼彻斯特脉宽EM4095 的 DATA 信号不是串口而是边沿周期约 256us 的曼彻斯特码。STM32F103 上最简单可靠的读法是用定时器输入捕获配置 TIM2 通道 1 检测边沿记录相邻边沿的时间戳主程序再根据时间戳还原数据位。标准外设库 V3.5.0 的初始化代码如下void TIM2_Capture_Init(void) { GPIO_InitTypeDef gpio; TIM_ICInitTypeDef ic; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); gpio.GPIO_Pin GPIO_Pin_0; gpio.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, gpio); ic.TIM_Channel TIM_Channel_1; ic.TIM_ICPolarity TIM_ICPolarity_Rising; // 先用上升沿触发 ic.TIM_ICSelection TIM_ICSelection_DirectTI; ic.TIM_ICPrescaler TIM_ICPSC_DIV1; ic.TIM_ICFilter 0; TIM_ICInit(TIM2, ic); TIM_Cmd(TIM2, ENABLE); TIM_ClearFlag(TIM2, TIM_FLAG_CC1); }这段代码把 TIM2 的通道 1 映射到 PA0。TIM_ICPolarity_Rising表示只在上升沿触发这样第一次捕获边沿的时间戳会被记录在 CC1 寄存器里。这里先不切边沿而是在中断里动态切换捕获边沿原理是每次捕获后把TIM_ICPolarity改成相反极性这样就能交替测量高电平和低电平的脉宽。对 125kHz RFID 来说TIM2 时钟为 72MHz半位 256us 对应约 18432 个计数。4.2 曼彻斯特解码与校验实现捕获到了一串边沿时间之后需要转换成 bit。我一般维护一个状态机先找 9 个连续的 1 作为帧同步头然后每 5 个 bit 一组读出 4 位数据并做偶校验最后校验 4 位列校验。下面是一个可读性优先的解码函数骨架#define HALF_BIT_TICKS 18432 #define TOL 3000 uint8_t last_level; uint32_t last_time; uint8_t process_bit(uint32_t now) { uint32_t delta now - last_time; last_time now; if (delta HALF_BIT_TICKS * 1.5) { return 0xFF; // 异常间隔帧同步丢失 } // 读取当前 DATA 电平判断中心跳变方向 uint8_t level GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); uint8_t bit; if (last_level 0 level 1) bit 1; else if (last_level 1 level 0) bit 0; else return 0xFF; last_level level; return bit; }last_level记录上一次边沿后的电平now是捕获中断里读到的 CCR1 值。delta如果超过半位脉宽的一点五倍说明中间丢了边沿直接丢帧。曼彻斯特的判定关键是中心跳变而不是边沿本身所以这里用last_level和当前电平组成跳变方向上升沿对应 1下降沿对应 0。TOL是允许的时钟偏差ATtiny 内部 RC 振荡器可能有 3%~5% 误差所以容差要放宽一点。完整帧解析要把连续 bit 送入移位寄存器组完 64 bit 后检查并行校验。下面这段代码把边沿解析出的 bit 组装成帧uint8_t frame_bits[64]; void feed_bit(uint8_t bit) { static uint8_t idx 0; if (bit 0xFF) { idx 0; // 异常输入重新同步 return; } frame_bits[idx] bit; if (idx 64) { if (validate_em4100(frame_bits)) { output_id(frame_bits); } idx 0; } }feed_bit每次接收一个有效 bit完全填满 64 位后交给validate_em4100做行校验和列校验校验通过才输出 ID。这样能过滤掉大部分噪声脉冲避免因为一次干扰就输出错误卡号。output_id可以把 40 bit 用户 ID 拆成 10 位十进制打印也可以封装成十六进制数组给上层协议用。4.3 把 ID 输出到串口原项目在 ATtiny 上把解码结果以 9600bps 从串口发出STM32F103 如果作为接收端只需把 PA9/PA10 接到 ATtiny 的 TX/RX。假设你让 STM32F103 直接解码也可以用串口把 10 位 ID 打印出来printf(RFID ID: %02X-%04X-%04X\n, id[0], id[1] 4, id[1] 0xFFFF);这个写法会把 5 字节 ID 拆成三段输出方便和门禁管理里的卡号对应。要注意的是串口波特率。原 hex 是 9600bps如果你的 STM32F103 板子用 8MHz 晶振需要按照外设库里的 RCC 配置把 PLL 倍频调到 72MHz否则串口时间基准就不准。很多人遇到的“rfid数据连接错误什么问题”排查下来一半是波特率不对另一半是 STM32 和读卡器模块没有共地。参数计算值说明载波周期8us125kHz 正弦波周期数据率1953 bpsEM4100 用 64 个载波周期表示 1 bit半位脉宽256us曼彻斯特跳变间隔TIM2 计数1843272MHz 下半个 bit 对应的计数值5. 调试技巧与扩展从读卡到复制、屏蔽验证5.1 常见失败原因排查表现象可能原因处理天线无磁场谐振电容虚焊或 LC 失谐用示波器看 ANT1/ANT2确认存在 125kHz 正弦波读卡距离小于 1cmVREF 参考电压偏高把 VREF 分压调低同时观察 DATA 波形能读但不能稳定输出 IDTOL 容差太小把TOL从 1000 调整到 3000~4000串口输出乱码ATtiny 熔丝位或波特率不匹配检查 ATtiny 运行频率和 PC 端波特率 9600STM32 串口没收到数据没有共地用万用表量读卡器 GND 与 STM32 GND 是否导通逐个说明VREF 调太低会导致空闲时 DATA 毛刺不停调太高会使标签的负载调制信号过不了比较器。最佳状态是拿示波器探头挂在 DATA 输出上人拿着标签慢慢靠近能看到干净、完整的曼彻斯特脉冲包络。那种毛刺多、幅度不齐的波形先不要急着改代码。5.2 STM32F103 下载与启动细节如果你把解码工程移植到 STM32F103 最小系统板上下载阶段最常见的坑是 DAP 下载失败。检查 BOOT0 和 BOOT1 的电平正常从 Flash 启动时 BOOT00、BOOT1 任意如果 BOOT0 被拉高芯片会进入系统存储器或 SRAM 启动SWD 接口可能被占用下载器自然连不上。每次烧录失败先看这两个引脚别急着怀疑 EM4095。另外不同容量 STM32F103 对应不同启动文件中容量用startup_stm32f10x_md.s大容量用startup_stm32f10x_hd.s工程里选错会出现进不了 main 或外设寄存器异常。还有一个隐蔽问题PA11/PA12 在复用 USB 后即使不连接 USB 设备也可能被 USB IP 拉到一个不确定状态导致读到的 GPIO 电平抖动。如果你把 EM4095 的 DATA 接在 PA 口建议换成 PB 口或显式关闭 USB 时钟。5.3 用这个方案试复制与屏蔽最后给一个能直接上手的扩展用读卡器读出 EM4100 兼容卡后如果你想验证“rfid怎么复制”可以买几张 T5577 空白卡把读出的 64 bit 数据用另一个可写低频读写器写入 T5577。注意T5577 的页格式和 EM4100 不完全一样写入时要选对芯片型号和曼彻斯特编码。这套只建议用你自己的测试标签做实验。反过来想测试“rfid芯片怎么屏蔽”可以拿一张铜箔纸或者金属卡套把标签包住。125kHz 是靠磁场耦合铜箔中的涡流会吸收磁场能量屏蔽后读卡器应该立刻读不到。这比靠调整距离更可靠。如果在铜箔上开一条窄缝读卡距离会明显变短但不会完全消失这个现象可以用第 3 章的天线谐振来解释金属体内的涡流等效成一个短路线圈改变了天线侧的谐振阻抗。把这个测试做过一遍你对低频 RFID 的感觉会完全不一样。本文还有配套的精品资源点击获取
返回列表