Arduino Uno 搭配 RFID-RC522上手:读取卡号,写入数据、读取数据
简介
单片机:Arduino Uno
额外库:MFRC522(可直接在库管理器下载)
S50 IC卡 采用NXP MF1 IC S50制作的非接触智能卡,通常简称S50卡或Mifare 1K,符合ISO14443A标准;存储容量:8Kbit,16个分区,每分区两组密码。
枯叶笑与东方大叔的IC卡小结
分类 IC - ID
市场上常用的卡片就两种,IC卡和ID卡,这两者的区别就是IC卡有存储芯片(如M1,UID,CUID,FUID,UFUID),而 ID卡只是一个卡号( 全称为身份识别卡,是一种不可写入的感应卡,含固定的编号.卡号在封卡前写入后不可再更改)。CPU卡因为价格太高,没有推广起来
IC卡的芯片,目前市场上常用的有两种,一种是价格较高的飞利浦原装芯片,一种是上海复旦芯片;原装飞利浦芯片IC卡,市场拿货价不超过3元,例如公交卡,国产芯片IC卡,价格几毛钱,常用于电梯、停车场、食堂就餐、水卡
IC卡和ID卡都可以用于一卡通系统,各有优缺点:
ID卡,因为只是ID号,没有内置存储芯片,因此,当ID卡用于一卡通系统时,必须要电脑开着,因为,你消费扣款或充值,都是从电脑数据库里加加减减,这类似于磁条性质的银行卡,卡片本身没有钱,你取钱存钱,其实都是在银行数据库里加减
- 优点:因为是从电脑数据库里直接加减,因此,充值或取款,卡片无需到场,刷卡数据实时传输到电脑
- 缺点:电脑坏了或通讯有问题,整套系统都瘫痪(脱机消费模式也行,这里不具体讲)
IC卡,常用的公交卡、地铁卡都是IC卡,内置芯片,0-15 共16个扇区,可以写入数据
- 优点:因为钱是直接存储在卡里面,因此,消费时,无需联网,跟电脑无关,直接从卡里面扣钱
- 缺点:充值时,卡片必须到场 (省事的方法,补贴机之类),刷卡数据暂时储存在刷卡机里,待电脑开机后,采集消费数据到电脑
IC细分类
M1 卡
普通IC卡,0扇区不可以修改,其他扇区可反复擦写,我们使用的电梯卡、门禁卡等智能卡发卡商所使用的都是 M1 卡,可以理解为物业发的原卡。
UID 卡
普通复制卡,可以重复擦写所有扇区,主要应用在IC卡复制上,遇到带有防火墙的读卡器就会失效。
CUID 卡
可擦写防屏蔽卡,可以重复擦写所有扇区,UID卡复制无效的情况下使用,可以绕过防火墙。
(防屏蔽就是防止某些设备里面有检测机制能够检查出卡片是否为复制卡,cuid卡比较常用,需要注意第二次使用需要格式化,还有说明一下 0扇区就是机器与卡片的桥梁用来存放对应信息。)
FUID 卡
不可擦写防屏蔽卡,此卡的特点0扇区只能写入一次,写入一次变成 M1 卡,CUID 复制没用的情况下使用,可以绕过防火墙。
UFUID 卡
高级复制卡,我们就理解为是 UID 和 FUID 的合成卡,需要封卡操作,不封卡就是 UID 卡,封卡后就变为 M1 卡。
工具
ACR122
使用最多的读卡器,很流行,大抵是因为网络上流传了非常强大的GUI改卡读卡复制卡软件吧。Proxmark3
国外的开源硬件,由FPGA驱动。性能十分强大,集嗅探、读取、克隆于一体,IC卡和ID卡通杀。PN532
由NXP出品,是一款高度集成的载波的13.56MHz传输模块,基于80C51内核有40KROM、1KRAM。某宝价格为几十元,非常便宜。只能用来读取IC卡,不能读取ID卡和CPU卡。
入门
引脚接线
常用接线也在示例程序中写明,这里我使用的是Arduino Uno,所以接线参考前两列即可。
* Typical pin layout used:* -----------------------------------------------------------------------------------------* MFRC522 Arduino Arduino Arduino Arduino Arduino* Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro* Signal Pin Pin Pin Pin Pin Pin* -----------------------------------------------------------------------------------------* RST/Reset RST 9 5 D9 RESET/ICSP-5 RST* SPI SS SDA(SS) 10 53 D10 10 10* SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16* SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14* SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15*/
即(左侧为RFID-RC522引脚,右侧为Uno引脚)
RST <----------> 9
SDA(SS) <----------> 10
MOSI <----------> 11
MISO <----------> 12
SCK <----------> 13
3.3V <----------> 3.3V
GND <----------> GND
读取 UNID <-> 卡号 <-> ID号
这里使用的是MFRC522库中的示例-ReadUNID,读取卡号。
据说每一张卡的ID都不一样-,-读取卡号就能判断身份,不过最好是先尝试写入数据(尝试修改卡号),能修改的卡说明是复制卡,这就需要认真对待这样卡的安全性了。
Sketch
#include <SPI.h>
#include <MFRC522.h>#define SS_PIN 10
#define RST_PIN 9MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the classMFRC522::MIFARE_Key key; // Init array that will store new NUID
byte nuidPICC[4];void setup() { Serial.begin(9600);SPI.begin(); // Init SPI busSerial.println(F("Start--------------------"));rfid.PCD_Init(); // Init MFRC522 for (byte i = 0; i < 6; i++) {key.keyByte[i] = 0xFF;}Serial.println(F("This code scan the MIFARE Classsic NUID."));Serial.print(F("Using the following key:"));printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
}void loop() {// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.if ( ! rfid.PICC_IsNewCardPresent())return;// Verify if the NUID has been readedif ( ! rfid.PICC_ReadCardSerial())return;Serial.print(F("PICC type: "));MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);Serial.println(rfid.PICC_GetTypeName(piccType));// Check is the PICC of Classic MIFARE typeif (piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType != MFRC522::PICC_TYPE_MIFARE_1K &&piccType != MFRC522::PICC_TYPE_MIFARE_4K) {Serial.println(F("Your tag is not of type MIFARE Classic."));return;}if (rfid.uid.uidByte[0] != nuidPICC[0] || rfid.uid.uidByte[1] != nuidPICC[1] || rfid.uid.uidByte[2] != nuidPICC[2] || rfid.uid.uidByte[3] != nuidPICC[3] ) {Serial.println(F("A new card has been detected."));// Store NUID into nuidPICC arrayfor (byte i = 0; i < 4; i++) {nuidPICC[i] = rfid.uid.uidByte[i];}Serial.println(F("The NUID tag is:"));Serial.print(F("In hex: "));printHex(rfid.uid.uidByte, rfid.uid.size);Serial.println();Serial.print(F("In dec: "));printDec(rfid.uid.uidByte, rfid.uid.size);Serial.println();}else Serial.println(F("Card read previously."));// Halt PICCrfid.PICC_HaltA();// Stop encryption on PCDrfid.PCD_StopCrypto1();
}/*** Helper routine to dump a byte array as hex values to Serial. */
void printHex(byte *buffer, byte bufferSize) {for (byte i = 0; i < bufferSize; i++) {Serial.print(buffer[i] < 0x10 ? " 0" : " ");Serial.print(buffer[i], HEX);}
}/*** Helper routine to dump a byte array as dec values to Serial.*/
void printDec(byte *buffer, byte bufferSize) {for (byte i = 0; i < bufferSize; i++) {Serial.print(buffer[i] < 0x10 ? " 0" : " ");Serial.print(buffer[i], DEC);}
}
结果
打开Arduino的串口监视器,下载好程序,把IC卡刷到RFID-RC522模块上有标记线圈的位置,就能在串口监视器中看到其编号(饭卡、银行卡刷不出来。。。。。)
写入&&读取个人信息:名+姓氏
接线请往上爬,一模一样。
Sketch-写入
rfid_write_personal_data.ino
#include <SPI.h>
#include <MFRC522.h>#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout aboveMFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instancevoid setup() {Serial.begin(9600); // Initialize serial communications with the PCSPI.begin(); // Init SPI busmfrc522.PCD_Init(); // Init MFRC522 cardSerial.println(F("Write personal data on a MIFARE PICC "));
}void loop() {// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.MFRC522::MIFARE_Key key;for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.if ( ! mfrc522.PICC_IsNewCardPresent()) {return;}// Select one of the cardsif ( ! mfrc522.PICC_ReadCardSerial()) {return;}Serial.print(F("Card UID:")); //Dump UIDfor (byte i = 0; i < mfrc522.uid.size; i++) {Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");Serial.print(mfrc522.uid.uidByte[i], HEX);}Serial.print(F(" PICC type: ")); // Dump PICC typeMFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);Serial.println(mfrc522.PICC_GetTypeName(piccType));byte buffer[34];byte block;MFRC522::StatusCode status;byte len;Serial.setTimeout(20000L) ; // wait until 20 seconds for input from serial// Ask personal data: Family nameSerial.println(F("Type Family name, ending with #"));len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serialfor (byte i = len; i < 30; i++) buffer[i] = ' '; // pad with spacesblock = 1;//Serial.println(F("Authenticating using key A..."));status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));if (status != MFRC522::STATUS_OK) {Serial.print(F("PCD_Authenticate() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}else Serial.println(F("PCD_Authenticate() success: "));// Write blockstatus = mfrc522.MIFARE_Write(block, buffer, 16);if (status != MFRC522::STATUS_OK) {Serial.print(F("MIFARE_Write() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}else Serial.println(F("MIFARE_Write() success: "));block = 2;//Serial.println(F("Authenticating using key A..."));status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));if (status != MFRC522::STATUS_OK) {Serial.print(F("PCD_Authenticate() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}// Write blockstatus = mfrc522.MIFARE_Write(block, &buffer[16], 16);if (status != MFRC522::STATUS_OK) {Serial.print(F("MIFARE_Write() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}else Serial.println(F("MIFARE_Write() success: "));// Ask personal data: First nameSerial.println(F("Type First name, ending with #"));len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serialfor (byte i = len; i < 20; i++) buffer[i] = ' '; // pad with spacesblock = 4;//Serial.println(F("Authenticating using key A..."));status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));if (status != MFRC522::STATUS_OK) {Serial.print(F("PCD_Authenticate() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}// Write blockstatus = mfrc522.MIFARE_Write(block, buffer, 16);if (status != MFRC522::STATUS_OK) {Serial.print(F("MIFARE_Write() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}else Serial.println(F("MIFARE_Write() success: "));block = 5;//Serial.println(F("Authenticating using key A..."));status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));if (status != MFRC522::STATUS_OK) {Serial.print(F("PCD_Authenticate() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}// Write blockstatus = mfrc522.MIFARE_Write(block, &buffer[16], 16);if (status != MFRC522::STATUS_OK) {Serial.print(F("MIFARE_Write() failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}else Serial.println(F("MIFARE_Write() success: "));Serial.println(" ");mfrc522.PICC_HaltA(); // Halt PICCmfrc522.PCD_StopCrypto1(); // Stop encryption on PCD}
Result
例如我第一次输入 Smith#
第二次输入 Rick#
Sketch-读取
#include <SPI.h>
#include <MFRC522.h>#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout aboveMFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance//*****************************************************************************************//
void setup() {Serial.begin(9600); // Initialize serial communications with the PCSPI.begin(); // Init SPI busmfrc522.PCD_Init(); // Init MFRC522 cardSerial.println(F("Read personal data on a MIFARE PICC:")); //shows in serial that it is ready to read
}//*****************************************************************************************//
void loop() {// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.MFRC522::MIFARE_Key key;for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;//some variables we needbyte block;byte len;MFRC522::StatusCode status;//-------------------------------------------// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.if ( ! mfrc522.PICC_IsNewCardPresent()) {return;}// Select one of the cardsif ( ! mfrc522.PICC_ReadCardSerial()) {return;}Serial.println(F("**Card Detected:**"));//-------------------------------------------mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card//mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex//-------------------------------------------Serial.print(F("Name: "));byte buffer1[18];block = 4;len = 18;//------------------------------------------- GET FIRST NAMEstatus = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp fileif (status != MFRC522::STATUS_OK) {Serial.print(F("Authentication failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}status = mfrc522.MIFARE_Read(block, buffer1, &len);if (status != MFRC522::STATUS_OK) {Serial.print(F("Reading failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}//PRINT FIRST NAMEfor (uint8_t i = 0; i < 16; i++){if (buffer1[i] != 32){Serial.write(buffer1[i]);}}Serial.print(" ");//---------------------------------------- GET LAST NAMEbyte buffer2[18];block = 1;status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834if (status != MFRC522::STATUS_OK) {Serial.print(F("Authentication failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}status = mfrc522.MIFARE_Read(block, buffer2, &len);if (status != MFRC522::STATUS_OK) {Serial.print(F("Reading failed: "));Serial.println(mfrc522.GetStatusCodeName(status));return;}//PRINT LAST NAMEfor (uint8_t i = 0; i < 16; i++) {Serial.write(buffer2[i] );}//----------------------------------------Serial.println(F("\n**End Reading**\n"));delay(1000); //change value if you want to read cards fastermfrc522.PICC_HaltA();mfrc522.PCD_StopCrypto1();
}
Result
正如上面所输入的一样-.-
读取扇区数据
以S50为例,读取其中16个扇区的全部数据,烧录程序后刷一下就能在串口监视器看到所有扇区对应的数据了
Sketch
Dumpinfo.info
#include <SPI.h>
#include <MFRC522.h>#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout aboveMFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instancevoid setup() {Serial.begin(9600); // Initialize serial communications with the PCwhile (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)SPI.begin(); // Init SPI busmfrc522.PCD_Init(); // Init MFRC522delay(4); // Optional delay. Some board do need more time after init to be ready, see Readmemfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader detailsSerial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}void loop() {// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.if ( ! mfrc522.PICC_IsNewCardPresent()) {return;}// Select one of the cardsif ( ! mfrc522.PICC_ReadCardSerial()) {return;}// Dump debug info about the card; PICC_HaltA() is automatically calledmfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}
Result
References
- Arduino教程 RFID-RC522读IC卡门禁原理
- Introduction to NFC
- 产品资料 提取码: qi6v
- M1 : S50和S70
- IC卡小结
Arduino Uno 搭配 RFID-RC522上手:读取卡号,写入数据、读取数据相关推荐
- 基于Arduino Uno的RFID门禁
前言 这个门禁已经用了一年多啦~实测很稳定 接线也比较简单,而且实用性拉满,适合用来入门 因为我宿舍靠阳台下雨会泼水所以就没做指纹和密码,有兴趣的也可以拓展多种解锁方式 背景 本人没有带钥匙出门的习惯 ...
- vb.net读取excel并写入dgv_读取PDF中的表格写入EXCEL?30行代码搞定
办公自动化系列+1 现在,各类数据分析的书籍,都可以在网上找到PDF版本: 同时,百度文库.各类数据统计文库.行业研究等众多论文报告,是通过PDF的形式去展示输出的: 但是,令人都头疼的是,各类数据分 ...
- python读取pdf并写入excel_Python读取pdf表格写入excel代码方法
本篇文章小编给大家分享一下Python读取pdf表格写入excel代码方法,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. 避免CV大法 pdf 文件的 ...
- python读取txt文件写入-python 读取、写入txt文件的示例
写入文件 使用open()函数和write()函数 但是有两种写法,分别是'a'和'w' 'a' 表示写入文件 若无该文件会直接创建一个 如果存在这个文件,会接着已有的内容的后面写入 with ope ...
- Arduino + RFID 读取 IC 卡 Arduino uno中获得RFID的UID 并通过串口转发RFID卡号
RFID简介:射频识别即RFID(Radio Frequency IDentification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需识别系统与特定 ...
- Arduino Uno + RFID 读取 把你的门禁卡读取看看有什么秘密
欢迎关注「凌顺实验室」微信公众号 RFID技术现在都非常成熟和应用广泛 今天我们就来看看这个RFID如何实现读取里面的数据 看看RFID模块是什么模样的 实验效果 在串口监控器里面,我们把IC卡放在模 ...
- RFID模块+WIFI模块+振动传感器+有源蜂鸣器+舵机+Arduino UNO R3所构成的门禁系统模块
该系统模块主要由RFID模块+WIFI模块+振动传感器+有源蜂鸣器+舵机+Arduino UNO R3组成的门禁系统模块.这里使用舵机充当门锁,用户可以刷卡开门,也可以通过APP控制舵机状态达到开门的 ...
- Arduino UNO控制带AB相磁通量式编码器电动推杆(测试阻尼)实录(L289N电机驱动)
前段时间为了测试实验器材的阻尼,需要去开发一套装置来测试.提出用Arduino单片机来控制电动推杆(Linear Actuator)来制造相应速度的运动,搭配上测力计,从而根据来测得阻尼,在这里简单记 ...
- ESP32学习笔记(49)——RFID RC522使用
一.简介 MF RC522 是应用于 13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员.是 NXP 公司针对"三表"应用推出的一款低电压.低成本.体积小的非接触式读写 ...
最新文章
- 怕蛇的人如何学Python?
- Linux操作系统下以不同颜色命名的文件类型
- SolrJ查询Solr数据
- 【H2 Database】导出CSV
- 非文学翻译理论与实践_北外“欧洲非通用语文学翻译与研究中心”正式成立
- Solr 配置文件之schema.xml
- Kotlin静态方法定义和调用
- Linux 设置环境变量导致bash:command not found
- weblogic时间问题
- 计算机网络—数据链路层 网络层 传输层 应用层
- 手机号码好坏什么软件测试,测试你的手机号码好不好(很准哦)
- com.jcraft.jsch.JSchException: Algorithm negotiation fail 异常解决
- 献给盲目追谁IT的管理者的话,转载:活着就是王道---- -一年
- (一)TileMap使用
- 元代家谱上的名字是以数字命名的?这里面蕴含了哪些历史特色?
- halcon 图像合成与通道
- 老版三星笔记本识别不到U盘启动解决办法
- 数论--欧几里得和扩展的欧几里得定理
- 玩转96boards之(一)---高通410c板硬件
- leetcode 51. N 皇后
热门文章
- 第二十五讲 实例补充
- [附源码]计算机毕业设计Python+uniapp拼车出行微信小程序01hbw(程序+lw+远程部署)
- 输出1000-2000内的闰年
- materials about miR-501 Alters Susceptibility to HCC
- ALV的lvc_s_layo和lvc_s_fcat参数详解
- SCP (Secure copy)简介
- IC设计工程师发展方向探究
- verilog 移位运算符 说明_Verilog HDL的基本语法
- 泰山OFFICE技术讲座:重新研究了中英文间隔,提出了柳氏中英文间隔计算公式
- 旅行一条龙服务 【在线旅游OTA产品相关性分析】