2025 年最新树莓派 Pico 实现 RFID 射频识别、NFC 近场通信数据读写详细教程(更新中)
RFID 是 Radio Frequency Identification 的缩写,即射频识别技术,其工作原理基于电磁感应理论(射频一般指微波,频段在 1-100G Hz,适用于短距离通信),是一种非接触式的自动识别技术(目前在门禁卡、二代身份证中都有使用),它通过射频信号可以在一定范围内自动识别目标对象并获取相关数据,识别过程无需人工干预,能够在恶劣环境中工作,是无限版本的条形码,它防水、防磁、
RFID 射频识别概述
RFID 是 Radio Frequency Identification 的缩写,即射频识别技术,其工作原理基于电磁感应理论(射频一般指微波,频段在 1-100G Hz,适用于短距离通信),是一种非接触式的自动识别技术(目前在门禁卡、二代身份证中都有使用),它通过射频信号可以在一定范围内自动识别目标对象并获取相关数据,识别过程无需人工干预,能够在恶劣环境中工作,是无限版本的条形码,它防水、防磁、耐高温、使用寿命超长、读取距离大,标签上可以存储更多的数据并且可以加密,最重要的是条码识别需要人工逐一扫描,而 RFID 可同时辨识并读取多个电子标签。
RFID 组成:标签、阅读器(读写器)和天线
Tag 标签概述
标签用于附着在物体上标识目标对象,由微芯片(存储数据)和天线(发送数据)组成,每个标签有唯一的电子编码,高容量的电子标签有用户写入区。

mfrc522
from machine import Pin, SPI
class MFRC522:
OK = 0
NOTAGERR = 1
ERR = 2
REQIDL = 0x26
REQALL = 0x52
AUTHENT1A = 0x60
AUTHENT1B = 0x61
def __init__(self, sck, mosi, miso, rst, cs):
self.sck = Pin(sck, Pin.OUT)
self.mosi = Pin(mosi, Pin.OUT)
self.miso = Pin(miso)
self.rst = Pin(rst, Pin.OUT)
self.cs = Pin(cs, Pin.OUT)
self.rst.value(0)
self.cs.value(1)
self.spi = SPI(
0,
baudrate=100000,
polarity=0,
phase=0,
sck=self.sck,
mosi=self.mosi,
miso=self.miso,
)
self.spi.init()
self.rst.value(1)
self.init()
def _wreg(self, reg, val):
self.cs.value(0)
self.spi.write(b"%c" % int(0xFF & ((reg << 1) & 0x7E)))
self.spi.write(b"%c" % int(0xFF & val))
self.cs.value(1)
def _rreg(self, reg):
self.cs.value(0)
self.spi.write(b"%c" % int(0xFF & (((reg << 1) & 0x7E) | 0x80)))
val = self.spi.read(1)
self.cs.value(1)
return val[0]
def _sflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) | mask)
def _cflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) & (~mask))
def _tocard(self, cmd, send):
recv = []
bits = irq_en = wait_irq = n = 0
stat = self.ERR
if cmd == 0x0E:
irq_en = 0x12
wait_irq = 0x10
elif cmd == 0x0C:
irq_en = 0x77
wait_irq = 0x30
self._wreg(0x02, irq_en | 0x80)
self._cflags(0x04, 0x80)
self._sflags(0x0A, 0x80)
self._wreg(0x01, 0x00)
for c in send:
self._wreg(0x09, c)
self._wreg(0x01, cmd)
if cmd == 0x0C:
self._sflags(0x0D, 0x80)
i = 2000
while True:
n = self._rreg(0x04)
i -= 1
if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)):
break
self._cflags(0x0D, 0x80)
if i:
if (self._rreg(0x06) & 0x1B) == 0x00:
stat = self.OK
if n & irq_en & 0x01:
stat = self.NOTAGERR
elif cmd == 0x0C:
n = self._rreg(0x0A)
lbits = self._rreg(0x0C) & 0x07
if lbits != 0:
bits = (n - 1) * 8 + lbits
else:
bits = n * 8
if n == 0:
n = 1
elif n > 16:
n = 16
for _ in range(n):
recv.append(self._rreg(0x09))
else:
stat = self.ERR
return stat, recv, bits
def _crc(self, data):
self._cflags(0x05, 0x04)
self._sflags(0x0A, 0x80)
for c in data:
self._wreg(0x09, c)
self._wreg(0x01, 0x03)
i = 0xFF
while True:
n = self._rreg(0x05)
i -= 1
if not ((i != 0) and not (n & 0x04)):
break
return [self._rreg(0x22), self._rreg(0x21)]
def init(self):
self.reset()
self._wreg(0x2A, 0x8D)
self._wreg(0x2B, 0x3E)
self._wreg(0x2D, 30)
self._wreg(0x2C, 0)
self._wreg(0x15, 0x40)
self._wreg(0x11, 0x3D)
self.antenna_on()
def reset(self):
self._wreg(0x01, 0x0F)
def antenna_on(self, on=True):
if on and ~(self._rreg(0x14) & 0x03):
self._sflags(0x14, 0x03)
else:
self._cflags(0x14, 0x03)
def request(self, mode):
self._wreg(0x0D, 0x07)
(stat, recv, bits) = self._tocard(0x0C, [mode])
if (stat != self.OK) | (bits != 0x10):
stat = self.ERR
return stat, bits
def anticoll(self):
ser_chk = 0
ser = [0x93, 0x20]
self._wreg(0x0D, 0x00)
(stat, recv, bits) = self._tocard(0x0C, ser)
if stat == self.OK:
if len(recv) == 5:
for i in range(4):
ser_chk = ser_chk ^ recv[i]
if ser_chk != recv[4]:
stat = self.ERR
else:
stat = self.ERR
return stat, recv
def select_tag(self, ser):
buf = [0x93, 0x70] + ser[:5]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR
def auth(self, mode, addr, sect, ser):
return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0]
def stop_crypto1(self):
self._cflags(0x08, 0x08)
def read(self, addr):
data = [0x30, addr]
data += self._crc(data)
(stat, recv, _) = self._tocard(0x0C, data)
return recv if stat == self.OK else None
def write(self, addr, data):
buf = [0xA0, addr]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A):
stat = self.ERR
else:
buf = []
for i in range(16):
buf.append(data[i])
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
if (
not (stat == self.OK)
or not (bits == 4)
or not ((recv[0] & 0x0F) == 0x0A)
):
stat = self.ERR
return stat
其他版本 mfrc522 下载地址:https://github.com/wendlers/micropython-mfrc522/blob/master/mfrc522.py
Pico 连接读写测试
import mfrc522
from machine import Pin
sck = 6
mosi = 7
miso = 4
cs = 5
rst = 22
def do_write():
rdr = mfrc522.MFRC522(sck=sck, mosi=mosi, miso=miso, rst=rst, cs=cs)
print("")
print("Place card before reader to write address 0x08")
print("")
try:
while True:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
print("New card detected")
print("- tag type: 0x%02x" % tag_type)
print("- uid: 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
print("")
if rdr.select_tag(raw_uid) == rdr.OK:
key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
stat = rdr.write(8, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")
rdr.stop_crypto1()
if stat == rdr.OK:
print("Data written to card")
else:
print("Failed to write data to card")
else:
print("Authentication error")
else:
print("Failed to select tag")
except KeyboardInterrupt:
print("Exit")
if __name__ == '__main__':
do_write()
import mfrc522
from machine import Pin
sck = 6
mosi = 7
miso = 4
cs = 5
rst = 22
def do_read():
rdr = mfrc522.MFRC522(sck=sck, mosi=mosi, miso=miso, rst=rst, cs=cs)
print("")
print("Place card before reader to read from address 0x08")
print("")
try:
while True:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
print("New card detected")
print("- tag type: 0x%02x" % tag_type)
print("- uid: 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
print("")
if rdr.select_tag(raw_uid) == rdr.OK:
key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
print("Address 8 data: %s" % rdr.read(8))
rdr.stop_crypto1()
else:
print("Authentication error")
else:
print("Failed to select tag")
except KeyboardInterrupt:
print("Exit")
if __name__ == '__main__':
do_read()
运行结果
Place card before reader to write address 0x08
New card detected
- tag type: 0x10
- uid: 0xf5dc2c03
Place card before reader to read from address 0x08
New card detected
- tag type: 0x10
- uid: 0xf5dc2c03
Address 8 data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
NFC 概述
NFC 英文全称 Near Field Communication,近距离无线通信。是由飞利浦公司发起,由诺基亚、索尼等著名厂商联合主推的一项无线技术。
NFC 由非接触式射频识别 (RFID) 及互联互通技术整合演变而来,在单一芯片上结合感应式读卡器、感应式卡片和点对点的功能,能在短距离内与兼容设备进行识别和数据交换。这项技术最初只是 RFID 技术和网络技术的简单合并,现在已经演变成一种短距离无线通信技术,发展态势相当迅速。
主动模式:在这种模式下,两台NFC设备(如智能手机和支付终端)都生成自己的射频场,互相通信。每个设备在发送数据时生成射频场,并在接收数据时关闭射频场。
被动模式:在这种模式下,只有一个设备(如NFC标签)生成射频场,而另一个设备(如智能手机)利用这个射频场进行通信。NFC标签通常不需要内置电源,而是通过外部设备的射频场供电。
NFC 终端主要包括非接触性前端 CLF (NFC 控制器)、天线 (Antenna)、安全模块 (Secure Element, SE) 3 个主要部件,其中非接前端、天线一般都集成在手机终端中,而安全模块可根据情况存放在不同的位置。

待更新······
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)