基础资料

基于Air103开发板:🚗 Air103 - LuatOS 文档

上手:开发上手 - LuatOS 文档

探讨重点

对官方社区库接口RC522模块库调用及示例进行复现及分析,了解RDIF及非接触式IC卡的原理及操作方法。

实现功能

利用已知的A,B密钥,进行标准和异型IC卡的数据处理及读写;

硬件准备

Air103开发板1块,面包板1块,RC522读写器模块,标准、异型IC卡各1张,导线若干。

aesir说明书 aesir耳机说明书_物联网

接线

标准SPI接口,可参考博文:

合宙Air105|摄像头|capture|SPI|Serial 串口|TFTLCD|Micro SD卡|GC032A|USB转TTL|官方demo|学习(2-1):摄像头camera-capture_Medlar_CN的博客

aesir说明书 aesir耳机说明书_物联网_02

除丝印为IRQ的端子无作用(应为NC)外,其他参照开发板功能定义正常接入方式(使用)。

SPI接线设置:

spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
    result=rc522.init(0,pin.PB04,pin.PB01) --spi_id, cs, rst

软件版本

AIR103:LuatOS@AIR103 base 22.10 bsp V0013

软件使用

接口文档可参考:rc522 非接触式读写卡驱动

RFID与IC卡

RFID一般指射频识别技术。 射频识别(RFID)是 Radio Frequency Identification 的缩写。其原理为阅读器与标签之间进行非接触式的数据通信,达到识别目标的目的。

而IC卡 (Integrated Circuit Card,集成电路卡),也称智能卡(Smart card)、智慧卡(Intelligent card)、微电路卡(Microcircuit card)或微芯片卡等。

IC卡由于其固有的信息安全、便于携带、比较完善的标准化等优点。IC卡属于使用RFID技术的一个卡片种类。

本文主要介绍Mifare1 S50IC卡,有标准和异型两种类别。

aesir说明书 aesir耳机说明书_lua_03

S50IC卡的编码格式

产品简介

S50非接触式IC卡性能简介(M1)

一、   主要指标

  容量为8K位EEPROM

  分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位

  每个扇区有独立的一组密码及访问控制

  每张卡有唯一序列号,为32位

  具有防冲突机制,支持多卡操作

  无电源,自带天线,内含加密控制逻辑和通讯逻辑电路

  数据保存期为10年,可改写10万次,读无限次

  工作温度:-20℃~50℃(湿度为90%)

  工作频率:13.56MHZ

  通信速率:106 KBPS

  读写距离:10 cm以内(与读写器有关)

二、存储结构

M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成(16个扇区的64个块按绝对地址编号为0~63。

PHILIPS原始芯片的卡片,控制字为:FF078069。

aesir说明书 aesir耳机说明书_射频工程_04

A、B密钥是重要的访问参数,即为操作库代码中的Key_A、Key_B。

local Key_A = string.char(0x00,0x00,0x00,0x00,0x00,0x0)
local Key_B = string.char(0xff,0xff,0xff,0xff,0xff,0xff)

三、特别提醒

测试时最好使用空白卡或者无重要作用的测试卡。

读写操作如果密钥错误或不知道密钥,有加密区块被锁定,而导致该区块整体无法访问和使用的风险。

RC522读写驱动使用及分析

Main.lua

(官方代码库只有RC22库和基础用法。为测试方便,增加了主文件:main.lua):

操作:

1、正常初始化

2、写扇区2-数据块8为:0100000000000000

3、顺序读扇区数据:(0-63)

PROJECT = "rc522-air103"
VERSION = "1.0.0"
sys = require("sys")

local rc522 = require "rc522"

sys.taskInit(function()
    spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
             --spi_id, cs, rst
   rc522.init(0,pin.PB04,pin.PB01)
   wdata = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
    local n=8
    while 1 do
        result=rc522.write_datablock(n,wdata)
        if result then
            log.info("rc522_write:"..tostring(n), "OK!", result)
        else
            log.info("rc522_write:"..tostring(n), "Error!", result)
        end
        for i=0,63 do
            local a,b = rc522.read_datablock(i)
            if a then
                log.info("read",i,b:toHex())  --字节流转换为16进制显示
            end
        end
        sys.wait(500)
    end
end)

sys.run()

rc522.lua(驱动程序,主要代码分析,完整代码见官方gitee)

操作库定义:

local rc522 = {}
local sys = require "sys"
local rc522_spi,rc522_rst,rc522_irq,rc522_cs

A,B密钥:

local Key_A = string.char(0x00,0x00,0x00,0x00,0xff,0x0)
local Key_B = string.char(0xff,0xff,0xff,0xff,0xff,0xff)

读写器初始化:

--[[
rc522 初始化
@api rc522.init(spi_id, cs, rst)
@number spi_id spi端口号
@number cs      cs引脚
@number rst     rst引脚
@return bool 初始化结果
@usage
spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
rc522.init(0,pin.PB04,pin.PB01)
]]
function rc522.init(spi_id,cs,rst)
    rc522_spi = spi_id
    rc522_cs = gpio.setup(cs, 0, gpio.PULLUP)
    rc522_cs(1)
    rc522_rst = gpio.setup(rst, 0, gpio.PULLUP)
    rc522_rst(1)
    rc522.reset()
    rc522_config_isotype()
    print("rc522.version",rc522.version())
    return true
end

读块内容:

--[[
按照rc522操作流程读取块
@api rc522.read_datablock(addr)
@number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
@return bool string 结果 数据
@usage
    for i=0,63 do
        local a,b = rc522.read_datablock(i)
        if a then
            print("read",i,b:toHex())
        end
    end
]]
function rc522.read_datablock(addr)
    local status,array_id = rc522.request(rc522.reqall)
    if  status ~= true then
        status,array_id = rc522.request(rc522.reqall)
    end
    if status == true then
        local status,uid = rc522.anticoll(array_id)
        if status == true then
            rc522.select(uid)
            status = authstate( rc522_authent1b, addr,Key_B,uid )
            if status == true then
                local status,data = read(addr)
                if status == true then
                    return true, data
                end
                rc522.halt()
            end
        end
    end
    return false
end

写块内容:

--[[
按照rc522操作流程写入16字节数据到块
@api rc522.write_datablock(addr,data)
@number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
@table data 指向要写入的数据,必须为16个字符
@return bool 结果
@usage
rc522.write_datablock(addr,data)
]]
function rc522.write_datablock(addr,data)
    if #data ~= 16 then
        return false
    end
    local status,array_id = rc522.request(rc522.reqall)
    if  status ~= true then
        status,array_id = rc522.request(rc522.reqall)
    end
    if status == true then
        local status,uid = rc522.anticoll(array_id)
        if status == true then
            rc522.select(uid)
            status = authstate( rc522_authent1b, addr,Key_B,uid )
            if status == true then
                status = rc522.write(addr,data)
                rc522.halt()
                return status
            end
        end
    end
    return false
end

日志log文件示例:

aesir说明书 aesir耳机说明书_物联网_05