3 @summary rc522 非接触式读写卡驱动
6 @author Dozingfiretruck
8 --注意:因使用了sys.wait()所有api需要在协程中使用
10 local rc522 = require "rc522"
11 sys.taskInit(function()
12 spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,0)
13 rc522.init(0,pin.PB04,pin.PB01)
14 wdata = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
16 rc522.write_datablock(8,wdata)
18 local a,b = rc522.read_datablock(i)
20 print("read",i,b:toHex())
31 local sys
= require
"sys"
33 local rc522_spi
,rc522_rst
,rc522_irq
,rc522_cs
36 local rc522_idle
= 0x00 --取消当前命令
37 local rc522_authent
= 0x0E --验证密钥
38 local rc522_receive
= 0x08 --接收数据
39 local rc522_transmit
= 0x04 --发送数据
40 local rc522_transceive
= 0x0C --发送并接收数据
41 local rc522_resetphase
= 0x0F --复位
42 local rc522_calccrc
= 0x03 --CRC计算
45 rc522
.reqidl
= 0x26 --寻天线区内未进入休眠状态
46 rc522
.reqall
= 0x52 --寻天线区内全部卡
47 local rc522_anticoll1
= 0x93 --防冲撞
48 local rc522_anticoll2
= 0x95 --防冲撞
49 local rc522_authent1a
= 0x60 --验证A密钥
50 local rc522_authent1b
= 0x61 --验证B密钥
51 local rc522_read
= 0x30 --读块
52 local rc522_write
= 0xA0 --写块
53 local rc522_decrement
= 0xC0 --扣款
54 local rc522_increment
= 0xC1 --充值
55 local rc522_restore
= 0xC2 --调块数据到缓冲区
56 local rc522_transfer
= 0xB0 --保存缓冲区中数据
57 local rc522_halt
= 0x50 --休眠
61 local rc522_rfu00
= 0x00 --保留为将来之用
62 local rc522_com_mand
= 0x01 --启动和停止命令的执行
63 local rc522_com_ie
= 0x02 --中断请求传递的使能和禁能控制位
64 local rc522_divl_en
= 0x03 --中断请求传递的使能和禁能控制位
65 local rc522_com_irq
= 0x04 --包含中断请求标志
66 local rc522_div_irq
= 0x05 --包含中断请求标志
67 local rc522_error
= 0x06 --错误标志,指示执行的上个命令的错误状态
68 local rc522_status1
= 0x07 --包含通信的状态标志
69 local rc522_status2
= 0x08 --包含接收器和发送器的状态标志
70 local rc522_fifo_data
= 0x09 --64 字节 FIFO 缓冲区的输入和输出
71 local rc522_fifo_level
= 0x0A --指示 FIFO 中存储的字节数
72 local rc522_water_level
= 0x0B --定义 FIFO 下溢和上溢报警的 FIFO 深度
73 local rc522_control
= 0x0C --不同的控制寄存器
74 local rc522_bit_framing
= 0x0D --面向位的帧的调节
75 local rc522_coll
= 0x0E --RF 接口上检测到的第一个位冲突的位的位置
76 local rc522_rfu0f
= 0x0F --保留为将来之用
78 local RFU10
= 0x10 --保留为将来之用
79 local rc522_mode
= 0x11 --定义发送和接收的常用模式
80 local rc522_tx_mode
= 0x12 --定义发送过程的数据传输速率
81 local rc522_rx_mode
= 0x13 --定义接收过程中的数据传输速率
82 local rc522_tx_control
= 0x14 --控制天线驱动器管脚 TX1 和 TX2 的逻辑特性
83 local rc522_tx_ayto
= 0x15 --控制天线驱动器的设置
84 local rc522_tx_sel
= 0x16 --选择天线驱动器的内部源
85 local rc522_rx_sel
= 0x17 --选择内部的接收器设置
86 local rc522_rx_threshold
= 0x18 --选择位译码器的阈值
87 local rc522_demod
= 0x19 --定义解调器的设置
88 local rc522_rfu1a
= 0x1A --保留为将来之用
89 local rc522_rfu1b
= 0x1B --保留为将来之用
90 local rc522_mifare
= 0x1C --控制 ISO 14443/MIFARE 模式中 106kbit/s 的通信
91 local rc522_rfu1d
= 0x1D --保留为将来之用
92 local rc522_rfu1e
= 0x1E --保留为将来之用
93 local rc522_serial_speed
= 0x1F --选择串行 UART 接口的速率
95 local rc522_rfu20
= 0x20 --保留为将来之用
96 local rc522_crcresult_m
= 0x21 --显示 CRC 计算的实际 MSB 值
97 local rc522_crcresult_l
= 0x22 --显示 CRC 计算的实际 LSB 值
98 local rc522_rfu23
= 0x23 --保留为将来之用
99 local rc522_mod_width
= 0x24 --控制 ModWidth 的设置
100 local rc522_rfu25
= 0x25 --保留为将来之用
101 local rc522_rfcfg
= 0x26 --配置接收器增益
102 local rc522_gsn
= 0x27 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
103 local rc522_cwgscfg
= 0x28 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
104 local rc522_modgscfg
= 0x29 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
105 local rc522_tmode
= 0x2A --定义内部定时器的设置
106 local rc522_tprescaler
= 0x2B --定义内部定时器的设置
107 local rc522_tpreload_h
= 0x2C --描述 16 位长的定时器重装值
108 local rc522_tpreload_l
= 0x2D --描述 16 位长的定时器重装值
109 local rc522_tcounter_value_h
= 0x2E --描述 16 位长的定时器重装值
110 local rc522_tcounter_value_l
= 0x2F --描述 16 位长的定时器重装值
112 local rc522_rfu30
= 0x30 --保留为将来之用
113 local rc522_testsel1
= 0x31 --常用测试信号的配置
114 local rc522_testsel2
= 0x32 --常用测试信号的配置和 PRBS 控制
115 local rc522_testpin_en
= 0x33 --D1-D7 输出驱动器的使能管脚(注:仅用于串行接口)
116 local rc522_testpin_value
= 0x34 --定义 D1-D7 用作 I/O 总线时的值
117 local rc522_testbus
= 0x35 --显示内部测试总线的状态
118 local rc522_autotest
= 0x36 --控制数字自测试
119 local rc522_version
= 0x37 --显示版本
120 local rc522_analogtest
= 0x38 --控制管脚 AUX1 和 AUX2
121 local rc522_testadc1
= 0x39 --定义 TestDAC1 的测试值
122 local rc522_testadc2
= 0x3A --定义 TestDAC2 的测试值
123 local rc522_testadc
= 0x3B --显示 ADC I 和 Q 通道的实际值
124 local rc522_rfu3c
= 0x3C --保留用于产品测试
125 local rc522_rfu3d
= 0x3D --保留用于产品测试
126 local rc522_rfu3e
= 0x3E --保留用于产品测试
127 local rc522_rfu3f
= 0x3F --保留用于产品测试
129 local Key_A
= string.char(0xff,0xff,0xff,0xff,0xff,0xff)
130 local Key_B
= string.char(0xff,0xff,0xff,0xff,0xff,0xff)
134 @api rc522.set_bit_mask(address, value)
138 write_rawrc(rc522_bit_framing,0x07)
140 local function write_rawrc(address
, value
)
142 local data
= string.char((address
<<1)&0x7E) .. string.char(value
)
143 spi
.send(rc522_spi
, data
)
144 -- rc522_spi:send(data)
150 @api rc522.read_rawrc(address)
154 local n = read_rawrc(rc522_com_irq)
156 local function read_rawrc(address
)
158 local data
= string.char(((address
<<1)&0x7E)|
0x80)
159 spi
.send(rc522_spi
, data
)
160 local val
= spi
.recv(rc522_spi
,1)
161 -- rc522_spi:send(data)
162 -- local val = rc522_spi:recv(1)
164 return string.byte(val
)
169 @api rc522.set_bit_mask(address, mask)
173 rc522.set_bit_mask (rc522_fifo_level, 0x80)
175 function rc522
.set_bit_mask(address
, mask
)
176 local current
= read_rawrc(address
)
177 write_rawrc(address
, bit
.bor(current
, mask
))
182 @api rc522.clear_bit_mask(address, mask)
186 rc522.clear_bit_mask(rc522_com_irq, 0x80 )
188 function rc522
.clear_bit_mask(address
, mask
)
189 local current
= read_rawrc(address
)
190 write_rawrc(address
, bit
.band(current
, bit
.bnot(mask
)))
195 @api rc522.command(command,data)
198 @return status data len 结果,返回数据,收到的位长度
202 function rc522
.command(command
,data
)
209 if command
==rc522_authent
then
212 elseif command
==rc522_transceive
then
216 write_rawrc(0x02, bit
.bor(Irq_en
, 0x80))
217 rc522
.clear_bit_mask(rc522_com_irq
, 0x80 )
218 write_rawrc (rc522_com_mand
, rc522_idle
)
219 rc522
.set_bit_mask (rc522_fifo_level
, 0x80)
221 write_rawrc(rc522_fifo_data
, data
[i
])
223 write_rawrc(rc522_com_mand
,command
)
224 if ( command
== rc522_transceive
)then
225 rc522
.set_bit_mask(rc522_bit_framing
,0x80)
230 n
= read_rawrc(rc522_com_irq
)
232 if not ((l
~= 0) and (bit
.band(n
, 0x01) == 0) and (bit
.band(n
, waitfor
) == 0)) then
236 rc522
.clear_bit_mask(rc522_bit_framing
, 0x80 )
238 if bit
.band(read_rawrc(rc522_error
), 0x1B) == 0x00 then
240 if bit
.band(n
,Irq_en
,0x01)~=0then
243 if (command
== rc522_transceive
)then
244 n
= read_rawrc(rc522_fifo_level
)
245 last_bits
= bit
.band(read_rawrc(rc522_control
),0x07)
246 if last_bits
~= 0 then
247 len
= (n
- 1) * 8 + last_bits
255 out_data
[ i
] = read_rawrc(rc522_fifo_data
)
262 rc522
.set_bit_mask (rc522_control
,0x80 )
263 write_rawrc(rc522_com_mand
,rc522_idle
)
264 return status
,out_data
,len
269 @api rc522.anticoll(id)
271 @return status uid 结果,uid
273 local status,uid = rc522.anticoll(array_id)
275 function rc522
.anticoll(id
)
278 rc522
.clear_bit_mask(rc522_status2
,0x08)
279 write_rawrc( rc522_bit_framing
, 0x00);
280 rc522
.clear_bit_mask (rc522_coll
, 0x80);
281 local status
, back_data
= rc522
.command(rc522_transceive
,{0x93,0x20})
282 if back_data
and #back_data
>= 5 then
284 check
= bit
.bxor(check
,back_data
[i
])
286 if check
~= back_data
[5] then
289 uid
= string.char(table.unpack(back_data
,1,4))
291 rc522
.clear_bit_mask( rc522_coll
, 0x80 )
297 @api calculate_crc(data)
301 local crc = calculate_crc(buff)
303 local function calculate_crc(data
)
305 rc522
.clear_bit_mask(rc522_div_irq
, 0x04)
306 write_rawrc(rc522_com_mand
, rc522_idle
)
307 rc522
.set_bit_mask (rc522_fifo_level
,0x80 )
309 write_rawrc(rc522_fifo_data
, data
[i
])
311 write_rawrc(rc522_com_mand
, rc522_calccrc
)
314 local n
= read_rawrc(0x05)
316 if not ((i
~= 0) and not (n
&0x04)) then
320 ret_data
[1] = read_rawrc(0x22)
321 ret_data
[2] = read_rawrc(0x21)
327 @api authstate(mode, addr,key,uid )
334 status = authstate(rc522_authent1b, addr,Key_B,uid )
336 local function authstate( mode
, addr
,key
,uid
)
341 buff
[i
+2]=key
:byte(i
)
344 buff
[i
+8]=uid
:byte(i
)
346 local status
, back_data
= rc522
.command(rc522_authent
,buff
)
347 if status
== true and (read_rawrc(rc522_status2
)& 0x08) ~= 0 then
355 @api rc522.write(addr, data)
356 @number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
360 rc522.write(addr, data)
362 function rc522
.write(addr
, data
)
364 buff
[1] = rc522_write
;
366 local crc
= calculate_crc(buff
)
369 local status
, back_data
, back_bits
= rc522
.command(rc522_transceive
,buff
)
370 if status
== true and back_bits
== 4 and (back_data
[1]& 0x0F)==0x0A then
373 table.insert(buf_w
, data
[i
])
375 local crc
= calculate_crc(buf_w
)
376 table.insert(buf_w
, crc
[1])
377 table.insert(buf_w
, crc
[2])
378 status
, back_data
, back_bits
= rc522
.command(rc522_transceive
,buf_w
)
379 if status
== true and back_bits
== 4 and (back_data
[1]& 0x0F)==0x0A then
388 @api rc522.read(addr)
389 @number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
390 @return bool,string 结果,数据
392 rc522.read(addr, data)
394 local function read(addr
)
396 buff
[1] = rc522_read
;
398 local crc
= calculate_crc(buff
)
401 local status
, back_data
, back_bits
= rc522
.command(rc522_transceive
,buff
)
402 if status
== true and back_bits
== 0x90 then
403 local data
= string.char(table.unpack(back_data
,1,16))
416 function rc522
.version()
417 return read_rawrc(rc522_version
)
427 function rc522
.halt()
429 buff
[1] = rc522_halt
;
431 local crc
= calculate_crc(buff
)
434 local status
= rc522
.command(rc522_transceive
,buff
)
444 function rc522
.reset()
448 write_rawrc(rc522_com_mand
, 0x0f)
449 write_rawrc(rc522_mode
, 0x3D)
450 write_rawrc(rc522_tpreload_l
, 30)
451 write_rawrc(rc522_tpreload_h
, 0)
452 write_rawrc(rc522_tmode
, 0x8D)
453 write_rawrc(rc522_tprescaler
, 0x3E)
454 write_rawrc(rc522_tx_ayto
, 0x40)
459 @api rc522.antenna_on()
463 function rc522
.antenna_on()
464 local uc
= read_rawrc( rc522_tx_control
)
465 if (( uc
& 0x03 )==0 ) then
466 rc522
.set_bit_mask(rc522_tx_control
, 0x03)
472 @api rc522.antenna_on()
476 function rc522
.antenna_off()
477 rc522
.clear_bit_mask( rc522_tx_control
, 0x03 )
481 设置rc522工作方式为ISO14443_A
482 @api rc522_config_isotype()
484 rc522_config_isotype()
486 local function rc522_config_isotype()
487 rc522
.clear_bit_mask(rc522_status2
, 0x08)
488 write_rawrc(rc522_mode
, 0x3D)
489 write_rawrc(rc522_rx_sel
, 0x86)
490 write_rawrc(rc522_rfcfg
, 0x7F)
491 write_rawrc(rc522_tpreload_l
, 30)
492 write_rawrc(rc522_tpreload_h
, 0)
493 write_rawrc(rc522_tmode
, 0x8D)
494 write_rawrc(rc522_tprescaler
, 0x3E)
500 @api rc522.request(req_code)
501 @number req_code rc522.reqidl 寻天线区内未进入休眠状态 rc522.reqall 寻天线区内全部卡
502 @return bool tagtype 结果,卡类型
504 status,array_id = rc522.request(rc522.reqall)
506 function rc522
.request(req_code
)
507 rc522
.clear_bit_mask(rc522_status2
,0x08)
508 write_rawrc(rc522_bit_framing
,0x07)
509 rc522
.set_bit_mask(rc522_tx_control
,0x03)
511 local status
, back_data
, back_bits
= rc522
.command(rc522_transceive
,{req_code
})
512 if status
== true and back_bits
== 0x10 then
513 tagtype
= string.char(table.unpack(back_data
,1,2))
514 return status
, tagtype
521 @api rc522.select(id)
525 status = rc522.select(id)
527 function rc522
.select(id
)
532 buff
[1]=rc522_anticoll1
537 buff
[7]= bit
.bxor(buff
[7],id
:byte(i
))
539 local crc
= calculate_crc(buff
)
542 rc522
.clear_bit_mask( rc522_status2
, 0x08 )
543 local status
, back_data
, back_bits
= rc522
.command(rc522_transceive
,buff
)
544 if status
== true and back_bits
== 0x18 then
551 按照rc522操作流程写入16字节数据到块
552 @api rc522.write_datablock(addr,data)
553 @number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
554 @table data 指向要写入的数据,必须为16个字符
557 rc522.write_datablock(addr,data)
559 function rc522
.write_datablock(addr
,data
)
563 local status
,array_id
= rc522
.request(rc522
.reqall
)
564 if status
~= true then
565 status
,array_id
= rc522
.request(rc522
.reqall
)
567 if status
== true then
568 local status
,uid
= rc522
.anticoll(array_id
)
572 if status
== true and uid
then
574 status
= authstate( rc522_authent1b
, addr
,Key_B
,uid
)
575 if status
== true then
576 status
= rc522
.write(addr
,data
)
587 @api rc522.read_datablock(addr)
588 @number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
589 @return bool string 结果 数据
592 local a,b = rc522.read_datablock(i)
594 print("read",i,b:toHex())
598 function rc522
.read_datablock(addr
)
599 local status
,array_id
= rc522
.request(rc522
.reqall
)
600 if status
~= true then
601 status
,array_id
= rc522
.request(rc522
.reqall
)
603 if status
== true then
604 local status
,uid
= rc522
.anticoll(array_id
)
605 if status
== true and uid
then
607 status
= authstate( rc522_authent1b
, addr
,Key_B
,uid
)
608 if status
== true then
609 local status
,data
= read(addr
)
610 if status
== true then
622 @api rc522.init(spi_id, cs, rst)
623 @number spi_id spi端口号
628 spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
629 rc522.init(0,pin.PB04,pin.PB01)
631 function rc522
.init(spi_id
,cs
,rst
)
633 rc522_cs
= gpio
.setup(cs
, 0, gpio
.PULLUP
)
635 rc522_rst
= gpio
.setup(rst
, 0, gpio
.PULLUP
)
638 rc522_config_isotype()
639 log.debug("rc522.version",rc522
.version())
643 function rc522
.test()