Dozingfiretruck пре 3 година
родитељ
комит
ff898f9f5e
2 измењених фајлова са 653 додато и 0 уклоњено
  1. 9 0
      script/libs/rc522/package.json
  2. 644 0
      script/libs/rc522/rc522.lua

+ 9 - 0
script/libs/rc522/package.json

@@ -0,0 +1,9 @@
+{
+    "type" : "lua", // 可以是lua(纯lua), c(纯c), 或者lua-c(混合)
+    "enterpoint" : "rc522.lua",
+    "compatibility" : {
+        "soc" : true,
+        "air" : false
+    },
+    "dependency" : ["spi"] // 需要何种硬件或软件接口
+}

+ 644 - 0
script/libs/rc522/rc522.lua

@@ -0,0 +1,644 @@
+--[[
+@module rc522
+@summary rc522 非接触式读写卡驱动
+@version 1.0
+@date    2022.06.14
+@author  Dozingfiretruck
+@usage
+--注意:因使用了sys.wait()所有api需要在协程中使用
+-- 用法实例
+local rc522 = require "rc522"
+sys.taskInit(function()
+    spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
+    rc522.init(0,pin.PB04,pin.PB01)
+    wdata = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+    while 1 do
+        rc522.write_datablock(8,wdata)
+        for i=0,63 do
+            local a,b = rc522.read_datablock(i)
+            if a then
+                print("read",i,b:toHex())
+            end
+        end
+        sys.wait(500)
+    end
+end)
+]]
+
+
+local rc522 = {}
+
+local sys = require "sys"
+
+local rc522_spi,rc522_rst,rc522_irq,rc522_cs
+
+---器件所用地址
+local rc522_idle              =       0x00   --取消当前命令
+local rc522_authent           =       0x0E   --验证密钥
+local rc522_receive           =       0x08   --接收数据
+local rc522_transmit          =       0x04   --发送数据
+local rc522_transceive        =       0x0C   --发送并接收数据
+local rc522_resetphase        =       0x0F   --复位
+local rc522_calccrc           =       0x03   --CRC计算
+
+--Mifare_One卡片命令字
+rc522.reqidl                 =       0x26   --寻天线区内未进入休眠状态
+rc522.reqall                 =       0x52   --寻天线区内全部卡
+local rc522_anticoll1        =       0x93   --防冲撞
+local rc522_anticoll2        =       0x95   --防冲撞
+local rc522_authent1a        =       0x60   --验证A密钥
+local rc522_authent1b        =       0x61   --验证B密钥
+local rc522_read             =       0x30   --读块
+local rc522_write            =       0xA0   --写块
+local rc522_decrement        =       0xC0   --扣款
+local rc522_increment        =       0xC1   --充值
+local rc522_restore          =       0xC2   --调块数据到缓冲区
+local rc522_transfer         =       0xB0   --保存缓冲区中数据
+local rc522_halt             =       0x50   --休眠
+
+--MF522寄存器定义
+-- PAGE 0
+local rc522_rfu00            =       0x00 --保留为将来之用    
+local rc522_com_mand         =       0x01 --启动和停止命令的执行      
+local rc522_com_ie           =       0x02 --中断请求传递的使能和禁能控制位      
+local rc522_divl_en          =       0x03 --中断请求传递的使能和禁能控制位      
+local rc522_com_irq          =       0x04 --包含中断请求标志      
+local rc522_div_irq          =       0x05 --包含中断请求标志  
+local rc522_error            =       0x06 --错误标志,指示执行的上个命令的错误状态      
+local rc522_status1          =       0x07 --包含通信的状态标志      
+local rc522_status2          =       0x08 --包含接收器和发送器的状态标志      
+local rc522_fifo_data        =       0x09 --64 字节 FIFO 缓冲区的输入和输出  
+local rc522_fifo_level       =       0x0A --指示 FIFO 中存储的字节数  
+local rc522_water_level      =       0x0B --定义 FIFO 下溢和上溢报警的 FIFO 深度  
+local rc522_control          =       0x0C --不同的控制寄存器  
+local rc522_bit_framing      =       0x0D --面向位的帧的调节  
+local rc522_coll             =       0x0E --RF 接口上检测到的第一个位冲突的位的位置  
+local rc522_rfu0f            =       0x0F --保留为将来之用  
+-- PAGE 1     
+local RFU10                  =       0x10 --保留为将来之用
+local rc522_mode             =       0x11 --定义发送和接收的常用模式
+local rc522_tx_mode          =       0x12 --定义发送过程的数据传输速率
+local rc522_rx_mode          =       0x13 --定义接收过程中的数据传输速率
+local rc522_tx_control       =       0x14 --控制天线驱动器管脚 TX1 和 TX2 的逻辑特性
+local rc522_tx_ayto          =       0x15 --控制天线驱动器的设置
+local rc522_tx_sel           =       0x16 --选择天线驱动器的内部源
+local rc522_rx_sel           =       0x17 --选择内部的接收器设置
+local rc522_rx_threshold     =       0x18 --选择位译码器的阈值
+local rc522_demod            =       0x19 --定义解调器的设置
+local rc522_rfu1a            =       0x1A --保留为将来之用
+local rc522_rfu1b            =       0x1B --保留为将来之用
+local rc522_mifare           =       0x1C --控制 ISO 14443/MIFARE 模式中 106kbit/s 的通信
+local rc522_rfu1d            =       0x1D --保留为将来之用
+local rc522_rfu1e            =       0x1E --保留为将来之用
+local rc522_serial_speed     =       0x1F --选择串行 UART 接口的速率
+-- PAGE 2    
+local rc522_rfu20            =       0x20 --保留为将来之用  
+local rc522_crcresult_m      =       0x21 --显示 CRC 计算的实际 MSB 值
+local rc522_crcresult_l      =       0x22 --显示 CRC 计算的实际 LSB 值
+local rc522_rfu23            =       0x23 --保留为将来之用
+local rc522_mod_width        =       0x24 --控制 ModWidth 的设置
+local rc522_rfu25            =       0x25 --保留为将来之用
+local rc522_rfcfg            =       0x26 --配置接收器增益
+local rc522_gsn              =       0x27 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_cwgscfg          =       0x28 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_modgscfg         =       0x29 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_tmode            =       0x2A --定义内部定时器的设置
+local rc522_tprescaler       =       0x2B --定义内部定时器的设置
+local rc522_tpreload_h       =       0x2C --描述 16 位长的定时器重装值
+local rc522_tpreload_l       =       0x2D --描述 16 位长的定时器重装值
+local rc522_tcounter_value_h =       0x2E --描述 16 位长的定时器重装值
+local rc522_tcounter_value_l =       0x2F --描述 16 位长的定时器重装值
+-- PAGE 3      
+local rc522_rfu30            =       0x30 --保留为将来之用
+local rc522_testsel1         =       0x31 --常用测试信号的配置
+local rc522_testsel2         =       0x32 --常用测试信号的配置和 PRBS 控制
+local rc522_testpin_en       =       0x33 --D1-D7 输出驱动器的使能管脚(注:仅用于串行接口)
+local rc522_testpin_value    =       0x34 --定义 D1-D7 用作 I/O 总线时的值
+local rc522_testbus          =       0x35 --显示内部测试总线的状态
+local rc522_autotest         =       0x36 --控制数字自测试
+local rc522_version          =       0x37 --显示版本
+local rc522_analogtest       =       0x38 --控制管脚 AUX1 和 AUX2
+local rc522_testadc1         =       0x39 --定义 TestDAC1 的测试值  
+local rc522_testadc2         =       0x3A --定义 TestDAC2 的测试值   
+local rc522_testadc          =       0x3B --显示 ADC I 和 Q 通道的实际值   
+local rc522_rfu3c            =       0x3C --保留用于产品测试   
+local rc522_rfu3d            =       0x3D --保留用于产品测试   
+local rc522_rfu3e            =       0x3E --保留用于产品测试   
+local rc522_rfu3f		     =       0x3F --保留用于产品测试
+
+local Key_A = string.char(0xff,0xff,0xff,0xff,0xff,0xff)
+local Key_B = string.char(0xff,0xff,0xff,0xff,0xff,0xff)
+
+--[[
+写rc522寄存器
+@api rc522.set_bit_mask(address, value)
+@number address 地址
+@number value    值
+@usage
+write_rawrc(rc522_bit_framing,0x07)
+]]
+local function write_rawrc(address, value)
+    rc522_cs(0)
+    local data = string.char((address<<1)&0x7E) .. string.char(value)
+    spi.send(rc522_spi, data)
+    -- rc522_spi:send(data)
+    rc522_cs(1)
+end
+
+--[[
+读rc522寄存器
+@api rc522.read_rawrc(address)
+@number address 地址
+@return number 寄存器值
+@usage
+local n = read_rawrc(rc522_com_irq) 
+]]
+local function read_rawrc(address)
+    rc522_cs(0)
+    local data = string.char(((address<<1)&0x7E)|0x80)
+    spi.send(rc522_spi, data)
+    local val = spi.recv(rc522_spi,1)
+    -- rc522_spi:send(data)
+    -- local val = rc522_spi:recv(1)
+    rc522_cs(1)
+    return string.byte(val)
+end
+
+--[[
+对rc522寄存器置位
+@api rc522.set_bit_mask(address, mask)
+@number address 地址
+@number mask    置位值
+@usage
+rc522.set_bit_mask (rc522_fifo_level, 0x80)	
+]]
+function rc522.set_bit_mask(address, mask)
+    local current = read_rawrc(address)
+    write_rawrc(address, bit.bor(current, mask))
+end
+
+--[[
+对rc522寄存器清位
+@api rc522.clear_bit_mask(address, mask)
+@number address 地址
+@number mask    清位值
+@usage
+rc522.clear_bit_mask(rc522_com_irq, 0x80 )
+]]
+function rc522.clear_bit_mask(address, mask)
+    local current = read_rawrc(address)
+    write_rawrc(address, bit.band(current, bit.bnot(mask)))
+end
+
+--[[ 
+命令通讯
+@api rc522.command(command,data)
+@number command 
+@number data 
+@return status data len 结果,返回数据,收到的位长度
+@usage
+rc522.version()
+]]
+function rc522.command(command,data)
+    local out_data = {}
+    local len = 0
+    local status = false
+    local Irq_en  = 0x00
+    local waitfor = 0x00
+    local last_bits,n,l
+    if command==rc522_authent then
+        Irq_en   = 0x12;		
+        waitfor = 0x10;		
+    elseif command==rc522_transceive then 
+        Irq_en   = 0x77;		
+        waitfor = 0x30;		
+    end
+    write_rawrc(0x02, bit.bor(Irq_en, 0x80))
+    rc522.clear_bit_mask(rc522_com_irq, 0x80 )
+    write_rawrc (rc522_com_mand, rc522_idle)	 
+    rc522.set_bit_mask (rc522_fifo_level, 0x80)	
+    for i=1,#data do
+        write_rawrc(rc522_fifo_data, data[i])
+    end
+    write_rawrc(rc522_com_mand,command )	
+    if ( command == rc522_transceive )then
+        rc522.set_bit_mask(rc522_bit_framing,0x80)
+    end
+    l = 12;
+    while true do
+        sys.wait(1)
+        n = read_rawrc(rc522_com_irq) 
+        l = l - 1
+        if  not ((l ~= 0) and (bit.band(n, 0x01) == 0) and (bit.band(n, waitfor) == 0)) then
+            break
+        end
+    end
+    rc522.clear_bit_mask(rc522_bit_framing, 0x80 )
+    if (l ~= 0)then 
+        if bit.band(read_rawrc(rc522_error), 0x1B) == 0x00 then
+            status = true
+            if bit.band(n,Irq_en,0x01)~=0then			
+                status = false
+            end   
+            if (command == rc522_transceive )then
+                n = read_rawrc(rc522_fifo_level)
+                last_bits = bit.band(read_rawrc(rc522_control),0x07)	
+                if last_bits ~= 0 then
+                    len = (n - 1) * 8 + last_bits  
+                else
+                    len = n * 8  
+                end
+                if n == 0 then	
+                    n = 1  
+                end  
+                for i=1, n do
+                    out_data [ i ] = read_rawrc(rc522_fifo_data)
+                end 
+            end
+        end   
+    else
+        status = false
+    end
+    rc522.set_bit_mask (rc522_control,0x80 )
+    write_rawrc(rc522_com_mand,rc522_idle )
+    return status,out_data,len 
+end
+
+--[[ 
+防冲撞
+@api rc522.anticoll(id)
+@string id 卡片序列号,4字节
+@return status uid 结果,uid
+@usage
+local status,uid = rc522.anticoll(array_id)
+]]
+function rc522.anticoll(id)
+    local check = 0
+    local uid
+    rc522.clear_bit_mask(rc522_status2,0x08)
+    write_rawrc( rc522_bit_framing, 0x00);
+    rc522.clear_bit_mask (rc522_coll, 0x80);			  
+    local status, back_data = rc522.command(rc522_transceive,{0x93,0x20})
+    if status == true then		            
+        for i=1,4 do
+            check = bit.bxor(check,back_data[i])
+        end
+        if check ~= back_data[5] then
+            status = false;
+        end   			
+        uid = string.char(table.unpack(back_data,1,4))	
+    end
+    rc522.clear_bit_mask( rc522_coll, 0x80 )
+    return status,uid;		
+end
+
+--[[ 
+crc计算
+@api calculate_crc(data)
+@table data 数据
+@return table crc值
+@usage
+local crc = calculate_crc(buff)
+]]
+local function calculate_crc(data)
+    local ret_data = {}
+    rc522.clear_bit_mask(rc522_div_irq, 0x04)
+    write_rawrc(rc522_com_mand, rc522_idle) 
+    rc522.set_bit_mask (rc522_fifo_level,0x80 ) 
+    for i=1,#data do
+        write_rawrc(rc522_fifo_data, data[i])
+    end
+    write_rawrc(rc522_com_mand, rc522_calccrc) 
+    local i = 0xFF
+    while true do
+        local n = read_rawrc(0x05)
+        i = i - 1
+        if not ((i ~= 0) and not (n&0x04)) then
+            break
+        end
+    end
+    ret_data[1] = read_rawrc(0x22)
+    ret_data[2] = read_rawrc(0x21)
+    return ret_data
+end
+
+--[[ 
+验证卡片密码
+@api authstate(mode, addr,key,uid )
+@number mode 模式
+@number addr 地址
+@string key 密码
+@string uid uid
+@return bool 结果
+@usage
+status = authstate(rc522_authent1b, addr,Key_B,uid )
+]]
+local function authstate( mode, addr,key,uid )
+    local buff = {}
+    buff[1] = mode
+    buff[2] = addr
+    for i=1,6 do
+        buff[i+2]=key:byte(i)
+    end
+    for i=1,4 do
+        buff[i+8]=uid:byte(i)
+    end
+    local status, back_data = rc522.command(rc522_authent,buff)
+    if status == true and (read_rawrc(rc522_status2)& 0x08) ~= 0 then
+        return true
+    end
+    return false	
+end
+
+--[[ 
+写数据到M1卡一块
+@api rc522.write(addr, data)
+@number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@table data 数据
+@return bool 结果
+@usage
+rc522.write(addr, data)
+]]
+function rc522.write(addr, data)
+    local buff = {}
+    buff[1] = rc522_write;
+    buff[2] = addr;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 4 and (back_data[1]& 0x0F)==0x0A then
+        local buf_w = {}
+        for i=0, 16 do
+            table.insert(buf_w, data[i])
+        end
+        local crc = calculate_crc(buf_w)
+        table.insert(buf_w, crc[1])
+        table.insert(buf_w, crc[2])
+        status, back_data, back_bits = rc522.command(rc522_transceive,buf_w)
+        if status == true and back_bits == 4 and (back_data[1]& 0x0F)==0x0A then
+            return status;
+        end
+    end
+    return status;		
+end
+
+--[[ 
+写数据到M1卡一块
+@api rc522.read(addr)
+@number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@return bool,string 结果,数据
+@usage
+rc522.read(addr, data)
+]]
+local function read(addr)
+    local buff = {}
+    buff[1] = rc522_read;
+    buff[2] = addr;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 0x90 then
+        local data = string.char(table.unpack(back_data,1,16))
+        return status,data
+    end
+    return false
+end
+
+--[[ 
+rc522 硬件版本
+@api rc522.version()
+@return number 硬件版本
+@usage
+rc522.version()
+]]
+function rc522.version()
+    return read_rawrc(rc522_version)
+end
+
+--[[ 
+rc522 命令卡片进入休眠状态
+@api rc522.halt()
+@return bool 结果
+@usage
+rc522.halt()
+]]
+function rc522.halt()
+    local buff = {}
+    buff[1] = rc522_halt;
+    buff[2] = 0;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status = rc522.command(rc522_transceive,buff)
+    return status
+end
+
+--[[ 
+rc522 复位
+@api rc522.reset()
+@usage
+rc522.reset()
+]]
+function rc522.reset()
+    rc522_rst(1)
+    rc522_rst(0)
+    rc522_rst(1)
+    write_rawrc(rc522_com_mand, 0x0f)
+    write_rawrc(rc522_mode, 0x3D)        
+    write_rawrc(rc522_tpreload_l, 30)       
+    write_rawrc(rc522_tpreload_h, 0)			
+    write_rawrc(rc522_tmode, 0x8D)			
+    write_rawrc(rc522_tprescaler, 0x3E)	
+    write_rawrc(rc522_tx_ayto, 0x40)		
+end
+
+--[[ 
+开启天线 
+@api rc522.antenna_on()
+@usage
+rc522.antenna_on()
+]]
+function rc522.antenna_on()
+    local uc = read_rawrc( rc522_tx_control )
+    if (( uc & 0x03 )==0 ) then
+        rc522.set_bit_mask(rc522_tx_control, 0x03)
+    end
+end
+
+--[[ 
+关闭天线 
+@api rc522.antenna_on()
+@usage
+rc522.antenna_on()
+]]
+function rc522.antenna_off()
+    rc522.clear_bit_mask( rc522_tx_control, 0x03 )
+end
+
+--[[ 
+设置rc522工作方式为ISO14443_A
+@api rc522_config_isotype()
+@usage
+rc522_config_isotype()
+]]
+local function rc522_config_isotype()
+    rc522.clear_bit_mask(rc522_status2, 0x08)
+    write_rawrc(rc522_mode, 0x3D)
+    write_rawrc(rc522_rx_sel, 0x86)
+    write_rawrc(rc522_rfcfg, 0x7F)
+    write_rawrc(rc522_tpreload_l, 30)
+    write_rawrc(rc522_tpreload_h, 0)
+    write_rawrc(rc522_tmode, 0x8D)
+    write_rawrc(rc522_tprescaler, 0x3E)
+    rc522.antenna_on()
+end
+
+--[[
+rc522 寻卡
+@api rc522.request(req_code)
+@number req_code rc522.reqidl 寻天线区内未进入休眠状态 rc522.reqall 寻天线区内全部卡
+@return bool tagtype 结果,卡类型 
+@usage
+status,array_id = rc522.request(rc522.reqall)
+]]
+function rc522.request(req_code)
+    rc522.clear_bit_mask(rc522_status2,0x08)
+    write_rawrc(rc522_bit_framing,0x07)
+    rc522.set_bit_mask(rc522_tx_control,0x03)
+    local tagtype
+    local status, back_data, back_bits = rc522.command(rc522_transceive,{req_code})
+    if status == true and back_bits == 0x10 then
+        tagtype = string.char(table.unpack(back_data,1,2))
+        return status, tagtype
+    end
+    return false
+end
+
+--[[
+选定卡片
+@api rc522.select(id)
+@number id 卡片序列号,4字节
+@return bool 结果 
+@usage
+status = rc522.select(id)
+]]
+function rc522.select(id)
+    local buff = {}
+    buff[1]=rc522_anticoll1
+    buff[2]=0x70
+    buff[7]=0
+    for i=1,4 do
+        buff[i+2]=id:byte(i)
+        buff[7]= bit.bxor(buff[7],id:byte(i))
+    end
+    local crc = calculate_crc(buff)
+    buff[8]=crc[1]
+    buff[9]=crc[2]
+    rc522.clear_bit_mask( rc522_status2, 0x08 )
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 0x18 then
+        return true
+    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 ~= 6 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
+
+--[[
+按照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 初始化
+@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
+
+function rc522.test()
+
+end
+
+return rc522
+
+
+