remove: 移除多余的mind目录
[LuatOS.git] / script / libs / rc522.lua
blob34aa33a1b05a408e427accd860e2d1b999780895
1 --[[
2 @module rc522
3 @summary rc522 非接触式读写卡驱动
4 @version 1.0
5 @date 2022.06.14
6 @author Dozingfiretruck
7 @usage
8 --注意:因使用了sys.wait()所有api需要在协程中使用
9 -- 用法实例
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}
15 while 1 do
16 rc522.write_datablock(8,wdata)
17 for i=0,63 do
18 local a,b = rc522.read_datablock(i)
19 if a then
20 print("read",i,b:toHex())
21 end
22 end
23 sys.wait(500)
24 end
25 end)
29 local rc522 = {}
31 local sys = require "sys"
33 local rc522_spi,rc522_rst,rc522_irq,rc522_cs
35 ---器件所用地址
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计算
44 --Mifare_One卡片命令字
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 --休眠
59 --MF522寄存器定义
60 -- PAGE 0
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 --保留为将来之用
77 -- PAGE 1
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 接口的速率
94 -- PAGE 2
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 位长的定时器重装值
111 -- PAGE 3
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)
132 --[[
133 写rc522寄存器
134 @api rc522.set_bit_mask(address, value)
135 @number address 地址
136 @number value 值
137 @usage
138 write_rawrc(rc522_bit_framing,0x07)
140 local function write_rawrc(address, value)
141 rc522_cs(0)
142 local data = string.char((address<<1)&0x7E) .. string.char(value)
143 spi.send(rc522_spi, data)
144 -- rc522_spi:send(data)
145 rc522_cs(1)
148 --[[
149 读rc522寄存器
150 @api rc522.read_rawrc(address)
151 @number address 地址
152 @return number 寄存器值
153 @usage
154 local n = read_rawrc(rc522_com_irq)
156 local function read_rawrc(address)
157 rc522_cs(0)
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)
163 rc522_cs(1)
164 return string.byte(val)
167 --[[
168 对rc522寄存器置位
169 @api rc522.set_bit_mask(address, mask)
170 @number address 地址
171 @number mask 置位值
172 @usage
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))
180 --[[
181 对rc522寄存器清位
182 @api rc522.clear_bit_mask(address, mask)
183 @number address 地址
184 @number mask 清位值
185 @usage
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)))
193 --[[
194 命令通讯
195 @api rc522.command(command,data)
196 @number command
197 @number data
198 @return status data len 结果,返回数据,收到的位长度
199 @usage
200 rc522.version()
202 function rc522.command(command,data)
203 local out_data = {}
204 local len = 0
205 local status = false
206 local Irq_en = 0x00
207 local waitfor = 0x00
208 local last_bits,n,l
209 if command==rc522_authent then
210 Irq_en = 0x12;
211 waitfor = 0x10;
212 elseif command==rc522_transceive then
213 Irq_en = 0x77;
214 waitfor = 0x30;
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)
220 for i=1,#data do
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)
227 l = 12;
228 while true do
229 sys.wait(1)
230 n = read_rawrc(rc522_com_irq)
231 l = l - 1
232 if not ((l ~= 0) and (bit.band(n, 0x01) == 0) and (bit.band(n, waitfor) == 0)) then
233 break
236 rc522.clear_bit_mask(rc522_bit_framing, 0x80 )
237 if (l ~= 0)then
238 if bit.band(read_rawrc(rc522_error), 0x1B) == 0x00 then
239 status = true
240 if bit.band(n,Irq_en,0x01)~=0then
241 status = false
242 end
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
248 else
249 len = n * 8
251 if n == 0 then
252 n = 1
253 end
254 for i=1, n do
255 out_data [ i ] = read_rawrc(rc522_fifo_data)
256 end
258 end
259 else
260 status = false
262 rc522.set_bit_mask (rc522_control,0x80 )
263 write_rawrc(rc522_com_mand,rc522_idle )
264 return status,out_data,len
267 --[[
268 防冲撞
269 @api rc522.anticoll(id)
270 @string id 卡片序列号,4字节
271 @return status uid 结果,uid
272 @usage
273 local status,uid = rc522.anticoll(array_id)
275 function rc522.anticoll(id)
276 local check = 0
277 local uid
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
283 for i=1,4 do
284 check = bit.bxor(check,back_data[i])
286 if check ~= back_data[5] then
287 status = false;
288 end
289 uid = string.char(table.unpack(back_data,1,4))
291 rc522.clear_bit_mask( rc522_coll, 0x80 )
292 return status,uid;
295 --[[
296 crc计算
297 @api calculate_crc(data)
298 @table data 数据
299 @return table crc值
300 @usage
301 local crc = calculate_crc(buff)
303 local function calculate_crc(data)
304 local ret_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 )
308 for i=1,#data do
309 write_rawrc(rc522_fifo_data, data[i])
311 write_rawrc(rc522_com_mand, rc522_calccrc)
312 local i = 0xFF
313 while true do
314 local n = read_rawrc(0x05)
315 i = i - 1
316 if not ((i ~= 0) and not (n&0x04)) then
317 break
320 ret_data[1] = read_rawrc(0x22)
321 ret_data[2] = read_rawrc(0x21)
322 return ret_data
325 --[[
326 验证卡片密码
327 @api authstate(mode, addr,key,uid )
328 @number mode 模式
329 @number addr 地址
330 @string key 密码
331 @string uid uid
332 @return bool 结果
333 @usage
334 status = authstate(rc522_authent1b, addr,Key_B,uid )
336 local function authstate( mode, addr,key,uid )
337 local buff = {}
338 buff[1] = mode
339 buff[2] = addr
340 for i=1,6 do
341 buff[i+2]=key:byte(i)
343 for i=1,4 do
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
348 return true
350 return false
353 --[[
354 写数据到M1卡一块
355 @api rc522.write(addr, data)
356 @number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
357 @table data 数据
358 @return bool 结果
359 @usage
360 rc522.write(addr, data)
362 function rc522.write(addr, data)
363 local buff = {}
364 buff[1] = rc522_write;
365 buff[2] = addr;
366 local crc = calculate_crc(buff)
367 buff[3] = crc[1]
368 buff[4] = crc[2]
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
371 local buf_w = {}
372 for i=0, 16 do
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
380 return status;
383 return status;
386 --[[
387 写数据到M1卡一块
388 @api rc522.read(addr)
389 @number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
390 @return bool,string 结果,数据
391 @usage
392 rc522.read(addr, data)
394 local function read(addr)
395 local buff = {}
396 buff[1] = rc522_read;
397 buff[2] = addr;
398 local crc = calculate_crc(buff)
399 buff[3] = crc[1]
400 buff[4] = crc[2]
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))
404 return status,data
406 return false
409 --[[
410 rc522 硬件版本
411 @api rc522.version()
412 @return number 硬件版本
413 @usage
414 rc522.version()
416 function rc522.version()
417 return read_rawrc(rc522_version)
420 --[[
421 rc522 命令卡片进入休眠状态
422 @api rc522.halt()
423 @return bool 结果
424 @usage
425 rc522.halt()
427 function rc522.halt()
428 local buff = {}
429 buff[1] = rc522_halt;
430 buff[2] = 0;
431 local crc = calculate_crc(buff)
432 buff[3] = crc[1]
433 buff[4] = crc[2]
434 local status = rc522.command(rc522_transceive,buff)
435 return status
438 --[[
439 rc522 复位
440 @api rc522.reset()
441 @usage
442 rc522.reset()
444 function rc522.reset()
445 rc522_rst(1)
446 rc522_rst(0)
447 rc522_rst(1)
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)
457 --[[
458 开启天线
459 @api rc522.antenna_on()
460 @usage
461 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)
470 --[[
471 关闭天线
472 @api rc522.antenna_on()
473 @usage
474 rc522.antenna_on()
476 function rc522.antenna_off()
477 rc522.clear_bit_mask( rc522_tx_control, 0x03 )
480 --[[
481 设置rc522工作方式为ISO14443_A
482 @api rc522_config_isotype()
483 @usage
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)
495 rc522.antenna_on()
498 --[[
499 rc522 寻卡
500 @api rc522.request(req_code)
501 @number req_code rc522.reqidl 寻天线区内未进入休眠状态 rc522.reqall 寻天线区内全部卡
502 @return bool tagtype 结果,卡类型
503 @usage
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)
510 local tagtype
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
516 return false
519 --[[
520 选定卡片
521 @api rc522.select(id)
522 @number id 卡片序列号,4字节
523 @return bool 结果
524 @usage
525 status = rc522.select(id)
527 function rc522.select(id)
528 if not id then
529 return false
531 local buff = {}
532 buff[1]=rc522_anticoll1
533 buff[2]=0x70
534 buff[7]=0
535 for i=1,4 do
536 buff[i+2]=id:byte(i)
537 buff[7]= bit.bxor(buff[7],id:byte(i))
539 local crc = calculate_crc(buff)
540 buff[8]=crc[1]
541 buff[9]=crc[2]
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
545 return true
547 return false
550 --[[
551 按照rc522操作流程写入16字节数据到块
552 @api rc522.write_datablock(addr,data)
553 @number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
554 @table data 指向要写入的数据,必须为16个字符
555 @return bool 结果
556 @usage
557 rc522.write_datablock(addr,data)
559 function rc522.write_datablock(addr,data)
560 if #data ~= 16 then
561 return false
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)
569 if not uid then
570 return false
572 if status == true and uid then
573 rc522.select(uid)
574 status = authstate( rc522_authent1b, addr,Key_B,uid )
575 if status == true then
576 status = rc522.write(addr,data)
577 rc522.halt()
578 return status
582 return false
585 --[[
586 按照rc522操作流程读取块
587 @api rc522.read_datablock(addr)
588 @number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
589 @return bool string 结果 数据
590 @usage
591 for i=0,63 do
592 local a,b = rc522.read_datablock(i)
593 if a then
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
606 rc522.select(uid)
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
611 return true, data
613 rc522.halt()
617 return false
620 --[[
621 rc522 初始化
622 @api rc522.init(spi_id, cs, rst)
623 @number spi_id spi端口号
624 @number cs cs引脚
625 @number rst rst引脚
626 @return bool 初始化结果
627 @usage
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)
632 rc522_spi = spi_id
633 rc522_cs = gpio.setup(cs, 0, gpio.PULLUP)
634 rc522_cs(1)
635 rc522_rst = gpio.setup(rst, 0, gpio.PULLUP)
636 rc522_rst(1)
637 rc522.reset()
638 rc522_config_isotype()
639 log.debug("rc522.version",rc522.version())
640 return true
643 function rc522.test()
647 return rc522