37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来---小小的进步或是搞不掂的问题,希望能够抛砖引玉。
MF RC522
是应用于13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员。是NXP 公司针对“三表”应用推出的一款低 电压、低成本、体积小的非接触式读写卡芯片,是智能仪表和便携式手持设备研发的较好选择。
MF RC522特点和优势
高度集成的模拟电路来解调和解码的响应
缓冲的输出驱动器,用于连接一个天线的最小数量
外部元件
支持ISO / IEC 14443 A / MIFARE
典型操作距离在读/写模式下可达至50mm视
天线的尺寸和调整
支持MF1xxS20 , MF1xxS70和MF1xxS50在读/写模式加密
支持ISO / IEC 14443高达848 kBd的更高传输速度的通信
支持MFIN / MFOUT
额外的内部电源IC智能卡,通过MFIN / MFOUT连接
支持的主机接口
MFRC522是一个高度集成的读取器/写入器IC,适用于非接触式通信
在13.56MHz 。该MFRC522读卡器支持ISO / IEC 14443 A / MIFARE模式。
该MFRC522的内部发射器能够驱动一个读/写器天线设计
符合ISO / IEC 14443 A / MIFARE卡和转发器,无需额外通信
有源电路。接收器模块提供了一个强大而英法fi cient实现
从ISO / IEC解调和解码信号14443 A / MIFARE兼容卡
转发器。数字模块管理的完整的ISO / IEC 14443 A和取景
错误检测(奇偶和CRC )功能。
该MFRC522支持MF1xxS20 , MF1xxS70和MF1xxS50产品。该MFRC522
支持非接触式通信,并使用MIFARE更高的传输速度高达
848 kBd的两个方向。
提供了下面的主机接口:
•串行外设接口(SPI )
•串行UART (类似与RS232电平依赖于引脚电压源)
•I2C- BUS接口
MF522-AN模块采用Philips MFRC522原装芯片设计读卡电路,使用方便,成本低廉,适用于设备开发、读卡器开发等高级应用的用户、需要进行射频卡终端设计/生产的用户。本模块可直接装入各种读卡器模具。模块采用电压为3.3V,通过SPI接口简单的几条线就可以直接与用户任何CPU主板相连接通信,可以保证模块稳定可靠的工作、读卡距离远;
【电气参数简介】
工作电流:13—26mA/直流3.3V
空闲电流:10-13mA/直流3.3V
休眠电流:<80uA
峰值电流:<30mA
工作频率:13.56MHz
支持的卡类型:mifare1 S50、mifare1 S70、mifare UltraLight、mifare Pro、mifare Desfire
产品物理特性:尺寸:40mm×60mm
环境工作温度:摄氏-20—80度
环境储存温度:摄氏-40—85度
环境相对湿度:相对湿度5%—95%
【模块接口SPI参数】
数据传输速率:最大10Mbit/s
MFRC-522 RC522 RFID射频 IC卡感应模块读卡器S50复旦卡钥匙扣模组
模块参考电原理图
射频卡
非接触式IC卡又称射频卡,由IC芯片、感应天线组成,封装在一个标准的PVC卡片内,芯片及天线无任何外露部分。是世界上最近几年发展起来的一项新技术,它成功的将射频识别技术和IC卡技术结合起来,结束了无源(卡中无电源)和免接触这一难题,是电子器件领域的一大突破。卡片在一定距离范围(通常为5—10cm)靠近读写器表面,通过无线电波的传递来完成数据的读写操作。
工作原理
射频读写器向IC卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,这样在电磁波激励下,LC谐振电路产生共振,从而使电容内有了电荷;在这个电荷的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内存储,当所积累的电荷达到2V时,此电容可作为电源为其它电路提供工作电压,将卡内数据发射出去或接受读写器的数据。
发射原理
非接触性IC卡与读卡器之间通过无线电波来完成读写操作。二者之间的通讯频率为13.56MHZ。非接触性IC卡本身是无源卡,当读写器对卡进行读写操作时,读写器发出的信号由两部分叠加组成:一部分是电源信号,该信号由卡接收后,与本身的L/C产生一个瞬间能量来供给芯片工作。另一部分则是指令和数据信号,指挥芯片完成数据的读取、修改、储存等,并返回信号给读写器,完成一次读写操作。读写器则一般由单片机,专用智能模块和天线组成,并配有与PC的通讯接口,打印口,I/O口等,以便应用于不同的领域。
Miafre 1 s50 感应式IC卡
◇ 芯 片: Philips Mifare 1 S50
◇ 存储容量: 8Kbit ,16个分区,每分区两组密码
◇ 工作频率: 13.56MHZ
◇ 通讯速度: 106Kboud
◇ 读写距离: 2.5—10CM
◇ 读写时间: 1-2MS
◇ 工作温度: -20℃-85℃
◇ 擦写次数: >100000次
◇ 数据保存: >10年
◇ 规 格: 0.87×85.5×54/ 非标卡
◇ 封装材料: PVC、PET、0.13铜钱
◇ 封装工艺: 超声波自动植线/自动碰焊
◇ 制作标准: ISO 14443, ISO 10536
◇ 应用范围: 企业/校园一卡通、公交储值卡、高速公路收费、停车场、小区管理等
实验原理
RFID系统组成
RFID 技术利用无线射频方式在阅读器和射频卡之间进行非接触双向数据传输,以达到目标识别和数据交换的目的。最基本的 RFID 系统由三部分组成:
1. 标签(Tag,即射频卡):由耦合元件及芯片组成,标签含有内置天线,用于和射频天线间进行通信。
2. 阅读器:读取(在读写卡中还可以写入)标签信息的设备。
3. 天线:在标签和读取器间传递射频信号。
工作原理
MCU通过对读卡器芯片内寄存器的读写来控制读卡器芯片,读卡器芯片收到MCU发来的命令后,按照非接触式射频卡协议格式,通过天线及其匹配电路向附近发出一组固定频率的调制信号(13.56 MHz)进行寻卡,若此范围内有卡片存在,卡片内部的LC谐振电路(谐振频率与读卡器发送的电磁波频率相同)在电磁波的激励下,产生共振,在卡片内部电压泵的作用下不断为其另一端的电容充电,获得能量,当该电容电压达到2 V时,即可作为电源为卡片的其他电路提供工作电压。 当有卡片处在读卡器的有效工作范围内时,MCU向卡片发出寻卡命令,卡片将回复卡片类型,建立卡片与读卡器的第一步联系,若同时有多张卡片在天线的工作范围内,读卡器通过启动防冲撞机制,根据卡片序列号来选定一张卡片,被选中的卡片再与读卡器进行密码校验,确保读卡器对卡片有操作权限以及卡片的合法性,而未被选中的则仍然处在闲置状态,等待下一次寻卡命令。密码验证通过之后,就可以对卡片进行读写等应用操作。
RC522模块
模块的射频读写芯片应该是飞利浦的 MF RC522,在上一篇文章我应该已经附上了英文和中文的手册。MF RC522提供了3种接口模式:高达10 Mb/s的SPI、I2C总线模式(快速模式下能达400 kb/s,而高速模式下能达3.4 Mb/s)、最高达1228.8 kb/s的UART模式。买来的模块采用了第一种模式——四线制SPI,通信中的时钟信号由 Arduino 产生,MF RC522芯片设置为从机模式,接收来自 Arduino 的数据以设置寄存器,并负责射频接口通信中相关数据的收发。数据的传输路径为:Arduino 通过 MOSI 线将数据发到 MF RC522,MF RC522 通过 MISO 线发回至 Arduino。
RC522模块各引脚功能
SDA -- 串行数据线(IIC接口时的I/O线);在SPI接口中为NSS(从机标志管脚);
SCK -- 连接MCU的SCK信号;
MOSI -- MCU输出,RC522接收(即主设备输出,从设备输入);
MISO -- RC522输出,MCU接收(即从设备输出,主设备输入);
IRQ -- 中断请求输出;
GND -- 接地;
RST -- 复位;
3.3V -- VSS,工作电压,若使用的事5V的MCU,注意分压。
实验开源代码
/* 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验九十八:MFRC-522 RC522 RFID射频 IC卡感应模块读卡器S50复旦卡钥匙扣模组 1、工具-管理库-搜索“MFRC522”库-安装 2、项目:使用MFRC522 RFID和Arduino读写标签 3、RFID与Arduino Uno的连线 SDA------------------------Digital 10 SCK------------------------Digital 13 MOSI----------------------Digital 11 MISO----------------------Digital 12 IRQ------------------------不用连接 GND-----------------------GND RST------------------------Digital 9 3.3V------------------------3.3V (千万不要连接到5V接口!!!) */ #include <SPI.h> #include <MFRC522.h> #define SS_PIN 10 #define RST_PIN 9 MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance. void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card Serial.println("Scan PICC to see UID and type..."); } void loop() { // Look for new cards if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return; } // Dump debug info about the card. PICC_HaltA() is automatically called. mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); }
实验串口返回情况
实验场景图
实验开源代码之二
/* 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验九十八:MFRC-522 RC522 RFID射频 IC卡感应模块读卡器S50复旦卡钥匙扣模组 1、工具-管理库-搜索“MFRC522”库-安装 2、项目二:读取UID,并将其分别以十进制和十六进制输出到串口 3、RFID与Arduino Uno的连线 SDA------------------------Digital 10 SCK------------------------Digital 13 MOSI----------------------Digital 11 MISO----------------------Digital 12 IRQ------------------------不用连接 GND-----------------------GND RST------------------------Digital 9 3.3V------------------------3.3V (千万不要连接到5V接口!!!) */ #include <SPI.h> #include <MFRC522.h> #define SS_PIN 10 #define RST_PIN 9 MFRC522 rfid(SS_PIN, RST_PIN); //实例化类 // 初始化数组用于存储读取到的NUID byte nuidPICC[4]; void setup() { Serial.begin(9600); SPI.begin(); // 初始化SPI总线 rfid.PCD_Init(); // 初始化 MFRC522 } void loop() { // 找卡 if ( ! rfid.PICC_IsNewCardPresent()) return; // 验证NUID是否可读 if ( ! rfid.PICC_ReadCardSerial()) return; MFRC522::ICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak); // 检查是否MIFARE卡类型 if (piccType != MFRC522::ICC_TYPE_MIFARE_MINI && piccType != MFRC522::ICC_TYPE_MIFARE_1K && piccType != MFRC522::ICC_TYPE_MIFARE_4K) { Serial.println("不支持读取此卡类型"); return; } // 将NUID保存到nuidPICC数组 for (byte i = 0; i < 4; i++) { nuidPICC = rfid.uid.uidByte; } Serial.print("十六进制UID:"); printHex(rfid.uid.uidByte, rfid.uid.size); Serial.println(); Serial.print("十进制UID:"); printDec(rfid.uid.uidByte, rfid.uid.size); Serial.println(); // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡 rfid.PICC_HaltA(); // 停止读卡模块编码 rfid.PCD_StopCrypto1(); } void printHex(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer < 0x10 ? " 0" : ""); Serial.print(buffer, HEX); } } void printDec(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer < 0x10 ? " 0" : ""); Serial.print(buffer, DEC); } }
实验串口返回情况
实验开源代码之三
/* 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程) 实验九十八:MFRC-522 RC522 RFID射频 IC卡感应模块读卡器S50复旦卡钥匙扣模组 1、安装库:IDE-工具-管理库-搜索“MFRC522”库-安装 2、项目三:RC522 模块的读写操作 3、RFID与Arduino Uno的连线 SDA------------------------Digital 10 SCK------------------------Digital 13 MOSI----------------------Digital 11 MISO----------------------Digital 12 IRQ------------------------不用连接 GND-----------------------GND RST------------------------Digital 9 3.3V------------------------3.3V (千万不要连接到5V接口!!!) */ #include <SPI.h> #include <MFRC522.h> #define RST_PIN 9 // 配置针脚 #define SS_PIN 10 MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建新的RFID实例 MFRC522::MIFARE_Key key; void setup() { Serial.begin(9600); // 设置串口波特率为9600 while (!Serial); // 如果串口没有打开,则死循环下去不进行下面的操作 SPI.begin(); // SPI开始 mfrc522.PCD_Init(); // Init MFRC522 card for (byte i = 0; i < 6; i++) { key.keyByte = 0xFF; } Serial.println(F("扫描卡开始进行读或者写")); Serial.print(F("使用A和B作为键")); dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE); Serial.println(); Serial.println(F("注意,会把数据写入到卡在#1")); } void loop() { // 寻找新卡 if ( ! mfrc522.PICC_IsNewCardPresent()) return; // 选择一张卡 if ( ! mfrc522.PICC_ReadCardSerial()) return; // 显示卡片的详细信息 Serial.print(F("卡片 UID:")); dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); Serial.println(); Serial.print(F("卡片类型: ")); MFRC522:ICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak); Serial.println(mfrc522.PICC_GetTypeName(piccType)); // 检查兼容性 if ( piccType != MFRC522:ICC_TYPE_MIFARE_MINI && piccType != MFRC522:ICC_TYPE_MIFARE_1K && piccType != MFRC522:ICC_TYPE_MIFARE_4K) { Serial.println(F("仅仅适合Mifare Classic卡的读写")); return; } // 我们只使用第二个扇区 // 覆盖扇区4 byte sector = 1; byte blockAddr = 4; byte dataBlock[] = { 0x01, 0x02, 0x03, 0x04, // 1, 2, 3, 4, 0x05, 0x06, 0x07, 0x08, // 5, 6, 7, 8, 0x00, 0x00, 0x00, 0x00, // 0,0,0,0 0x00, 0x00, 0x00, 0x00 // 0,0,0,0 };//写入的数据定义 byte trailerBlock = 7; MFRC522::StatusCode status; byte buffer[18]; byte size = sizeof(buffer); // 原来的数据 Serial.println(F("显示原本的数据...")); status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522:ICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("身份验证失败?或者是卡链接失败")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // 显示整个扇区 Serial.println(F("显示所有扇区的数据")); mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector); Serial.println(); // 从块儿读取数据 Serial.print(F("读取块儿的数据在:")); Serial.print(blockAddr); Serial.println(F("块 ...")); status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size); if (status != MFRC522::STATUS_OK) { Serial.print(F("读卡失败,没有连接上 ")); Serial.println(mfrc522.GetStatusCodeName(status)); } Serial.print(F("数据内容在第 ")); Serial.print(blockAddr); Serial.println(F(" 块:")); dump_byte_array(buffer, 16); Serial.println(); Serial.println(); //开始进行写入准备 Serial.println(F("开始进行写入的准备...")); status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522:ICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("写入失败,没有连接上或者没有权限 ")); Serial.println(mfrc522.GetStatusCodeName(status)); return; } // Write data to the block Serial.print(F("在第: ")); Serial.print(blockAddr); Serial.println(F(" 块中写入数据...")); dump_byte_array(dataBlock, 16); Serial.println(); status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16); if (status != MFRC522::STATUS_OK) { Serial.print(F("写入失败... ")); Serial.println(mfrc522.GetStatusCodeName(status)); } Serial.println(); // 再次读取卡中数据,这次是写入之后的数据 Serial.print(F("读取写入后第")); Serial.print(blockAddr); Serial.println(F(" 块的数据 ...")); status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size); if (status != MFRC522::STATUS_OK) { Serial.print(F("读取失败... ")); Serial.println(mfrc522.GetStatusCodeName(status)); } Serial.print(F("块 ")); Serial.print(blockAddr); Serial.println(F("数据为 :")); dump_byte_array(buffer, 16); Serial.println(); // 验证一下数据,要保证写入前后数据是相等的 // 通过计算块中的字节数量 Serial.println(F("等待验证结果...")); byte count = 0; for (byte i = 0; i < 16; i++) { // 比较一下缓存中的数据(我们读出来的数据) = (我们刚刚写的数据) if (buffer == dataBlock) count++; } Serial.print(F("匹配的字节数量 = ")); Serial.println(count); if (count == 16) { Serial.println(F("验证成功 :")); } else { Serial.println(F("失败,数据不匹配")); Serial.println(F("也许写入的内容不恰当")); } Serial.println(); // 转储扇区数据 Serial.println(F("写入后的数据内容为::")); mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector); Serial.println(); // 停止 PICC mfrc522.PICC_HaltA(); //停止加密PCD mfrc522.PCD_StopCrypto1(); } /** * 将字节数组转储为串行的十六进制值 */ void dump_byte_array(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer < 0x10 ? " 0" : " "); Serial.print(buffer, HEX); } }
实验串口返回情况
实验开源仿真编程(Linkboy V4.62)
实验仿真编程(Linkboy V4.62)之二
实验串口返回情况