news 2026/9/6 6:12:21

【STM32 物联网实训】RFID 三连:读卡、写卡、刷卡

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【STM32 物联网实训】RFID 三连:读卡、写卡、刷卡

这一篇记录物联网方向的RFID 系列:读取、写入、刷卡消费充值,同样是学校的智联场景实训箱(STM32L431 + Keil MDK5 + HAL 库)。RFID是物联网感知层里 "身份识别" 的代表技术,门禁、校园卡、食堂刷卡、公交卡全是它。这篇不贴大段代码,重点讲核心逻辑真正踩过的坑


一、实验环境与硬件

项目

配置

主控芯片

STM32L431VCTx(Cortex-M4,主频 80MHz)

RFID 芯片

RC522(NXP MFRC522,13.56MHz,ISO14443A)

卡类型

Mifare 1(S50),默认密码 FF FF FF FF FF FF

RC522 接口

硬件 SPI3(分频 64)+ 复位 PD0 + 片选 PA15

人机交互

TFT LCD + 4 个按键 + 蜂鸣器 + 串口 2(115200)

知识铺垫:M1 卡内部结构 =16 个扇区 × 每扇区 4 块,每块 16 字节。每扇区的块 0/1/2 是数据块,块 3 是控制块(存密码和访问控制位)——块 3 千万别乱写,这是后面重点坑之一。


二、实验一:RFID 读取功能

功能:把卡放到感应区,读出卡类型和 4 字节 UID 卡号,LCD + 串口显示,蜂鸣器提示。

核心代码(读卡四步流程):

static void RC522_Read_ID(void) { uint8_t card_id_arr[4] = {0}; // 卡ID缓存 uint8_t card_type_arr[2] = {0}; // 卡类型缓存 status = RC522_Search_Cards(PICC_REQALL, card_type_arr); // ① 寻卡 if(status == MI_OK) { status = MI_ERR; status = RC522_Anticoll(card_id_arr); } // ② 防冲撞 if(status == MI_OK) { status = MI_ERR; status = RC522_Select_Cards(card_id_arr); } // ③ 选卡 if(status == MI_OK) // ④ 合成卡ID和类型 { Card_Id = (card_id_arr[0] << 24) | (card_id_arr[1] << 16) | (card_id_arr[2] << 8) | card_id_arr[3]; Card_Type = (card_type_arr[0] << 8) | card_type_arr[1]; RC522_Sleep(); // 让卡进入睡眠,防止一直重复触发 } }

实验现象:刷卡 → 蜂鸣器响 400ms → 串口打印:

Card type = S50(0x0400) Card ID = 1268881799

LCD 同步显示 Card Type = Mifare_One(S50) 和 Card ID = ...。卡类型判断表:0x0400=M1(S50)、0x0200=S70、0x4400=UltraLight、0x4403=DESFire。

⚠️重点坑(必看)寻卡 → 防冲撞 → 选卡这三步一步都不能省。防冲撞(Anticoll)是解决 "两张卡同时放在感应区" 时的冲突问题 —— 没有它,两张卡一起放会读不出任何一张。新手最容易把三步简化成一步 "寻卡就读",然后发现读卡偶尔失败还找不到原因。

另外:读完后要调 RC522_Sleep() 让卡睡眠,不然卡一直贴在感应区会每秒重复触发,串口刷屏。


三、实验二:RFID 写入功能

功能:向卡扇区 1 的块 0/1/2写入数据(key1→块 0 写 "tangrenjie",key2→块 1 写 "dongfangxueyuan",key3→块 2 写 0x30313233,key4→清空三块),写完读回验证。

核心代码(验证密码 + 写数据 + 读回):

// ① 验证扇区密码(默认 FFFFFFFFFFFF),不通过则无法读写 status = RC522_Verification_Password(PICC_AUTHENT1A, Sector_Addr_Date[1], Pass_Word, card_id); // ② 向扇区1的块0写入16字节数据 status = RC522_Write_Date(Sector_Addr_Date[1], Test_date1); // "tangrenjie" if(status != MI_OK) { printf("数据写入失败\r\n"); return; } // ③ 读回块0/1/2,确认写入成功 for(i = 0; i < 3; i++) { status = RC522_Read_Date(Sector_Addr_Date[1] + i, card_date); memcpy(&BlockData[i][0], card_date, 16); }

实验现象:按 key1 → 刷卡 → "数据写入成功",读回显示 块0:tangrenjie 块1:dongfangxueyuan 块2:0123;按 key4 刷卡后三块全部清零。

⚠️重点坑(必看)每个扇区的块 3 是密码控制块,写数据永远只能写块 0/1/2。块 3(绝对地址 3,7,11,15,...,63)存的是密码 A/B 和访问控制位,有固定的数据格式,一旦乱写进去,整个扇区直接废掉—— 密码对不上、读写全部失败,这张卡的这个扇区就再也用不了了。原厂代码注释里特意用大写警告了这一点,是真的会发生的。

另外:写数据前必须先 RC522_Verification_Password 验证密码(默认全 F),密码错会导致写入静默失败,现象就是 "写数据失败" 刷屏。


四、实验三:RFID 应用设计・刷卡消费充值

这个实验最 "物联网":把卡当成一张电子钱包。key1 扣 2 元、key2 扣 12 元、key3 充值 200 元、key4 初始化新卡,余额存在卡的数值块里,刷卡即读写,不联网也能用 —— 这就是 M1 卡在食堂 / 超市的玩法。

背景知识:M1 卡数据块有两种模式 ——数据保存模式(普通读写,实验二用的)和数值模式(专门存金额,支持初始化 / 加值 / 减值指令)。数值块格式固定:4字节数值(小端) + 4字节反码 + 4字节数值 + 1字节地址 + 3字节地址反码。

核心代码(充值 + 扣费):

// ① 新卡先初始化:生成数值块格式写入(初始金额 10 元) Wallet_Data_Init(); // ② 十进制金额转成 4 字节小端 Value_Change(&Deduction_Value1, &HEXvalue[0]); // 扣费 2 元 // ③ 执行减值/加值指令 status = RC522_Deduction_Recharge(PICC_DECREMENT, // 扣费 Sector_Addr_Date[1] + 0, HEXvalue); status = RC522_Deduction_Recharge(PICC_INCREMENT, // 充值 Sector_Addr_Date[1] + 0, HEXvalue); // ④ 读余额(小端合成) Card_Money = card_money[0] | (card_money[1] << 8) | (card_money[2] << 16) | (card_money[3] << 24);

实验现象:key4 初始化新卡(余额 10 元)→ key3 刷卡充值 200 → 余额 210 → key1 刷卡扣 2 → 208 → key2 刷卡扣 12 → 196,串口全程打印 RFID卡当前余额:xxx元,LCD 同步显示,蜂鸣器提示。

⚠️重点坑(必看)余额判断的数值是模板没改干净的雷。看代码:

if(RCC522_Work_Mode == 1) // 扣费2元

if(Card_Money <= 0) // ← 应该是 < 2!

if(RCC522_Work_Mode == 2) // 扣费12元

if(Card_Money < 5) // ← 应该是 < 12!

扣 2 元判断的是 <= 0、扣 12 元判断的是 < 5—— 余额 5 元时扣 12 元照样成功,余额直接变负数。这是因为工程模板默认金额是 1 元和 5 元,改金额时判断条件没跟着改。演示到 "余额不足" 环节时会翻车,记得改成 Card_Money < 2 / Card_Money < 12。

另外两个提醒:①新卡必须先 key4 初始化,否则刷卡会提示 "此卡未初始化";② 初始化 / 扣费 / 充值之后要重新读一次余额再显示,别用旧值。


五、三个实验对比(含总结)

实验

核心功能

关键 API

存储位置

总结

B01 读取

读卡类型 + UID 卡号

RC522_Search_Cards → Anticoll → Select_Cards

只读,不动卡内数据

入门第一步,四步流程要背熟;注意防冲撞和多卡冲突

B02 写入

向扇区 1 块 0/1/2 写数据

Verification_Password + Write_Date + Read_Date

M1 数据块(16 字节 / 块)

密码验证是读写前提;块 3 控制块千万别碰,写坏扇区直接废

B03 刷卡消费

充值 / 扣费 / 余额 / 初始化

Deduction_Recharge(PICC_INCREMENT/DECREMENT)

M1 数值块(固定格式)

数值块有专用格式和加值 / 减值指令;余额判断要按真实金额改(模板坑)

总结:三个实验是层层递进的 —— 读卡是基础,写卡是 "能存数据",消费是 "把数据用起来",正好对应物联网 "感知 → 存储 → 应用" 的链路。


六、重点坑速查

  1. 余额 5 元扣 12 元竟然成功:余额判断是模板默认值没改(Card_Money < 5 应为 < 12),金额和判断条件要同步修改。
  1. 某扇区读写全部失败,卡 "废了":把数据写进了块 3(密码控制块)。只写块 0/1/2,块 3 绝对不动。
  1. 提示 "此卡未初始化":新卡没有数值块格式,先按 key4 初始化再使用。
  1. 读卡偶尔失败、两张卡都读不出:少了防冲撞或流程被简化,寻卡→防冲撞→选卡三步要齐全。
  1. 卡贴着感应区串口刷屏:处理完没让卡睡眠,记得调 RC522_Sleep()。

七、总结

RFID 三个实验做下来,最深的感受:

  1. RFID 的 "身份" 是硬件的:每张 M1 卡的 4 字节 UID 出厂就烧死了,读卡就是 "认卡不认人",这是它跟二维码最大的区别 —— 所以门禁、公交卡至今离不开它。
  1. 卡内存储要分清 "数据块" 和 "数值块":普通读写用数据块,存金额要用数值块指令(加值 / 减值),混用会出各种莫名其妙的问题。
  1. 细节决定成败:块 3 不能写、新卡先初始化、余额判断改金额要同步改 —— 这三个坑全是 "照抄模板没细看" 造成的。
  1. 物联网的套路:传感器篇是 "采集数据",RFID 篇是 "识别身份 + 存数据",后面再接上 WiFi 上云,就是完整的物联网应用了。

如果帮到了你,欢迎点赞收藏,评论区交流!🫡


本文基于学校智联场景实训箱(STM32L431 + Keil MDK5 + HAL 库)真实工程代码整理,代码已实测跑通。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 6:10:10

从零构建分布式网络计算机:资源聚合、任务调度与Python实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 6:09:53

【性价比降维打击】机械大师千元内白金1000W电源卷王

还在觉得1000W白金电源动辄大几百上千&#xff1f;机械大师MX1000直接打破行业溢价&#xff01;百元价位拿下80PLUS白金认证&#xff0c;转换效率高达94%&#xff0c;同级竞品里性价比直接拉满。绝非简配缩水款&#xff0c;全系搭载全日系电解电容、NXP数字主控芯片&#xff0c…

作者头像 李华
网站建设 2026/9/6 6:09:36

100英寸电视选购指南:康佳100G10省741元值不值?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 6:07:09

电容笔什么牌子好?2026专业测评榜单权威发布,帮助选购少走弯路

平板手写笔早已突破学生或设计师的小众圈层&#xff0c;成为笔记摘录、文档批注、草图绘制乃至日常办公中不可或缺的效率工具&#xff0c;它带来的精准度和流畅感&#xff0c;远非手指可比。然而面对市面上品牌繁杂、价格从几十到上千不等的电容笔&#xff0c;想要在里面挑到一…

作者头像 李华
网站建设 2026/9/6 6:02:15

某信小程序自动化与云函数调用技术解析

YYB协议后台实战&#xff0c;某信小程序自动化与云函数调用技术解析 做过某信小程序逆向和自动化采集的兄弟们都清楚&#xff0c;脱离真机环境搞自动化&#xff0c;最大的拦路虎就是 wx.login 凭证的获取、手机号授权绑定以及云函数加密调用。传统的 UIAutomator 太重&#xff…

作者头像 李华