RC522模塊不但可以讀取標(biāo)簽中的數(shù)據(jù),還能將數(shù)據(jù)寫入標(biāo)簽中,本篇介紹S50卡的寫卡操作。
1
S50卡介紹
S50非接觸式IC卡的容量為1K字節(jié)EEPROM,又稱M1卡。內(nèi)部EEPROM又分為16個(gè)扇區(qū),每個(gè)扇區(qū)分4個(gè)塊,以塊為存取單位,每個(gè)塊由16個(gè)字節(jié)組成。
1.M1卡主要指標(biāo)
- 每個(gè)扇區(qū)有獨(dú)立的一組密碼和訪問(wèn)控制。
- 每張卡有唯一32位序列號(hào)。
- 無(wú)電源,自帶天線,內(nèi)含加密控制邏輯和通訊邏輯電路。
- 數(shù)據(jù)保存期為10年,可改寫10萬(wàn)次,讀無(wú)限次
- 工作頻率:13.56MHZ
- 通信速率:106 KBPS
- 工作溫度:-20℃~50℃(濕度為90%)
2.M1卡存儲(chǔ)結(jié)構(gòu)
存儲(chǔ)結(jié)構(gòu)如下圖,16個(gè)扇區(qū),每個(gè)扇區(qū)4個(gè)塊,可將16個(gè)扇區(qū)的64個(gè)塊按絕對(duì)地址編號(hào)0-63。
M1卡存儲(chǔ)結(jié)構(gòu)
其中第0扇區(qū)的塊0,用于存放廠商代碼,一般前四字節(jié)為UID,已經(jīng)固化,一般不可更改。
每個(gè)扇區(qū)的塊0、塊1、塊2為數(shù)據(jù)塊,可用于存儲(chǔ)數(shù)據(jù),塊3為控制塊,包括了密碼A,存取控制,密碼B。
控制塊
3.讀寫流程
每個(gè)扇區(qū)的密碼和存取控制都是獨(dú)立的,可根據(jù)實(shí)際需要設(shè)定各自的密碼及存取控制。出廠默認(rèn)的密碼6個(gè)字節(jié)都為0xFF。
扇區(qū)中每個(gè)塊的存取條件是由密碼和存取控制共同決定的,每個(gè)塊有相應(yīng)的三個(gè)控制位,按照一定規(guī)則進(jìn)行約束,具體可以參照M1卡數(shù)據(jù)手冊(cè)。
本篇演示向扇區(qū)1的塊0,絕對(duì)地址為塊4中寫入數(shù)據(jù)。主要流程為:模塊進(jìn)行卡掃描讀取卡片信息,通過(guò)密碼進(jìn)行身份認(rèn)證,然后讀取寫入前的塊數(shù)據(jù),然后再次進(jìn)行身份認(rèn)證并寫入自定義數(shù)據(jù),然后再次身份認(rèn)證讀取寫入后的塊數(shù)據(jù)來(lái)檢測(cè)是否寫入成功。
2
實(shí)驗(yàn)材料
3
實(shí)驗(yàn)材料
1. 根據(jù)原理圖搭建電路圖。
RC522模塊的3.3V、GND分別對(duì)應(yīng)連接開(kāi)發(fā)板的3.3V、GND,模塊的MOSI、MISO、SCK分別連接開(kāi)發(fā)板的SPI接口11、12、13,模塊的SDA、RST分別連接開(kāi)發(fā)板數(shù)字管腳10、9。
實(shí)驗(yàn)原理圖如下圖所示:
實(shí)驗(yàn)原理圖
2. 代碼較長(zhǎng),部分截取如下,全部代碼文末獲取。
1...
2 // 使用密碼A進(jìn)行身份認(rèn)證
3 Serial.println(F("使用密碼A進(jìn)行身份認(rèn)證..."));
4 status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
5 if (status != MFRC522::STATUS_OK) {
6 Serial.print(F("身份認(rèn)證失敗 "));
7 Serial.println(mfrc522.GetStatusCodeName(status));
8 return;
9 }
10
11 // 顯示當(dāng)前扇區(qū)數(shù)據(jù)
12 Serial.println(F("當(dāng)前扇區(qū)數(shù)據(jù):"));
13 mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
14 Serial.println();
15
16 // 讀取寫入前塊數(shù)據(jù)
17 Serial.print(F("讀取寫入前塊")); Serial.print(blockAddr);
18 Serial.println(F("數(shù)據(jù)..."));
19 status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
20 if (status != MFRC522::STATUS_OK) {
21 Serial.print(F("讀取失敗 "));
22 Serial.println(mfrc522.GetStatusCodeName(status));
23 }
24 Serial.print(F("塊")); Serial.print(blockAddr); Serial.println(F("數(shù)據(jù):"));
25 dump_byte_array(buffer, 16); Serial.println();
26 Serial.println();
27
28 // 使用密碼B進(jìn)行身份認(rèn)證
29 Serial.println(F("使用密碼B進(jìn)行身份認(rèn)證..."));
30 status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
31 if (status != MFRC522::STATUS_OK) {
32 Serial.print(F("身份認(rèn)證失敗 "));
33 Serial.println(mfrc522.GetStatusCodeName(status));
34 return;
35 }
36
37 //寫入數(shù)據(jù)
38 Serial.print(F("寫數(shù)據(jù)到塊")); Serial.print(blockAddr);
39 Serial.println(F("..."));
40 dump_byte_array(dataBlock, 16); Serial.println();
41 status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
42 if (status != MFRC522::STATUS_OK) {
43 Serial.print(F("寫入失敗 "));
44 Serial.println(mfrc522.GetStatusCodeName(status));
45 }
46 Serial.println();
47
48 //讀取寫入后塊數(shù)據(jù)
49 Serial.print(F("讀取寫入后塊")); Serial.print(blockAddr);
50 Serial.println(F("數(shù)據(jù)..."));
51 status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
52 if (status != MFRC522::STATUS_OK) {
53 Serial.print(F("讀取失敗 "));
54 Serial.println(mfrc522.GetStatusCodeName(status));
55 }
56 Serial.print(F("塊")); Serial.print(blockAddr); Serial.