15 AirRC522_1000
作者: 马亚丹 | 最后修改:2026-04-13
一、AirRC522_1000 简介
1.1 背景
RC522 是荷兰 NXP(恩智浦)半导体推出的一款高集成度 RFID 射频卡读写芯片,专门用于处理 13.56MHz 频段的非接触式 IC 卡(如 MIFARE Classic 1K/4K 卡、NFC 标签等),是物联网、嵌入式领域中低成本、易集成的经典 RFID 读写方案。
- 主打非接触式射频识别(RFID)读写,支持 ISO 14443A 通信协议(主流非接触 IC 卡标准)
- 集成射频收发器、数字信号处理单元,无需额外射频电路,仅需少量外围元件即可工作
- 工作电压 2.5V~3.3V,低功耗,适合嵌入式设备。
1.2 AirRC522_1000 与普通 RFID 模块的区别
合宙 AirRC522_1000 是模块化产品,即把 RC522 核心芯片 + 外围电路(天线、电容电阻)封装好的成品,无需自己焊接射频电路,直接接线即可使用。
特点
- 容量为 8K 位 EEPROM。
- 分为 16 个扇区,每个扇区为 4 块,每块 16 个字节,以块为存取单位。
- 每个扇区有独立的一组密码及访问控制。
- 每张卡有唯一序列号,为 32 位。
- 具有防冲突机制,支持多卡操作。
- 无电源,自带天线,内含加密控制逻辑和通讯逻辑电路。
- 数据保存期为 10 年,可改写 10 万次,读无限次。
储存结构
M1 卡分为 16 个扇区,每个扇区由 4 块(块 0、块 1、块 2、块 3)组成,(我们也将 16 个扇区的 64 个块按绝对地址编号为 0~63,存储结构如下图所示:

- 第 0 扇区的块 0(即绝对地址 0 块),它用于存放厂商代码,已经固化,不可更改。
- 每个扇区的块 0、块 1、块 2 为数据块,可用于存贮数据。
数据块可作两种应用:
- 用作一般的数据保存,可以进行读、写操作。
- 用作数据值,可以进行初始化值、加值、减值、读值操作。
每个扇区的块 3 为控制块,包括了密码 A、存取控制、密码 B。具体结构如下:

每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为 4 个字节,共 32 位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:

1.3 AirRC522_1000 典型应用场景
- 门禁系统、考勤机(读取员工卡 UID 验证身份);
- 公交卡、校园卡、消费机(读写卡内金额 / 数据块);
- 嵌入式设备外接 RFID 功能;
- 小型仓储、物流的电子标签识别。
AirRC522_1000 适用于 Air700ECH/Air780EHN/EHU/EHM/EHV/EGH/EPM/Air8000 全系/Air8101
二、功能演示概述
本文演示合宙 4G 模组 Air8000 使用 LuatOS 开发时, 通过 spi 接口挂载 AirRC522_1000 应用功能,通过 spi 接口驱动 RC522 传感器读取 ic 数据卡数据.
使用 Air8000 核心板下载 Air8000 的 LuatOS 示例代码中 accessory_board/AirRC522_1000 的例程进行功能演示:
- 初始化并启用 spi,如果初始化失败,退出程序
- 初始化 RC522 模块,如果初始化失败,退出程序
- 循环检测卡片。
- 向卡片指定块号写入数据,并读取数据验证一致性
- 读取卡片所有数据
三、准备硬件环境
3.1 参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。
3.2 Air8000 核心板一块,AirRC522_1000 一套
AirRC522_1000 小板实物图:

3.3 TYPE-C USB 数据线一根 ,Air8000 核心板和数据线的硬件接线方式为:
- Air8000 核心板通过 TYPE-C USB 口供电(核心板背面的开关拨到 USB ON 一端,正面开关拨到 供电 一端)
- TYPE-C USB 数据线直接插到开发板的 TYPE-C USB 座子,另外一端连接电脑 USB 口;
3.4 杜邦线 7 根
Air8000 核心板与 AirRC522_1000 按以下方式接线:
| Air8000核心板 | AirRC522_1000配件版 |
| GND(任意) | GND |
| VDD_EXT | 3.3V |
| GPIO12/SPI1_CS | SDA |
| SPI1_SCLK | SCK |
| SPI1_MOSI | MOSI |
| SPI1_MISO | MISO |
| GPIO16(可选任意空闲IO) | RST |
Air8000 核心板管脚图:

Air8000 核心板与 AirRC522_1000 小板接线实物图:

四、准备软件环境
在开始实践本示例之前,先准备一下软件环境:
4.1 Luatools 工具,如果是第一次使用 Luatools 工具,请仔细阅读此链接教程。
4.2 内核固件文件(底层 core 固件文件):
本demo开发测试时使用的固件为LuatOS-SoC_V2018_Air8000_1.soc,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
4.3 luatos 需要的脚本和资源文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/accessory_board/AirRC522_1000
-
main.lua:主程序入口
-
rc522.lua :rc522 扩展库文件,在 AirRC522_1000.lua 功能模块中 require 使用
4.4 lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到 Air8000 核心板,将本篇文章中演示使用的项目文件烧录到 Air8000 核心板中。
五、API 接口说明
六、示例代码和功能展示
6.1 流程介绍
1、搭建好硬件环境
2、Luatools 烧录内核固件和 demo 脚本代码.
AirRC522_1000.lua 脚本中,硬件配置参数中 rst_pin 是使用 Air8000 核心板的 GPIO16,如果接其他 IO,注意修改硬件配置参数中 rst_pin 对应的管脚号。
3、烧录成功后,自动开机运行,查看打印日志,如果正常运行,会打印相关信息,spi 初始化,rc522 初始化,写入数据读取数据等。
6.2 代码和 log
6.2.1 main.lua
代码示例(点击查看完整 demo)
PROJECT = "Air8000_rc522_DEMO"
VERSION = "001.000.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
if wdt then
--配置喂狗超时时间为9秒钟
wdt.init(9000)
--启动一个循环定时器,每隔3秒钟喂一次狗
sys.timerLoopStart(wdt.feed, 3000)
end
-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
-- 启动errDump日志存储并且上传功能,600秒上传一次
-- if errDump then
-- errDump.config(true, 600)
-- end
-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
-- 可以使用合宙的iot.openluat.com平台进行远程升级
-- 也可以使用客户自己搭建的平台进行远程升级
-- 远程升级的详细用法,可以参考fota的demo进行使用
-- 启动一个循环定时器
-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
-- 方便分析内存使用是否有异常
-- sys.timerLoopStart(function()
-- log.info("mem.lua", rtos.meminfo())
-- log.info("mem.sys", rtos.meminfo("sys"))
-- end, 3000)
-- 加载AirRC522_1000功能模块
require "AirRC522_1000"
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行
6.2.2 AirRC522_1000.lua
6.2.2.1 核心代码部分(点击查看完整 demo)
rc522 = require "rc522"
-- 硬件配置参数(Air8000适配)
local RC522_CONFIG = {
spi_id = 1, -- SPI通道
cs_pin = 12, -- 片选引脚
rst_pin = 16, -- 复位引脚
spi_baud = 2 * 1000 * 1000, -- SPI波特率
}
-- 全局变量(模块内可见)
local spi_dev = nil -- SPI设备对象
-- 1. 初始化SPI接口
local function init_spi()
log.info("RC522", "初始化SPI接口")
-- 配置SPI参数:模式0,8位数据,高位在前
spi_dev = spi.setup(
RC522_CONFIG.spi_id,
RC522_CONFIG.cs_pin,
0, -- 极性0
0, -- 相位0
8, -- 数据位
RC522_CONFIG.spi_baud,
spi.MSB, -- 高位优先
spi.master, --主模式
spi.half --半双工
)
if not spi_dev then
log.error("RC522", "SPI初始化失败")
return false
end
log.info("RC522", "SPI初始化成功")
return true
end
-- 2. 初始化RC522模块
local function init_rc522()
log.info("RC522", "初始化RC522传感器")
-- 初始化RC522硬件(SPI ID、CS引脚、RST引脚)
local init_ok = rc522.init(
RC522_CONFIG.spi_id,
RC522_CONFIG.cs_pin,
RC522_CONFIG.rst_pin
)
if not init_ok then
log.error("RC522", "传感器初始化失败")
return false
end
log.info("RC522", "传感器初始化成功")
return true
end
-- 3. 写数据
local function write_ic_card(block, data)
-- 步骤1:验证数据长度
if #data > 16 then
log.error("RC522", "数据过长(最大16字节)")
return false
end
-- 步骤2:写入数据块
local write_ok = rc522.write_datablock(block, data)
if not write_ok then
log.error("RC522", "数据写入失败,块号:", block)
return false
end
log.info("RC522", "数据写入成功,块号:", block, "写入数据是:", string.char(table.unpack(data)):toHex())
return true
end
-- 4. 检测并读取IC卡数据
local function read_ic_card()
-- 检测是否有卡片靠近
local status, array_id = rc522.request(rc522.reqall)
if not status then
log.info("RC522", "未检测到卡片")
return false
end
log.info("RC522", "检测到卡片,类型:", array_id:toHex())
-- 防冲突检测,获取卡片唯一ID
local status, card_uid = rc522.anticoll(array_id)
if not status then
log.error("RC522", "防冲突检测失败")
return false
end
log.info("RC522", "卡片UID:", card_uid:toHex())
-- -- 选择卡片,激活卡片进行后续操作
local select_ok = rc522.select(card_uid)
if not select_ok then
log.error("RC522", "卡片选择失败")
return false
end
-- 写数据测试
local TEST_BLOCK = 9
-- 待写入的数据
local TEST_DATA = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
if write_ic_card(TEST_BLOCK, TEST_DATA) then
-- 读数据验证
local read_ok, read_data = rc522.read_datablock(TEST_BLOCK)
if read_ok and read_data == string.char(table.unpack(TEST_DATA)) then
log.info("RC522", "写入验证成功,数据是:", read_data:toHex())
else
log.warn("RC522", "写入验证失败,实际读取的数据是:", read_data:toHex())
end
end
-- 读取卡片数据块(0-63块)
log.info("RC522", "开始读取卡片数据...")
for block = 0, 63 do
local read_ok, data = rc522.read_datablock(block)
if read_ok and data then
log.info(string.format("块[%d]", block), data:toHex())
else
log.warn(string.format("块[%d]读取失败", block))
end
--每读取完一个块等待20ms(时间可按需修改)
sys.wait(20)
end
-- 停止卡片操作
rc522.halt()
return true
end
-- 5. 关闭SPI设备,成功返回0
local function spi_close_func()
log.info("关闭spi", spi.close(RC522_CONFIG.spi_id))
end
-- 6. 主测试任务
local function rc522_main_test()
-- 初始化硬件
if not init_spi() then
spi_close_func()
return
end
if not init_rc522() then
spi_close_func()
return
end
-- 循环检测卡片
log.info("RC522", "开始检测卡片")
while true do
read_ic_card()
-- 循环检测间隔:2s
sys.wait(2000)
end
end
-- 启动主任务
sys.taskInit(rc522_main_test)
6.2.2.2 例程 log 打印如下:
[2025-12-01 15:03:45.780][000000000.374] I/user.main Air8000_rc522_DEMO 001.000.000
[2025-12-01 15:03:45.790][000000000.412] I/user.RC522 初始化SPI接口
[2025-12-01 15:03:45.799][000000000.413] SPI_HWInit 552:spi1 speed 2000000,1994805,154
[2025-12-01 15:03:45.805][000000000.413] I/user.RC522 SPI初始化成功
[2025-12-01 15:03:45.815][000000000.413] I/user.RC522 初始化RC522传感器
[2025-12-01 15:03:45.820][000000000.416] D/user.rc522.version 146
[2025-12-01 15:03:45.824][000000000.417] I/user.RC522 传感器初始化成功
[2025-12-01 15:03:45.831][000000000.417] I/user.RC522 开始检测卡片
[2025-12-01 15:03:45.835][000000000.424] I/user.RC522 检测到卡片,类型: 0400 4
[2025-12-01 15:03:45.839][000000000.430] I/user.RC522 卡片UID: E3E2AD14 8
[2025-12-01 15:03:45.845][000000000.526] I/user.RC522 数据写入成功,块号: 9 写入数据是: 01000000000000000000000000000000 32
[2025-12-01 15:03:45.904][000000000.580] I/user.RC522 写入验证成功,数据是: 01000000000000000000000000000000 32
[2025-12-01 15:03:45.913][000000000.581] I/user.RC522 开始读取卡片数据...
[2025-12-01 15:03:45.919][000000000.639] I/user.块[0] E3E2AD14B80804006263646566676869 32
[2025-12-01 15:03:45.923][000000000.716] I/user.块[1] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.031][000000000.814] I/user.块[2] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.040][000000000.942] I/user.块[3] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:46.045][000000001.011] I/user.块[4] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.056][000000001.084] I/user.块[5] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.130][000000001.152] I/user.块[6] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.195][000000001.219] I/user.块[7] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:46.273][000000001.289] I/user.块[8] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.337][000000001.354] I/user.块[9] 01000000000000000000000000000000 32
[2025-12-01 15:03:46.401][000000001.419] I/user.块[10] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.462][000000001.485] I/user.块[11] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:46.524][000000001.550] I/user.块[12] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.588][000000001.616] I/user.块[13] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.665][000000001.681] I/user.块[14] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.728][000000001.747] I/user.块[15] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:46.790][000000001.812] I/user.块[16] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.854][000000001.877] I/user.块[17] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.916][000000001.943] I/user.块[18] 00000000000000000000000000000000 32
[2025-12-01 15:03:46.994][000000002.009] I/user.块[19] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:47.056][000000002.074] I/user.块[20] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.118][000000002.139] I/user.块[21] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.180][000000002.204] I/user.块[22] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.241][000000002.269] I/user.块[23] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:47.319][000000002.335] I/user.块[24] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.382][000000002.400] I/user.块[25] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.443][000000002.466] I/user.块[26] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.505][000000002.532] I/user.块[27] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:47.607][000000002.589] D/mobile cid1, state0
[2025-12-01 15:03:47.611][000000002.591] D/mobile bearer act 0, result 0
[2025-12-01 15:03:47.615][000000002.592] D/mobile NETIF_LINK_ON -> IP_READY
[2025-12-01 15:03:47.619][000000002.628] I/user.块[28] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.623][000000002.632] D/mobile TIME_SYNC 0
[2025-12-01 15:03:47.676][000000002.694] I/user.块[29] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.738][000000002.759] I/user.块[30] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.801][000000002.825] I/user.块[31] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:47.863][000000002.890] I/user.块[32] 00000000000000000000000000000000 32
[2025-12-01 15:03:47.926][000000002.955] I/user.块[33] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.004][000000003.021] I/user.块[34] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.066][000000003.087] I/user.块[35] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:48.128][000000003.152] I/user.块[36] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.190][000000003.219] I/user.块[37] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.270][000000003.288] I/user.块[38] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.331][000000003.353] I/user.块[39] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:48.393][000000003.418] I/user.块[40] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.455][000000003.483] I/user.块[41] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.532][000000003.548] I/user.块[42] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.595][000000003.614] I/user.块[43] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:48.655][000000003.679] I/user.块[44] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.717][000000003.745] I/user.块[45] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.794][000000003.810] I/user.块[46] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.856][000000003.876] I/user.块[47] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:48.918][000000003.942] I/user.块[48] 00000000000000000000000000000000 32
[2025-12-01 15:03:48.983][000000004.007] I/user.块[49] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.044][000000004.073] I/user.块[50] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.123][000000004.138] I/user.块[51] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:49.187][000000004.204] I/user.块[52] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.249][000000004.270] I/user.块[53] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.311][000000004.335] I/user.块[54] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.375][000000004.401] I/user.块[55] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:49.438][000000004.467] I/user.块[56] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.515][000000004.533] I/user.块[57] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.577][000000004.600] I/user.块[58] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.639][000000004.667] I/user.块[59] 000000000000FF078069FFFFFFFFFFFF 32
[2025-12-01 15:03:49.716][000000004.732] I/user.块[60] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.779][000000004.797] I/user.块[61] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.843][000000004.862] I/user.块[62] 00000000000000000000000000000000 32
[2025-12-01 15:03:49.905][000000004.927] I/user.块[63] 000000000000FF078069FFFFFFFFFFFF 32
6.2.2.3 luatools 运行日志图示




七、总结
本文档主要介绍 AirRC522_1000 的使用方法。
结合 demo 例程讲解了 AirRC522_1000 的应用流程,介绍了 spi API 接口和 AirRC522_1000 的使用方法,旨在最简单的快速上手 Air8000 的 LuatOS 的 AirRC522_1000 应用.