深入了解M1卡[1] RC522 S50
M1卡的工作原理和保密性
深圳市联合智能卡有限公司
M1卡的工作原理和保密性
本文由联合智能卡编辑M1卡是是指菲利浦下属子公司恩智浦出品的芯片缩写,全称为NXP Mifare1系列,M1卡常用的芯片有S50及S70两种型号。
卡片的电气部分只由一个天线和ASIC(专用集成电路)组成,没有其它外部器件。
天线:卡片的天线是只有几组绕线的线圈,很适于封装到ISO卡片中。
ASIC:卡片的ASIC由一个高速(106KB波特率)的RF 接口,一个控制单元和一个8K位EEPROM组成。
M1卡的工作原理是:读写器向M1卡发一组固定频率的电磁波,卡片内有一个 LC串联谐振电路,其频率与读写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
M1卡的保密性高而受欢迎,M1卡的保密性能很好是由于:读写前的三次确认、独一无二的卡片序列号、传递数据加密、传输密码和访问密码的保护。
卡片中的密码是受保护、不可读的,只有知道密码的用户才能修改它。
卡中的EEPROM 存储区分为16个扇区,每个扇区都有自己的访问密码,用户可根据扇区的不同应用设定不同的密码(一卡多用)。
扇区的访问密码分为KEY A和KEY B两组不同密码,根据访问条件,在校验KEY A和KEY B之后才可以对存储器进行访问。
例如:KEY A用于保护减操作,KEY B用于保护加操作。
深圳市联合智能卡有限公司。
M1卡(S50)资料讲解
S50非接触式IC卡性能简介(M1)一、主要指标●容量为8K位EEPROM●分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位●每个扇区有独立的一组密码及访问控制●每张卡有唯一序列号,为32位●具有防冲突机制,支持多卡操作●无电源,自带天线,内含加密控制逻辑和通讯逻辑电路●数据保存期为10年,可改写10万次,读无限次●工作温度:-20℃~50℃(湿度为90%)●工作频率:13.56MHZ●通信速率:106 KBPS●读写距离:10 cm以内(与读写器有关)二、存储结构1、M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示:数据块0数据块 1数据块 2控制块 3数据块 4数据块 5数据块 6控制块7数据块60数据块61数据块62控制块632、第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
3、每个扇区的块0、块1、块2为数据块,可用于存贮数据。
数据块可作两种应用:★用作一般的数据保存,可以进行读、写操作。
★用作数据值,可以进行初始化值、加值、减值、读值操作。
4、每个扇区的块3为控制块,包括了密码A、存取控制、密码B。
具体结构如下:密码A(6字节)存取控制(4字节)密码B(6字节)5、每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:块0:C10 C20 C30块1:C11 C21 C31块2:C12 C22 C32块3:C13 C23 C33三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。
三个控制位在存取控制字节中的位置,以块0为例:对块0的控制:字节7字节8字节9( 注:C10_b表示C10取反)存取控制(4字节,其中字节9为备用字节)结构如下所示:字节6字节7字节8字节9( 注:_b表示取反)6、数据块(块0、块1、块2)的存取控制如下:(KeyA|B 表示密码A或密码B,Never表示任何条件下不能实现)例如:当块0的存取控制位C10 C20 C30=1 0 0时,验证密码A或密码B正确后可读;验证密码B正确后可写;不能进行加值、减值操作。
M1卡详细介绍
M1卡详细介绍M1卡是非接触式感应卡,数据保存期为10年,可改写10万次,读无限次。
无电源,自带天线,工作频率为13.56MHZ.内含加密控制逻辑和通讯逻辑电路。
一般主要有两种,S50和S70。
M1卡的结构:S50容量1Kbyte,16个扇区(Sector),每个扇区4块(Block)(块0~3),共64块,按块号编址为0~63。
每个扇区有独立的一组密码及访问控制。
第0扇区的块0(即绝对地址0块)用于存放厂商代码,已经固化,不可更改。
其他各扇区的块0、块1、块2为数据块,用于存贮数据;块3为控制块,存放密码A、存取控制、密码B。
另一种是S70,4K byte(字节)的存储容量,即32Kbit(位)的存储容量。
S70卡和 S50卡在协议和命令上是完全兼容的,唯一不同的就是两种卡的容量,S70 卡一共有40个扇区,前面32个扇区(0 ~ 31)和 S50卡一模一样。
后面8个扇区(32 ~ 39),每个扇区都是16个块,同样每个块16个字节,并且同样是最后一块是该扇区的密码控制块。
M1卡的运作机理:连接读写器→寻卡→识别卡(获取卡序列号)→从多卡中选一张卡→向卡中缓冲区装载密码→验证密码→进行读写→关闭连接即:(代码说明)Open_USB→rf_request→rf_anticoll→rf_select→rf_load_key→rf_authentication→(/a_hex)→rf_read/rf_write→(hex_a)→Close_USB 如果概括来说的话,主要也就四部分:开关连接、寻卡、验证密码、读取。
(至于详细程序代码,相信看过dll说明文档后,会明白的)M1卡的功能模式:一.寻卡模式寻卡模式分三种情况:IDLE模式、ALL模式及指定卡模式(0,1,2 均是int类型,是方法参数,下同)。
0——表示IDLE模式,一次只对一张卡操作;1——表示ALL模式,一次可对多张卡操作;2——表示指定卡模式,只对序列号等于snr的卡操作(高级函数才有)【不常用】也就是说,我们一次也可以同时操作多张卡。
rc522射频模块使用方法
rc522射频模块使用方法RC522射频模块是一种无线通信设备,具有超低功耗、小型化、低成本和强大的功能特性,广泛用于身份证、智能卡和一些可携式设备的读写。
本文旨在介绍RC522射频模块的工作原理及其相关的使用方法。
一、RC522射频模块的工作原理RC522射频模块由读卡器和智能卡组成, RC522射频模块采用13.56MHz非接触式射频识别技术,它基于ISO/IEC 14443A标准设计,具有高性能、高度灵活性、高功率处理能力和低成本等特点。
RC522射频模块可以实现快速、有效地读取智能卡的信息,从而实现身份验证的功能,这是它的基本功能,而且它还支持其他多种功能。
其次,RC522射频模块支持读写NFC、M1卡和其他类型的磁卡,如ISO14443A、ISO14443B、ISO15693、ISO18092,而且还支持FeliCa、Mifare系列卡等,具备良好的兼容性和可编程性,可以满足不同应用场景的需求。
最后,RC522射频模块可以根据接入不同类型的外设,支持具有高达106Kbps的ISO/IEC 14443A/Mifare卡片快速传输。
二、RC522射频模块的使用方法1、安装驱动在使用RC522射频模块之前,首先需要安装驱动,使用支持RC522射频模块的主板进行安装,然后按照说明文档中的步骤安装完成,以保证该模块的正常工作。
2、安装模块安装好驱动之后,可以将RC522射频模块安装到主板上,每个模块都有一个单独的安装位置,有着一定的精准度和敏感度,所以在安装时要谨慎,并将模块固定在安装位置,以确保模块正常工作。
3、操作模块当模块安装完成后,需要进行操作,操作模块可以通过编程语言完成,根据编程语言的不同,使用的模块操作方法也不同,比如C语言可以使用MFC实现,Python语言可以使用pyRFID实现等。
4、测试模块模块操作完成后,需要进行测试,以确保模块工作正常,可以使用测试卡书进行测试,该卡书上有用于测试的信息,如果检测到正确的信息,则表明模块正常工作,可以正常使用。
关于M1卡有关情况介绍
关于M1卡有关情况介绍关于M1卡有关情况介绍Mifare one卡(或Mifare-1),简称M1卡内容简介一、Mifare one IC S50 主要指标●容量为8K位EEPROM●分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位●每个扇区有独立的一组密码及访问控制●每张卡有唯一序列号,为32位●具有防冲突机制,支持多卡操作●无电源,自带天线,内含加密控制逻辑和通讯逻辑电路●数据保存期为10年,可改写10万次,读无限次●工作温度:-20℃~50℃(湿度为90%)●工作频率:13.56MHZ●通信速率:106 KBPS●读写距离:10 cm以内(与读写器有关)二、Mifare one IC S70 主要指标●容量为32K位EEPROM●分为40个扇区,其中32个扇区中每个扇区存储容量为64个字节,分为4块,每块16个字节;8个扇区中每个扇区存储容量为256个字节,分为16块,每块16个字节;以块为存取单●每个扇区有独立的一组密码及访问控制●每张卡有唯一序列号,为32位●具有防冲突机制,支持多卡操作●无电源,自带天线,内含加密控制逻辑和通讯逻辑电路●数据保存期为10年,可改写10万次,读无限次●工作温度:-20℃~50℃(湿度为90%)●工作频率:13.56MHZ●通信速率:106 KBPS●读写距离:10 cm以内(与读写器有关)三、M1射频卡与读写器的通讯见下图示:四、工作原理卡片的电气部分只由一个天线和ASIC组成。
天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。
ASIC:卡片的ASIC由一个高速(106KB波特率)的RF接口,一个控制单元和一个8K位EEPROM组成。
工作原理:读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与讯写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
M1卡使用说明书
S50非接触式IC卡性能简介(M1)一、主要指标●容量为8K位EEPROM●分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位●每个扇区有独立的一组密码及访问控制●每张卡有唯一序列号,为32位●具有防冲突机制,支持多卡操作●无电源,自带天线,内含加密控制逻辑和通讯逻辑电路●数据保存期为10年,可改写10万次,读无限次●工作温度:-20℃~50℃(湿度为90%)●工作频率:13.56MHZ●通信速率:106 KBPS●读写距离:10 cm以内(与读写器有关)二、存储结构1、M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,存贮结构如下图所示:数据块0数据块 1数据块 2控制块 3数据块 4数据块 5数据块 6控制块7数据块60数据块61数据块62控制块632、第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
3、每个扇区的块0、块1、块2为数据块,可用于存贮数据。
数据块可作两种应用:★用作一般的数据保存,可以进行读、写操作。
★用作数据值,可以进行初始化值、加值、减值、读值操作。
4、每个扇区的块3为控制块,包括了密码A、存取控制、密码B。
具体结构如下:密码A(6字节)存取控制(4字节)密码B(6字节)5、每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:块0:C10 C20 C30块1:C11 C21 C31块2:C12 C22 C32块3:C13 C23 C33三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。
三个控制位在存取控制字节中的位置,以块0为例:对块0的控制:字节7字节8字节9( 注:C10_b表示C10取反)存取控制(4字节,其中字节9为备用字节)结构如下所示:字节6字节7字节8字节9( 注:_b表示取反)6、数据块(块0、块1、块2)的存取控制如下:例如:当块0的存取控制位C10 C20 C30=1 0 0时,验证密码A或密码B正确后可读;验证密码B正确后可写;不能进行加值、减值操作。
M1卡详细资料
MIFARE MF1 S50 简介
3
传输密码保护 支持一卡多用的存储结构
8K 位 EEPROM,无电池 分为 16 个扇区支持多种应用 每个扇区包括 4 块 块是最小的读写单位,每块包含 16 个字节 每个扇区有自己的一组密码 用户可灵活地定义每一扇区的访问条件 运算能力:加和减 数据保持 10 年 典型处理时间 识别一张卡 3ms (包括复位应答和防冲突) 读一个块 2.5ms(不包括认证过程)
Increment KEYA/B never never KEY B never never never never
decrement transfer restore KEYA/B never never KEYA/B KEYA/B never never never
六、保密性
S50 射频卡的保密性能很好是由于:读写前的三次确认、独一无二的卡片序列号、传递数 据加密、传输密码和访问密码的保护。
卡片中的密码是受保护、不可读的,只有知道密码的用户才能修改它。卡中的 EEPROM 存储区分为 16 个扇区,每个扇区都有自己的访问密码,用户可根据扇区的不同应用设定不同的 密码(一卡多用)。扇区的访问密码分为 KEY A 和 KEY B 两组不同密码,根据访问条件,在校 验 KEY A 和 KEY B 之后才可以对存储器进行访问。例如:KEY A 用于保护减操作,KEY B 用 于保护加操作。
C2XY 0 1 0 1 0 1 0 1
C3XY 0 0 0 0 1 1 1 1
Read KEYA/B KEYA/B KEYA/B KEYA/B KEYA/B KEY B KEY B never
Write KEYA/B never KEY B KEY B never KEY B never never
m1卡 工作原理
m1卡工作原理M1卡工作原理1. M1卡简介M1卡,是一种广泛应用于各种领域的智能卡片。
它采用了非接触式射频识别技术,主要用于身份验证、门禁控制、交通支付等领域。
2. 射频识别原理射频识别(RFID)是一种无线通信技术,通过射频信号实现对物体的识别和数据传输。
M1卡就是基于射频识别技术实现的一种智能卡片。
3. M1卡的内部结构M1卡内部包含一块射频芯片和一块储存芯片。
射频芯片用于接收和发送射频信号,实现与读卡器之间的通信;储存芯片用于存储卡片的数据信息。
4. M1卡的工作模式M1卡具有两种工作模式:被动模式和主动模式。
被动模式在被动模式下,M1卡会等待读卡器发射的射频信号来供电。
当读卡器发射射频信号时,M1卡接收并解码该信号,然后将卡片存储的数据信息发送给读卡器。
主动模式在主动模式下,M1卡可以自己发射射频信号。
通过发射特定的射频信号,M1卡可以与读卡器进行通信,并传输存储在卡片中的数据信息。
5. M1卡的数据存储M1卡的储存芯片将数据存储在一系列的块中。
每个块可以存储特定数量的字节数据。
块的数量和每个块的容量可以根据卡片的类型而有所不同。
6. M1卡的通信协议M1卡与读卡器之间的通信采用特定的通信协议。
常见的通信协议有ISO/IEC 14443和ISO/IEC 15693等。
通信协议规定了卡片和读卡器之间的数据传输格式和操作指令。
7. M1卡的应用领域M1卡广泛应用于各个领域,包括门禁控制、交通支付、园区管理等。
通过读卡器与M1卡的射频通信,可以实现身份验证、进出控制、支付扣款等功能。
8. M1卡的安全性M1卡采用了多种安全机制来确保数据的安全性。
例如,卡片和读卡器之间的通信会进行加密,防止数据泄露;卡片中的数据可以进行读写权限控制,防止未经授权的访问。
以上就是M1卡的工作原理的简要介绍。
通过射频识别技术、内部结构、工作模式、数据存储、通信协议、应用领域和安全性等方面的解析,我们对M1卡有了更深入的了解。
M1卡技术参数
芯片类型:
Philips Mifare 1 IC S50
存储容量:
8Kbit,16个分区,每分区两组密码
工作频率:
13.56 MHz
通讯速率:
106KBoud
读写距离:
2.5~10cm
读写时间:
1~2ms
工作温度:
-20℃~55℃
擦写寿命:
>100,000次
数据保存:
>10年
外形尺寸:
ISO标准卡85.6x54x0.82
封装材料:
PVC、PET、PETG、0.13mm铜线
封装工艺:
超声波自动植线/自动碰焊
执行标准:
ISO14443A
由深圳市联合智能卡有公司提供
M1卡技术参数
M1卡是菲利浦下属子公司恩智浦出品的芯片缩写,全称为NXP Mifare1系列,常用的有S50及S70两种型号,目前都有国产芯片与其兼容,利用PVC封装M1芯片、感应天线,然后压制成型后而制作的卡即是智能卡行业所说的M1卡,属于非接触式IC卡。非接触式IC卡又称射频卡,成功地解决了无源(卡中无电源)和免接触这一难题,是电子器件领域的一大突破。这大大减少人们排队的时间,提高企业的服务质量和人们的财产安全性。主要用于公交、轮渡、地铁的自动收费系统,也应用在门禁管理、身份证明和电子钱包。
m1卡 工作原理
m1卡工作原理M1卡是一种近场通信技术(NFC)卡片,广泛应用于支付、门禁、地铁刷卡等领域。
本文将详细介绍M1卡的工作原理。
我们需要了解M1卡的基本结构。
M1卡由内部集成电路芯片和外部封装材料组成。
内部芯片包括存储器和处理器,用于存储和处理相关数据。
封装材料则起到保护芯片的作用,并提供与读写设备的物理连接。
M1卡的工作原理主要分为读取和写入两个过程。
在读取过程中,读写设备通过无线电频率与M1卡进行通信。
读写设备向M1卡发送指令,M1卡则根据指令执行相应操作,并将结果发送回读写设备。
在写入过程中,读写设备将要写入的数据发送给M1卡,M1卡将数据存储在内部存储器中。
M1卡的通信方式采用的是非接触式近场通信技术。
在通信过程中,读写设备通过电磁感应产生高频电磁场,M1卡则利用感应线圈接收读写设备发送的电磁信号,并利用感应线圈发送响应信号。
由于近场通信的特性,读写设备与M1卡之间的通信距离较短,一般在几厘米之内。
M1卡的工作原理还涉及到认证和加密机制。
为了保证数据的安全性,M1卡在与读写设备通信之前需要进行认证。
认证过程中,读写设备向M1卡发送认证密钥和相关指令,M1卡通过内部的加密算法进行认证,并返回认证结果。
只有认证成功的M1卡才能与读写设备进行数据交互。
除了认证机制,M1卡还支持数据的读写和修改操作。
读写设备可以向M1卡发送读取指令,M1卡将存储在内部存储器中的数据发送回读写设备。
同时,读写设备也可以向M1卡发送写入指令,将数据写入到M1卡的内部存储器中。
通过这种方式,M1卡可以实现数据的存储和传输功能。
M1卡还支持多种应用场景。
在支付领域,M1卡可以用作电子钱包,用户可以通过M1卡进行消费支付。
在门禁领域,M1卡可以用作身份识别凭证,用户可以通过M1卡进行门禁开关控制。
在地铁刷卡领域,M1卡可以用作乘车凭证,用户可以通过M1卡进行地铁刷卡乘车。
M1卡是一种运用近场通信技术的智能卡片,具有读写、认证和加密等功能。
Philips S50 IC卡手册
KeyA|B
Never
KeyA|B
Never
1
0
0
Never
KeyB
KeyA|B
Never
Never
KeyB
1
1
0
Never
Never
KeyA|B
Never
Never
Never
0
0
1
Never
KeyA|B
KeyA|B
KeyA|B
KeyA|B
KeyA|B
0
1
1
Never
KeyB
KeyA|B
KeyB
选择卡片(Select Tag)
选择被选中的卡的序列号,并同时返回卡的容量代码。
三次互相确认(3 Pass Authentication)
选定要处理的卡片之后,读写器就确定要访问的扇区号,并对该扇区密码进行密码校验,在三次相互认证之后就可以通过加密流进行通讯。(在选择另一扇区时,则必须进行另一扇区密码校验。)
验证密码B正确后可写;不能进行加值、减值操作。
7、控制块块3的存取控制与数据块(块0、1、2)不同,它的存取控制如下:
密码A
存取控制
密码B
C13
C23
C33
Read
Write
Read
Write
Read
Write
0
0
0
Never
KeyA|B
KeyA|B
Never
KeyA|B
KeyA|B
0
1
0
Never
0
扇区0
块1
数据块
1
块2
数据块
2
rc522例程的基本使用
rc522例程的基本使用一、引言RC522是一种常用的射频识别(RFID)读写卡芯片,广泛应用于身份识别、门禁系统、物流管理等领域。
本文将介绍如何使用RC522例程进行基本的读写卡操作。
二、硬件准备1. MFRC522模块:包括RC522芯片、天线、天线接口等;2. 串口模块:用于连接PC和MFRC522模块进行通信;3. 电源模块:为MFRC522模块提供电源。
三、例程编写1. 导入相关库文件:根据使用的开发环境和编程语言,导入相应的库文件,例如Arduino IDE中需要导入“MFRC522”库。
2. 初始化串口:配置串口通信参数,例如波特率、数据位、停止位等,以便与PC进行通信。
3. 初始化MFRC522模块:配置MFRC522模块的参数,例如频率、时序等,以便与RFID卡进行通信。
4. 读写RFID卡:* 读卡:通过MFRC522模块读取RFID卡的UID(唯一标识符),并将其发送给PC。
* 写卡:将需要写入RFID卡的数据发送给MFRC522模块,由模块写入RFID 卡。
四、代码示例以下是一个使用Arduino IDE和MFRC522库的示例代码:```arduino#include <SPI.h>#include <MFRC522.h>#define SS_PIN 10 // 设置SS引脚为10号引脚#define RST_PIN 9 // 设置RST引脚为9号引脚MFRC522 rfid(SS_PIN, RST_PIN); // 创建MFRC522对象void setup() {Serial.begin(9600); // 初始化串口通信,波特率为9600SPI.begin(); // 初始化SPI总线rfid.PCD_Init(); // 初始化MFRC522模块}void loop() {if ( ! rfid.PICC_IsNewCardPresent()) { // 检查是否有新卡存在return;}if ( ! rfid.PICC_ReadCardSerial()) { // 读取新卡的UID并发送给PCSerial.println("Failed to read card serial.");return;}Serial.print("Card UID:"); // 输出卡的UIDString uid = rfid.uid.toString(); // 将UID转换为字符串格式并输出Serial.println(uid); // 输出UID字符串}```五、注意事项1. 在使用MFRC522模块之前,需要先了解其工作原理和通信协议,以便正确地编写例程和调试程序。
RC522通过SPI方式读写M1卡
1.准备工作战舰V3开发板,RC522模块为淘宝所买,赠送一张M1卡。
SPI方式实测可以读写。
2.RC522部分:rc522.h://///////////////////////////////////////////////////////////////////#include "sys.h"//MF522命令字/////////////////////////////////////////////////////////////////////#define PCD_IDLE 0x00 //取消当前命令#define PCD_AUTHENT 0x0E //验证密钥#define PCD_RECEIVE 0x08 //接收数据#define PCD_TRANSMIT 0x04 //发送数据#define PCD_TRANSCEIVE 0x0C //发送并接收数据#define PCD_RESETPHASE 0x0F //复位#define PCD_CALCCRC 0x03 //CRC计算///////////////////////////////////////////////////////////////////////Mifare_One卡片命令字/////////////////////////////////////////////////////////////////////#define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态#define PICC_REQALL 0x52 //寻天线区内全部卡#define PICC_ANTICOLL1 0x93 //防冲撞#define PICC_ANTICOLL2 0x95 //防冲撞#define PICC_AUTHENT1A 0x60 //验证A密钥#define PICC_AUTHENT1B 0x61 //验证B密钥#define PICC_READ 0x30 //读块#define PICC_WRITE 0xA0 //写块#define PICC_DECREMENT 0xC0 //扣款#define PICC_INCREMENT 0xC1 //充值#define PICC_RESTORE 0xC2 //调块数据到缓冲区#define PICC_TRANSFER 0xB0 //保存缓冲区中数据#define PICC_HALT 0x50 //休眠///////////////////////////////////////////////////////////////////////MF522 FIFO长度定义/////////////////////////////////////////////////////////////////////#define DEF_FIFO_LENGTH 64 //FIFO size=64byte#define MAXRLEN 18///////////////////////////////////////////////////////////////////////MF522寄存器定义///////////////////////////////////////////////////////////////////// // PAGE 0#define RFU00 0x00#define CommandReg 0x01#define ComIEnReg 0x02#define DivlEnReg 0x03#define ComIrqReg 0x04#define DivIrqReg 0x05#define ErrorReg 0x06#define Status1Reg 0x07#define Status2Reg 0x08#define FIFODataReg 0x09#define FIFOLevelReg 0x0A#define WaterLevelReg 0x0B#define ControlReg 0x0C#define BitFramingReg 0x0D#define CollReg 0x0E#define RFU0F 0x0F// PAGE 1#define RFU10 0x10#define ModeReg 0x11#define TxModeReg 0x12#define RxModeReg 0x13#define TxControlReg 0x14#define TxAutoReg 0x15#define TxSelReg 0x16#define RxSelReg 0x17#define RxThresholdReg 0x18#define DemodReg 0x19#define RFU1A 0x1A#define RFU1B 0x1B#define MifareReg 0x1C#define RFU1D 0x1D#define RFU1E 0x1E#define SerialSpeedReg 0x1F// PAGE 2#define RFU20 0x20#define CRCResultRegM 0x21#define CRCResultRegL 0x22#define RFU23 0x23#define ModWidthReg 0x24#define RFU25 0x25#define RFCfgReg 0x26#define GsNReg 0x27#define CWGsCfgReg 0x28#define ModGsCfgReg 0x29#define TModeReg 0x2A#define TPrescalerReg 0x2B#define TReloadRegH 0x2C#define TReloadRegL 0x2D#define TCounterValueRegH 0x2E#define TCounterValueRegL 0x2F// PAGE 3#define RFU30 0x30#define TestSel1Reg 0x31#define TestSel2Reg 0x32#define TestPinEnReg 0x33#define TestPinValueReg 0x34#define TestBusReg 0x35#define AutoTestReg 0x36#define VersionReg 0x37#define AnalogTestReg 0x38#define TestDAC1Reg 0x39#define TestDAC2Reg 0x3A#define TestADCReg 0x3B#define RFU3C 0x3C#define RFU3D 0x3D#define RFU3E 0x3E#define RFU3F 0x3F///////////////////////////////////////////////////////////////////// //和MF522通讯时返回的错误代码///////////////////////////////////////////////////////////////////// #define MI_OK 0#define MI_NOTAGERR (1)#define MI_ERR (2)#define SHAQU1 0X01#define KUAI4 0X04#define KUAI7 0X07#define REGCARD 0xa1#define CONSUME 0xa2#define READCARD 0xa3#define ADDMONEY 0xa4#define SPIReadByte() SPIWriteByte(0)u8 SPIWriteByte(u8 byte);void SPI2_Init(void);#define SET_SPI_CS GPIO_SetBits(GPIOF,GPIO_Pin_0);#define CLR_SPI_CS GPIO_ResetBits(GPIOF,GPIO_Pin_0)#define SET_RC522RST GPIO_SetBits(GPIOF,GPIO_Pin_1);#define CLR_RC522RST GPIO_ResetBits(GPIOF,GPIO_Pin_1)void InitRc522(void);void Usart1_Send_String(unsigned char *str);void ClearBitMask(u8 reg,u8 mask);void WriteRawRC(u8 Address, u8 value);void SetBitMask(u8 reg,u8 mask);char PcdComMF522(u8 Command,u8 *pIn ,u8 InLenByte,u8 *pOut ,u8 *pOutLenBit);void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut );u8 ReadRawRC(u8 Address);void PcdAntennaOn(void);char PcdReset(void);char PcdRequest(unsigned char req_code,unsigned char *pTagType);void PcdAntennaOn(void);void PcdAntennaOff(void);char M500PcdConfigISOType(unsigned char type);char PcdAnticoll(unsigned char *pSnr);char PcdSelect(unsigned char *pSnr);char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);char PcdWrite(unsigned char addr,unsigned char *pData);char PcdRead(unsigned char addr,unsigned char *pData);char PcdHalt(void);void Reset_RC522(void);char PcdValue(u8 dd_mode,u8 addr,u8 *pValue);/////////////////////////////////////////////////////////////////////////////// ///////////////////////rc522.c:#include "sys.h"#include "rc522.h"#include "delay.h"void delay_ns(u32 ns){u32 i;for(i=0;i<ns;i++){__nop();__nop();__nop();}}u8 SPIWriteByte(u8 Byte){while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI2, Byte);while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);return SPI_I2S_ReceiveData(SPI2);}//SPIx 读写一个字节//TxData:要写入的字节//返回值:读取到的字节u8 SPI2_ReadWriteByte(u8 TxData){u8 retry=0;while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位{retry++;if(retry>200)return 0;}SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据retry=0;while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位{retry++;if(retry>200)return 0;}return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据}void SPI2_Init(void){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE );//PORTB时钟使能RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //IO-->PF0、PF1 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOF, &GPIO_InitStructure); //根据设定参数初始化PF0、PF1GPIO_ResetBits(GPIOF,GPIO_Pin_1); //PF1输出低//GPIO_SetBits(GPIOF,GPIO_Pin_0);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //定义波特率预分频的值:波特率预分频值为256SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI2, ENABLE); //使能SPI外设//SPI2_ReadWriteByte(0xff);//启动传输}void InitRc522(void){SPI2_Init();PcdReset();PcdAntennaOff();delay_ms(2);PcdAntennaOn();M500PcdConfigISOType( 'A' );}void Reset_RC522(void){PcdReset();PcdAntennaOff();delay_ms(2);PcdAntennaOn();}///////////////////////////////////////////////////////////////////////功能:寻卡//参数说明: req_code[IN]:寻卡方式// 0x52 = 寻感应区内所有符合14443A标准的卡// 0x26 = 寻未进入休眠状态的卡// pTagType[OUT]:卡片类型代码// 0x4400 = Mifare_UltraLight// 0x0400 = Mifare_One(S50)// 0x0200 = Mifare_One(S70)// 0x0800 = Mifare_Pro(X)// 0x4403 = Mifare_DESFire//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdRequest(u8 req_code,u8 *pTagType){char status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x07);SetBitMask(TxControlReg,0x03);ucComMF522Buf[0] = req_code;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x10)){*pTagType = ucComMF522Buf[0];*(pTagType+1) = ucComMF522Buf[1];}else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:防冲撞//参数说明: pSnr[OUT]:卡片序列号,4字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdAnticoll(u8 *pSnr){char status;u8 i,snr_check=0;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x00);ClearBitMask(CollReg,0x80);ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x20;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);if (status == MI_OK){for (i=0; i<4; i++){*(pSnr+i) = ucComMF522Buf[i];snr_check ^= ucComMF522Buf[i];}if (snr_check != ucComMF522Buf[i]){ status = MI_ERR; }}SetBitMask(CollReg,0x80);return status;}///////////////////////////////////////////////////////////////////////功能:选定卡片//参数说明: pSnr[IN]:卡片序列号,4字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdSelect(u8 *pSnr){char status;u8 i;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x70;ucComMF522Buf[6] = 0;for (i=0; i<4; i++){ucComMF522Buf[i+2] = *(pSnr+i);ucComMF522Buf[6] ^= *(pSnr+i);}CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);ClearBitMask(Status2Reg,0x08);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x18)){ status = MI_OK; }else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:验证卡片密码//参数说明: auth_mode[IN]: 密码验证模式// 0x60 = 验证A密钥// 0x61 = 验证B密钥// addr[IN]:块地址// pKey[IN]:密码// pSnr[IN]:卡片序列号,4字节//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = auth_mode;ucComMF522Buf[1] = addr;// for (i=0; i<6; i++)// { ucComMF522Buf[i+2] = *(pKey+i); }// for (i=0; i<6; i++)// { ucComMF522Buf[i+8] = *(pSnr+i); }memcpy(&ucComMF522Buf[2], pKey, 6);memcpy(&ucComMF522Buf[8], pSnr, 4);status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))){ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:读取M1卡一块数据//参数说明: addr[IN]:块地址// p [OUT]:读出的数据,16字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdRead(u8 addr,u8 *p ){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_READ;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x90))// { memcpy(p , ucComMF522Buf, 16); }{for (i=0; i<16; i++){ *(p +i) = ucComMF522Buf[i]; }}else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:写数据到M1卡一块//参数说明: addr[IN]:块地址// p [IN]:写入的数据,16字节//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdWrite(u8 addr,u8 *p ){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_WRITE;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){ status = MI_ERR; }if (status == MI_OK){//memcpy(ucComMF522Buf, p , 16);for (i=0; i<16; i++){ucComMF522Buf[i] = *(p +i);}CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }}return status;}///////////////////////////////////////////////////////////////////////功能:命令卡片进入休眠状态//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdHalt(void){u8 status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_HALT;ucComMF522Buf[1] = 0;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);return MI_OK;}///////////////////////////////////////////////////////////////////////用MF522计算CRC16函数/////////////////////////////////////////////////////////////////////void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ){u8 i,n;ClearBitMask(DivIrqReg,0x04);WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80);for (i=0; i<len; i++){ WriteRawRC(FIFODataReg, *(pIn +i)); }WriteRawRC(CommandReg, PCD_CALCCRC);i = 0xFF;do{n = ReadRawRC(DivIrqReg);i--;}while ((i!=0) && !(n&0x04));pOut [0] = ReadRawRC(CRCResultRegL);pOut [1] = ReadRawRC(CRCResultRegM);}///////////////////////////////////////////////////////////////////////功能:复位RC522//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdReset(void){//PORTD|=(1<<RC522RST);SET_RC522RST;delay_ns(10);//PORTD&=~(1<<RC522RST);CLR_RC522RST;delay_ns(10);//PORTD|=(1<<RC522RST);SET_RC522RST;delay_ns(10);WriteRawRC(CommandReg,PCD_RESETPHASE);WriteRawRC(CommandReg,PCD_RESETPHASE);delay_ns(10);WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363 WriteRawRC(TReloadRegL,30);WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);WriteRawRC(TxAutoReg,0x40);//必须要return MI_OK;}////////////////////////////////////////////////////////////////////////设置RC632的工作方式//////////////////////////////////////////////////////////////////////char M500PcdConfigISOType(u8 type){if (type == 'A') //ISO14443_A{ClearBitMask(Status2Reg,0x08);WriteRawRC(ModeReg,0x3D);//3FWriteRawRC(RxSelReg,0x86);//84WriteRawRC(RFCfgReg,0x7F); //4FWriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);delay_ns(1000);PcdAntennaOn();}else{ return 1; }return MI_OK;}///////////////////////////////////////////////////////////////////////功能:读RC632寄存器//参数说明:Address[IN]:寄存器地址//返回:读出的值/////////////////////////////////////////////////////////////////////u8 ReadRawRC(u8 Address){u8 ucAddr;u8 ucResult=0;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E)|0x80;SPIWriteByte(ucAddr);delay_ms(5);ucResult=SPIReadByte();delay_ms(5);SET_SPI_CS;return ucResult;}///////////////////////////////////////////////////////////////////////功能:写RC632寄存器//参数说明:Address[IN]:寄存器地址// value[IN]:写入的值void WriteRawRC(u8 Address, u8 value){u8 ucAddr;// u8 tmp;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E);SPIWriteByte(ucAddr);delay_ms(5);SPIWriteByte(value);delay_ms(5);SET_SPI_CS;// tmp=ReadRawRC(Address);//// if(value!=tmp)// printf("wrong\n");}///////////////////////////////////////////////////////////////////// //功能:置RC522寄存器位//参数说明:reg[IN]:寄存器地址// mask[IN]:置位值///////////////////////////////////////////////////////////////////// void SetBitMask(u8 reg,u8 mask){char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg,tmp | mask); // set bit mask}///////////////////////////////////////////////////////////////////// //功能:清RC522寄存器位//参数说明:reg[IN]:寄存器地址// mask[IN]:清位值///////////////////////////////////////////////////////////////////// void ClearBitMask(u8 reg,u8 mask){char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg, tmp & ~mask); // clear bit mask}//功能:通过RC522和ISO14443卡通讯//参数说明:Command[IN]:RC522命令字// pIn [IN]:通过RC522发送到卡片的数据// InLenByte[IN]:发送数据的字节长度// pOut [OUT]:接收到的卡片返回数据// *pOutLenBit[OUT]:返回数据的位长度///////////////////////////////////////////////////////////////////// char PcdComMF522(u8 Command,u8 *pIn ,u8 InLenByte,u8 *pOut ,u8 *pOutLenBit){char status = MI_ERR;u8 irqEn = 0x00;u8 waitFor = 0x00;u8 lastBits;u8 n;u16 i;switch (Command){case PCD_AUTHENT:irqEn = 0x12;waitFor = 0x10;break;case PCD_TRANSCEIVE:irqEn = 0x77;waitFor = 0x30;break;default:break;}WriteRawRC(ComIEnReg,irqEn|0x80);ClearBitMask(ComIrqReg,0x80); //清所有中断位WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存for (i=0; i<InLenByte; i++){ WriteRawRC(FIFODataReg, pIn [i]); }WriteRawRC(CommandReg, Command);// n = ReadRawRC(CommandReg);if (Command == PCD_TRANSCEIVE){ SetBitMask(BitFramingReg,0x80); } //开始传送//i = 600;//根据时钟频率调整,操作M1卡最大等待时间25msi = 2000;do{n = ReadRawRC(ComIrqReg);i--;}while ((i!=0) && !(n&0x01) && !(n&waitFor));ClearBitMask(BitFramingReg,0x80);if (i!=0){if(!(ReadRawRC(ErrorReg)&0x1B)){status = MI_OK;if (n & irqEn & 0x01){ status = MI_NOTAGERR; }if (Command == PCD_TRANSCEIVE){n = ReadRawRC(FIFOLevelReg);lastBits = ReadRawRC(ControlReg) & 0x07;if (lastBits){ *pOutLenBit = (n-1)*8 + lastBits; }else{ *pOutLenBit = n*8; }if (n == 0){ n = 1; }if (n > MAXRLEN){ n = MAXRLEN; }for (i=0; i<n; i++){ pOut [i] = ReadRawRC(FIFODataReg); } }}else{ status = MI_ERR; }}SetBitMask(ControlReg,0x80); // stop timer now WriteRawRC(CommandReg,PCD_IDLE);return status;}///////////////////////////////////////////////////////////////////////开启天线//每次启动或关闭天险发射之间应至少有1ms的间隔/////////////////////////////////////////////////////////////////////void PcdAntennaOn(void){u8 i;i = ReadRawRC(TxControlReg);if (!(i & 0x03)){SetBitMask(TxControlReg, 0x03);}}///////////////////////////////////////////////////////////////////////关闭天线/////////////////////////////////////////////////////////////////////void PcdAntennaOff(void){ClearBitMask(TxControlReg, 0x03);}///////////////////////////////////////////////////////////////////////功能:扣款和充值//参数说明: dd_mode[IN]:命令字// 0xC0 = 扣款// 0xC1 = 充值// addr[IN]:钱包地址// pValue[IN]:4字节增(减)值,低位在前//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdValue(u8 dd_mode,u8 addr,u8 *pValue){char status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];//u8 i;ucComMF522Buf[0] = dd_mode;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }if (status == MI_OK){memcpy(ucComMF522Buf, pValue, 4);//for (i=0; i<16; i++)//{ ucComMF522Buf[i] = *(pValue+i); }CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);unLen = 0;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);if (status != MI_ERR){ status = MI_OK; }}if (status == MI_OK){ucComMF522Buf[0] = PICC_TRANSFER;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }}return status;}art部分用的串口1,打印读写数据到串口调试助手,hex_to_str函数为16进制转换为字符格式,可以不转换,直接串口打印数据,串口调试助手需要勾选hex。
S50简介
非接触式IC卡与读写器之间无机械接触,避免了因接触读写而产生的各种故障(例如:由于粗暴插卡、非卡外物插入、灰尘或油污导致接触不良造成的故障)。此外,非接触式卡表面无裸露芯片,无须担心芯片脱落、静电击穿、弯曲损坏等问题,既便于卡片印刷,又提高了卡片的使用可靠性。
⑵操作方便
由于非接触通讯,读写器在10CM范围内就可以对卡片操作,所以不必插拨卡,非常方便用户使用。非接触式卡使用时没有方向性,卡片可以在任意方向掠过读写器表面,即可完成操作,这大大提高了每次使用的速度。
M1卡有16个区,每个区都有独立的两组密码KeyA/KeyB和区读写控制位,每个区互不相关.
在M1卡出厂时,KeyA/KeyB默认的密码都是12个F.
密码的验证是在卡内部进行的,读写器只负责给卡提供电并和卡通讯,读写器发送加密的密码到卡,卡内部进行解密验证并发返回值,读写器根据卡的返回值来判断验证是否通过.
名称
● ISOISO M1 IC S50卡(进口芯片国内封装)
●ISO MF1 IC S50卡(进口) Philips Mifare 1 S50卡●符合IEC/ISO 14443A空气接口协议
●可封装成白卡/印刷卡
●产品批号20100120-0018
RC522射频读卡器模块(MINI型)
RC522射频读卡器模块(MINI型)⼀、硬件:⼆、[主芯⽚介绍]MF RC522是应⽤于13.56MHz⾮接触式通信中⾼集成度的读写卡芯⽚,是NXP公司针对“三表”应⽤推出的⼀款低电压、低成本、体积⼩的⾮接触式读写卡芯⽚,是智能仪表和便携式⼿持设备研发的较好选择。
MF RC522利⽤了先进的调制和解调概念,完全集成了在13.56MHz下所有类型的被动⾮接触式通信⽅式和协议。
⽀持14443A兼容应答器信号。
数字部分处理ISO14443A帧和错误检测。
此外,还⽀持快速CRYPTO1加密算法,⽤语验证MIFARE系列产品。
MFRC522⽀持MIFARE系列更⾼速的⾮接触式通信,双向数据传输速率⾼达424kbit/s。
作为13.56MHz⾼集成度读写卡系列芯⽚家族的新成员,MF RC522与MF RC500和MF RC530有不少相似之处,同时也具备许多特点和差异。
它与主机间通信采⽤连线较少的串⾏通信,且可根据不同的⽤户需求,选取SPI、IIC或串⾏UART模式之⼀,有利于减少连线,缩⼩PCB板体积,降低成本。
三、[WMFRC522模块介绍]WMFRC522模块采⽤Philips MFRC522原装芯⽚设计读卡电路,使⽤⽅便,成本低廉,适⽤于设备开发、读卡器开发等⾼级应⽤的⽤户、需要进⾏射频卡终端设计/⽣产的⽤户。
本模块可直接装⼊各种读卡器模具。
模块采⽤电压为3.3V,通过SPI接⼝简单的⼏条线就可以直接与⽤户任何CPU主板相连接通信,可以保证模块稳定可靠的⼯作、读卡距离远;注:模块接⼝座可以按客户需求更改:⽬前提供UART TTL、RX232和RS485三种接⼝1、RC522接⼝芯⽚电路2、通信电路3、PCB效果4、焊接完后的效果图:4、固件:/********************************************************************************* @Brief : 测试522读写M1卡, 完成操作后PC6的LED闪烁⼀下,并打印到USART2上* @Param : None* @Retval : None*/u8 MFRC522Test(void){u8 i;static u8 WriteFlag;u8 CardType[2], CardSN[4];//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15u8 DefaultData[16] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x01,0xFE,0x01,0xFE};u8 DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};u8 DataD[4] = {0,0,0,0x01};u8 BlockData[16];LED0_OFF();BEEP_OFF();if(MI_OK != PcdRequest(PICC_REQALL, CardType)) //扫描卡{printf("IC Card Type: %x\n", *((u16 *)CardType));return 1;}if(MI_OK != PcdAnticoll(CardSN)) //防冲撞{printf(" IC Card SN: %x\n", *((u32 *)CardSN));return 2;}if(MI_OK != PcdSelect(CardSN)) //选定卡⽚return 3;if(MI_OK != PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, CardSN))//验证卡⽚密码 return 4;if(MI_OK != PcdRead(1, BlockData)) //读块return 5;for(i = 0; i < 4; i++)printf("%x", BlockData[i]);if(!WriteFlag){if(MI_OK != PcdWrite(1, DefaultData)) //写块return 6;WriteFlag = 1;printf("First Write Value\n");}if(MI_OK != PcdValue(PICC_DECREMENT, 1, DataD)) //扣款return 7;if(MI_OK != PcdRead(1, BlockData)) //读块return 8;printf("IC Card Type: %x\n", *((u16 *)CardType));printf(" IC Card SN: %x\n", *((u32 *)CardSN));printf("Select Card!\n");printf("Check Pass Word Ok!\n");printf("Data Value decrease!\n");for(i = 0; i < 4; i++)printf("%x", BlockData[i]);printf("\n");LED0_ON();BEEP_ON();return 0;}。
RC522通过SPI方式读写M1卡
1.准备工作战舰V3开发板,RC522模块为淘宝所买,赠送一张M1卡。
SPI方式实测可以读写。
2.RC522部分:rc522.h://///////////////////////////////////////////////////////////////////#include "sys.h"//MF522命令字/////////////////////////////////////////////////////////////////////#define PCD_IDLE 0x00 //取消当前命令#define PCD_AUTHENT 0x0E //验证密钥#define PCD_RECEIVE 0x08 //接收数据#define PCD_TRANSMIT 0x04 //发送数据#define PCD_TRANSCEIVE 0x0C //发送并接收数据#define PCD_RESETPHASE 0x0F //复位#define PCD_CALCCRC 0x03 //CRC计算///////////////////////////////////////////////////////////////////////Mifare_One卡片命令字/////////////////////////////////////////////////////////////////////#define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态#define PICC_REQALL 0x52 //寻天线区内全部卡#define PICC_ANTICOLL1 0x93 //防冲撞#define PICC_ANTICOLL2 0x95 //防冲撞#define PICC_AUTHENT1A 0x60 //验证A密钥#define PICC_AUTHENT1B 0x61 //验证B密钥#define PICC_READ 0x30 //读块#define PICC_WRITE 0xA0 //写块#define PICC_DECREMENT 0xC0 //扣款#define PICC_INCREMENT 0xC1 //充值#define PICC_RESTORE 0xC2 //调块数据到缓冲区#define PICC_TRANSFER 0xB0 //保存缓冲区中数据#define PICC_HALT 0x50 //休眠///////////////////////////////////////////////////////////////////////MF522 FIFO长度定义/////////////////////////////////////////////////////////////////////#define DEF_FIFO_LENGTH 64 //FIFO size=64byte#define MAXRLEN 18///////////////////////////////////////////////////////////////////////MF522寄存器定义///////////////////////////////////////////////////////////////////// // PAGE 0#define RFU00 0x00#define CommandReg 0x01#define ComIEnReg 0x02#define DivlEnReg 0x03#define ComIrqReg 0x04#define DivIrqReg 0x05#define ErrorReg 0x06#define Status1Reg 0x07#define Status2Reg 0x08#define FIFODataReg 0x09#define FIFOLevelReg 0x0A#define WaterLevelReg 0x0B#define ControlReg 0x0C#define BitFramingReg 0x0D#define CollReg 0x0E#define RFU0F 0x0F// PAGE 1#define RFU10 0x10#define ModeReg 0x11#define TxModeReg 0x12#define RxModeReg 0x13#define TxControlReg 0x14#define TxAutoReg 0x15#define TxSelReg 0x16#define RxSelReg 0x17#define RxThresholdReg 0x18#define DemodReg 0x19#define RFU1A 0x1A#define RFU1B 0x1B#define MifareReg 0x1C#define RFU1D 0x1D#define RFU1E 0x1E#define SerialSpeedReg 0x1F// PAGE 2#define RFU20 0x20#define CRCResultRegM 0x21#define CRCResultRegL 0x22#define RFU23 0x23#define ModWidthReg 0x24#define RFU25 0x25#define RFCfgReg 0x26#define GsNReg 0x27#define CWGsCfgReg 0x28#define ModGsCfgReg 0x29#define TModeReg 0x2A#define TPrescalerReg 0x2B#define TReloadRegH 0x2C#define TReloadRegL 0x2D#define TCounterValueRegH 0x2E#define TCounterValueRegL 0x2F// PAGE 3#define RFU30 0x30#define TestSel1Reg 0x31#define TestSel2Reg 0x32#define TestPinEnReg 0x33#define TestPinValueReg 0x34#define TestBusReg 0x35#define AutoTestReg 0x36#define VersionReg 0x37#define AnalogTestReg 0x38#define TestDAC1Reg 0x39#define TestDAC2Reg 0x3A#define TestADCReg 0x3B#define RFU3C 0x3C#define RFU3D 0x3D#define RFU3E 0x3E#define RFU3F 0x3F///////////////////////////////////////////////////////////////////// //和MF522通讯时返回的错误代码///////////////////////////////////////////////////////////////////// #define MI_OK 0#define MI_NOTAGERR (1)#define MI_ERR (2)#define SHAQU1 0X01#define KUAI4 0X04#define KUAI7 0X07#define REGCARD 0xa1#define CONSUME 0xa2#define READCARD 0xa3#define ADDMONEY 0xa4#define SPIReadByte() SPIWriteByte(0)u8 SPIWriteByte(u8 byte);void SPI2_Init(void);#define SET_SPI_CS GPIO_SetBits(GPIOF,GPIO_Pin_0);#define CLR_SPI_CS GPIO_ResetBits(GPIOF,GPIO_Pin_0)#define SET_RC522RST GPIO_SetBits(GPIOF,GPIO_Pin_1);#define CLR_RC522RST GPIO_ResetBits(GPIOF,GPIO_Pin_1)void InitRc522(void);void Usart1_Send_String(unsigned char *str);void ClearBitMask(u8 reg,u8 mask);void WriteRawRC(u8 Address, u8 value);void SetBitMask(u8 reg,u8 mask);char PcdComMF522(u8 Command,u8 *pIn ,u8 InLenByte,u8 *pOut ,u8 *pOutLenBit);void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut );u8 ReadRawRC(u8 Address);void PcdAntennaOn(void);char PcdReset(void);char PcdRequest(unsigned char req_code,unsigned char *pTagType);void PcdAntennaOn(void);void PcdAntennaOff(void);char M500PcdConfigISOType(unsigned char type);char PcdAnticoll(unsigned char *pSnr);char PcdSelect(unsigned char *pSnr);char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);char PcdWrite(unsigned char addr,unsigned char *pData);char PcdRead(unsigned char addr,unsigned char *pData);char PcdHalt(void);void Reset_RC522(void);char PcdValue(u8 dd_mode,u8 addr,u8 *pValue);/////////////////////////////////////////////////////////////////////////////// ///////////////////////rc522.c:#include "sys.h"#include "rc522.h"#include "delay.h"void delay_ns(u32 ns){u32 i;for(i=0;i<ns;i++){__nop();__nop();__nop();}}u8 SPIWriteByte(u8 Byte){while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI2, Byte);while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);return SPI_I2S_ReceiveData(SPI2);}//SPIx 读写一个字节//TxData:要写入的字节//返回值:读取到的字节u8 SPI2_ReadWriteByte(u8 TxData){u8 retry=0;while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位{retry++;if(retry>200)return 0;}SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据retry=0;while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位{retry++;if(retry>200)return 0;}return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据}void SPI2_Init(void){GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE );//PORTB时钟使能RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //IO-->PF0、PF1 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOF, &GPIO_InitStructure); //根据设定参数初始化PF0、PF1GPIO_ResetBits(GPIOF,GPIO_Pin_1); //PF1输出低//GPIO_SetBits(GPIOF,GPIO_Pin_0);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //定义波特率预分频的值:波特率预分频值为256SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI2, ENABLE); //使能SPI外设//SPI2_ReadWriteByte(0xff);//启动传输}void InitRc522(void){SPI2_Init();PcdReset();PcdAntennaOff();delay_ms(2);PcdAntennaOn();M500PcdConfigISOType( 'A' );}void Reset_RC522(void){PcdReset();PcdAntennaOff();delay_ms(2);PcdAntennaOn();}///////////////////////////////////////////////////////////////////////功能:寻卡//参数说明: req_code[IN]:寻卡方式// 0x52 = 寻感应区内所有符合14443A标准的卡// 0x26 = 寻未进入休眠状态的卡// pTagType[OUT]:卡片类型代码// 0x4400 = Mifare_UltraLight// 0x0400 = Mifare_One(S50)// 0x0200 = Mifare_One(S70)// 0x0800 = Mifare_Pro(X)// 0x4403 = Mifare_DESFire//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdRequest(u8 req_code,u8 *pTagType){char status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x07);SetBitMask(TxControlReg,0x03);ucComMF522Buf[0] = req_code;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x10)){*pTagType = ucComMF522Buf[0];*(pTagType+1) = ucComMF522Buf[1];}else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:防冲撞//参数说明: pSnr[OUT]:卡片序列号,4字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdAnticoll(u8 *pSnr){char status;u8 i,snr_check=0;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ClearBitMask(Status2Reg,0x08);WriteRawRC(BitFramingReg,0x00);ClearBitMask(CollReg,0x80);ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x20;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);if (status == MI_OK){for (i=0; i<4; i++){*(pSnr+i) = ucComMF522Buf[i];snr_check ^= ucComMF522Buf[i];}if (snr_check != ucComMF522Buf[i]){ status = MI_ERR; }}SetBitMask(CollReg,0x80);return status;}///////////////////////////////////////////////////////////////////////功能:选定卡片//参数说明: pSnr[IN]:卡片序列号,4字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdSelect(u8 *pSnr){char status;u8 i;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_ANTICOLL1;ucComMF522Buf[1] = 0x70;ucComMF522Buf[6] = 0;for (i=0; i<4; i++){ucComMF522Buf[i+2] = *(pSnr+i);ucComMF522Buf[6] ^= *(pSnr+i);}CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);ClearBitMask(Status2Reg,0x08);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x18)){ status = MI_OK; }else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:验证卡片密码//参数说明: auth_mode[IN]: 密码验证模式// 0x60 = 验证A密钥// 0x61 = 验证B密钥// addr[IN]:块地址// pKey[IN]:密码// pSnr[IN]:卡片序列号,4字节//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = auth_mode;ucComMF522Buf[1] = addr;// for (i=0; i<6; i++)// { ucComMF522Buf[i+2] = *(pKey+i); }// for (i=0; i<6; i++)// { ucComMF522Buf[i+8] = *(pSnr+i); }memcpy(&ucComMF522Buf[2], pKey, 6);memcpy(&ucComMF522Buf[8], pSnr, 4);status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))){ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:读取M1卡一块数据//参数说明: addr[IN]:块地址// p [OUT]:读出的数据,16字节//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdRead(u8 addr,u8 *p ){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_READ;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status == MI_OK) && (unLen == 0x90))// { memcpy(p , ucComMF522Buf, 16); }{for (i=0; i<16; i++){ *(p +i) = ucComMF522Buf[i]; }}else{ status = MI_ERR; }return status;}///////////////////////////////////////////////////////////////////////功能:写数据到M1卡一块//参数说明: addr[IN]:块地址// p [IN]:写入的数据,16字节//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdWrite(u8 addr,u8 *p ){char status;u8 unLen;u8 i,ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_WRITE;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)){ status = MI_ERR; }if (status == MI_OK){//memcpy(ucComMF522Buf, p , 16);for (i=0; i<16; i++){ucComMF522Buf[i] = *(p +i);}CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }}return status;}///////////////////////////////////////////////////////////////////////功能:命令卡片进入休眠状态//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdHalt(void){u8 status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];ucComMF522Buf[0] = PICC_HALT;ucComMF522Buf[1] = 0;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);return MI_OK;}///////////////////////////////////////////////////////////////////////用MF522计算CRC16函数/////////////////////////////////////////////////////////////////////void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut ){u8 i,n;ClearBitMask(DivIrqReg,0x04);WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80);for (i=0; i<len; i++){ WriteRawRC(FIFODataReg, *(pIn +i)); }WriteRawRC(CommandReg, PCD_CALCCRC);i = 0xFF;do{n = ReadRawRC(DivIrqReg);i--;}while ((i!=0) && !(n&0x04));pOut [0] = ReadRawRC(CRCResultRegL);pOut [1] = ReadRawRC(CRCResultRegM);}///////////////////////////////////////////////////////////////////////功能:复位RC522//返回: 成功返回MI_OK/////////////////////////////////////////////////////////////////////char PcdReset(void){//PORTD|=(1<<RC522RST);SET_RC522RST;delay_ns(10);//PORTD&=~(1<<RC522RST);CLR_RC522RST;delay_ns(10);//PORTD|=(1<<RC522RST);SET_RC522RST;delay_ns(10);WriteRawRC(CommandReg,PCD_RESETPHASE);WriteRawRC(CommandReg,PCD_RESETPHASE);delay_ns(10);WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363 WriteRawRC(TReloadRegL,30);WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);WriteRawRC(TxAutoReg,0x40);//必须要return MI_OK;}////////////////////////////////////////////////////////////////////////设置RC632的工作方式//////////////////////////////////////////////////////////////////////char M500PcdConfigISOType(u8 type){if (type == 'A') //ISO14443_A{ClearBitMask(Status2Reg,0x08);WriteRawRC(ModeReg,0x3D);//3FWriteRawRC(RxSelReg,0x86);//84WriteRawRC(RFCfgReg,0x7F); //4FWriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);delay_ns(1000);PcdAntennaOn();}else{ return 1; }return MI_OK;}///////////////////////////////////////////////////////////////////////功能:读RC632寄存器//参数说明:Address[IN]:寄存器地址//返回:读出的值/////////////////////////////////////////////////////////////////////u8 ReadRawRC(u8 Address){u8 ucAddr;u8 ucResult=0;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E)|0x80;SPIWriteByte(ucAddr);delay_ms(5);ucResult=SPIReadByte();delay_ms(5);SET_SPI_CS;return ucResult;}///////////////////////////////////////////////////////////////////////功能:写RC632寄存器//参数说明:Address[IN]:寄存器地址// value[IN]:写入的值void WriteRawRC(u8 Address, u8 value){u8 ucAddr;// u8 tmp;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E);SPIWriteByte(ucAddr);delay_ms(5);SPIWriteByte(value);delay_ms(5);SET_SPI_CS;// tmp=ReadRawRC(Address);//// if(value!=tmp)// printf("wrong\n");}///////////////////////////////////////////////////////////////////// //功能:置RC522寄存器位//参数说明:reg[IN]:寄存器地址// mask[IN]:置位值///////////////////////////////////////////////////////////////////// void SetBitMask(u8 reg,u8 mask){char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg,tmp | mask); // set bit mask}///////////////////////////////////////////////////////////////////// //功能:清RC522寄存器位//参数说明:reg[IN]:寄存器地址// mask[IN]:清位值///////////////////////////////////////////////////////////////////// void ClearBitMask(u8 reg,u8 mask){char tmp = 0x0;tmp = ReadRawRC(reg);WriteRawRC(reg, tmp & ~mask); // clear bit mask}//功能:通过RC522和ISO14443卡通讯//参数说明:Command[IN]:RC522命令字// pIn [IN]:通过RC522发送到卡片的数据// InLenByte[IN]:发送数据的字节长度// pOut [OUT]:接收到的卡片返回数据// *pOutLenBit[OUT]:返回数据的位长度///////////////////////////////////////////////////////////////////// char PcdComMF522(u8 Command,u8 *pIn ,u8 InLenByte,u8 *pOut ,u8 *pOutLenBit){char status = MI_ERR;u8 irqEn = 0x00;u8 waitFor = 0x00;u8 lastBits;u8 n;u16 i;switch (Command){case PCD_AUTHENT:irqEn = 0x12;waitFor = 0x10;break;case PCD_TRANSCEIVE:irqEn = 0x77;waitFor = 0x30;break;default:break;}WriteRawRC(ComIEnReg,irqEn|0x80);ClearBitMask(ComIrqReg,0x80); //清所有中断位WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存for (i=0; i<InLenByte; i++){ WriteRawRC(FIFODataReg, pIn [i]); }WriteRawRC(CommandReg, Command);// n = ReadRawRC(CommandReg);if (Command == PCD_TRANSCEIVE){ SetBitMask(BitFramingReg,0x80); } //开始传送//i = 600;//根据时钟频率调整,操作M1卡最大等待时间25msi = 2000;do{n = ReadRawRC(ComIrqReg);i--;}while ((i!=0) && !(n&0x01) && !(n&waitFor));ClearBitMask(BitFramingReg,0x80);if (i!=0){if(!(ReadRawRC(ErrorReg)&0x1B)){status = MI_OK;if (n & irqEn & 0x01){ status = MI_NOTAGERR; }if (Command == PCD_TRANSCEIVE){n = ReadRawRC(FIFOLevelReg);lastBits = ReadRawRC(ControlReg) & 0x07;if (lastBits){ *pOutLenBit = (n-1)*8 + lastBits; }else{ *pOutLenBit = n*8; }if (n == 0){ n = 1; }if (n > MAXRLEN){ n = MAXRLEN; }for (i=0; i<n; i++){ pOut [i] = ReadRawRC(FIFODataReg); } }}else{ status = MI_ERR; }}SetBitMask(ControlReg,0x80); // stop timer now WriteRawRC(CommandReg,PCD_IDLE);return status;}///////////////////////////////////////////////////////////////////////开启天线//每次启动或关闭天险发射之间应至少有1ms的间隔/////////////////////////////////////////////////////////////////////void PcdAntennaOn(void){u8 i;i = ReadRawRC(TxControlReg);if (!(i & 0x03)){SetBitMask(TxControlReg, 0x03);}}///////////////////////////////////////////////////////////////////////关闭天线/////////////////////////////////////////////////////////////////////void PcdAntennaOff(void){ClearBitMask(TxControlReg, 0x03);}///////////////////////////////////////////////////////////////////////功能:扣款和充值//参数说明: dd_mode[IN]:命令字// 0xC0 = 扣款// 0xC1 = 充值// addr[IN]:钱包地址// pValue[IN]:4字节增(减)值,低位在前//返回: 成功返回MI_OK///////////////////////////////////////////////////////////////////// char PcdValue(u8 dd_mode,u8 addr,u8 *pValue){char status;u8 unLen;u8 ucComMF522Buf[MAXRLEN];//u8 i;ucComMF522Buf[0] = dd_mode;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }if (status == MI_OK){memcpy(ucComMF522Buf, pValue, 4);//for (i=0; i<16; i++)//{ ucComMF522Buf[i] = *(pValue+i); }CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);unLen = 0;status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);if (status != MI_ERR){ status = MI_OK; }}if (status == MI_OK){ucComMF522Buf[0] = PICC_TRANSFER;ucComMF522Buf[1] = addr;CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) { status = MI_ERR; }}return status;}art部分用的串口1,打印读写数据到串口调试助手,hex_to_str函数为16进制转换为字符格式,可以不转换,直接串口打印数据,串口调试助手需要勾选hex。
M1卡区块控制位详解
M1卡区块控制位详解M1卡区块控制位详解Mifare 1S50/Mifare 1S70每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。
存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的,在存取控制中每个块都有相应的三个控制位,定义如下:块0: C10 C20 C30块1: C11 C21 C31块2: C12 C22 C32块3: C13 C23 C33三个控制位以正和反两种形式存在于存取控制字节中,决定了该块的访问权限(如进行减值操作必须验证KEY A,进行加值操作必须验证KEY B,等等)。
三个控制位在存取控制字节中的位置,以块0为例:注意高字节和低字节顺序不同。
(一),以常用设置"08 77 8F 69"控制条件为例,先搞清楚它――具有的访问权限。
1、对"08 77 8F 69"值进行计算,该值定位于各区块3的6,7,8,9四个字节内,字节6=08,字节7=77,字节8=8F,字节9=69(默认值,不予计算)。
2、例如:字节6=08,对应其二进制值=00001000,则对6,7,8这三个字节进行二进制转换结果见下表:字节6 = 0 0 0 0 1 0 0 字节7 = 0 1 1 1 0 1 1 字节8 = 1 0 0 0 1 1 10 1 13、参照表2及表4算法,字节6的全部二进制值取反,字节7的低四位二进制值取反,字节8不变,得到:字节号 对应二进制值位置 高4位 位置 低4位 字节6字节7字节8 0 0 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 1 1 1 1 C2Y C1Y C3Y 1 1 1 1 0 1 1 1 1 0 0 0 C1Y C3Y C2Y 0 1 1 1 1 0 0 0 1 1 1 1 所属块位 块3块2块1块0 块3块2块1块04、对以上6,7,8字节的存取/控制二进制已取反值,依照表2,表4块位转换为各块控制值,如下表:块3位 字节7,字节6,字节8 = C13,C23,C33 = C1Y ,C2Y ,C3Y = 0 1 1 块2位 块1位 块0位 字节7,字节6,字节8 = C12,C22,C32 = C1Y ,C2Y ,C3Y = 1 1 0 字节7,字节6,字节8 = C11,C21,C31 = C1Y ,C2Y ,C3Y = 1 1 0 字节7,字节6,字节8 = C10,C20,C30 = C1Y ,C2Y ,C3Y = 1 1 0注意:1、高4位的各块值=低4位的各块值时,其值可用。
非接触IC卡物理结构(S50)
-----
4
16
可改写
16
ASCII
李四
17
可改写
16
ASCII
王五
18
可改写
16
ASCII
20070910
19
密钥区不能存放其它信息
----
-----
5
20
可改写
16
ASCII
20070910
21
可改写
16
ASCII
20080823
22
可改写
23
密钥区不能存放其它信息
----
-----
6
24
53454454534554
10
可改写
16
ASCII
Wereeeerweeww6576
11
密钥区不能存放其它信息
----
-----
3
12
可改写
16
ASCII
76767676767676767
13
可改写
16
ASCII
12AABDCDDEEADFADE
14
可改写
16
ASCII
13ACCB
15
密钥区不能存放其它信息
可改写
8
ASCII
30000(小数二位)
25
可改写
8+8
ASCII
30000 20080818
26
可改写
27
密钥区不能存放其它信息
----
-----
7
28
可改写
4
Hex
23600
29
可改写
16
ASCII
ICID卡知识
ICID卡知识
IC卡的种类ID卡双频卡
IC:
M1S50
M1卡=物业发的卡。
0扇区的0块是不可以更改的。
适用于80%的系统。
缺陷不可更改卡号,也就是说,除非有计算软件就发卡,
M1卡:使用的俩个前提:
卡是2张我的卡在什么情况用于M1卡卡号密码是否一样0扇区0块8位是卡号
后2位是效验(所有卡号都是不一样的,也是随机的)通过卡号算出所有扇区第3块密码密码分为KEYa前12个后12个数据KEYb中间密码控制位固定
通过卡号算出AB密码
确定自己的软件能算出你们的系统。
你们的系统,不是一卡一密的计算。
或者是一卡多密的【密码都是一样的】
UID:适合极小部分的系统使用,因为他没有任何防火墙
CUID:常用的过防火墙(解码后可以格式化)。
FUID:常用的卡,但是只能写入一次数据,有数据的部分,是不可更改的。
UFUID:写入数据后,可以锁定0扇区0块,实现和M1卡一样的。
用卡顺序:UID、cuid、ufuid或fuid.
ID卡
常用:8210、5577(有些卡读取后要求只能用5577卡)、过防火墙卡(8268/8310)其他类别不用考虑。
ID没有任何可修改的必要,ID卡只有卡号、防火墙区分!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第26卷 第12期2004年12月武 汉 理 工 大 学 学 报JOURNALOFWUHANUNIVERSITYOFTECHNOLOGYVol.26 No.12 Dec.2004MIFARE 非接触式IC 卡读卡器的设计构架研究严雄武,梁楚樵(武汉理工大学信息工程学院,武汉430070)摘 要: 非接触式IC 卡技术,成功地将射频识别技术和IC 卡技术结合起来。
其中非接触式IC 卡读卡器是非接触式IC 卡技术应用的关键之一。
文中介绍的非接触式IC 卡读卡器是以射频识别技术为基础,以MIFARE 卡作为非接触式IC读卡器识别对象,根据IS O 14443A 协议,采用非接触式IC 卡读卡器核心读写模块R C 500和R ISC 指令单片机来设计的。
简要介绍了非接触式IC 卡内部结构和工作原理,详细阐述了非接触式IC 卡读卡器硬件电路设计和软件开发。
该读卡器性能稳定,功耗低,抗干扰能力强,读写距离可达100m m 。
关键词: 非接触式IC 卡; R C 500; IS O 14443A ; 读卡器中图分类号: TP 368.1文献标识码: A 文章编号:1671-4431(2004)12-0089-03StudyontheFrameofMIFAREContact┐lessICCardReaderYANXiong-wu,LIANGChu-qiao(SchoolofInformationEngineering,WuhanUniversityofTechnology,Wuhan430070,China)Abstract: Thetechnologyofcontact-lessICcardisatechnologythatcombinestheradiofrequencyidentificationwiththeICcardtechnology.Contact-lessICcardreaderisoneofthekeyapplicationofICcard.BasedontechnologyofradiofrequencyidentificationandISO14443protocol,amethodusedtodesigncontact-lessICcardreaderwaspresentedbyusingthecoremoduleofcontact-lessICcardreaderandRISCsinglechipmicroprocessorandbytakingtheMIFAREcardastheobjectofidentification.Theinternalstructureofcontact-lessICcardanditsoperationalprinciplewasintroducedbriefly.Thedesignsofhardwareandsoftwareweredescribedindetail.Thereaderhasmanygoodfeatures,suchasreliability,lowpowerconsumptionandhighperformanceofanti-interference.Itsoperationdistancecanreachabout100mm.Keywords: contact-lessICcard; RC500; ISO14443A; reader收稿日期:2004-07-05.作者简介:严雄武(1976-),男,硕士生.E-mail:yxw2008@21cn.com非接触式IC卡技术,成功地将射频识别技术和IC卡技术结合起来,解决了无源、免接触这一难题。
应答器和阅读器是射频识别系统的重要组成部分,应答器也称邻近卡PICC(ProximityCard),是射频识别系统真正的数据载体,即IC卡。
阅读器也称邻近耦合设备PCD(ProximityCouplingDevice),具有读写功能,即读卡器。
文中介绍的非接触式IC卡读卡器是将PHILIPS公司的MF1ICS50射频IC卡作为系统应答器来设计的。
该读卡器采用串行异步通信方式,具有功耗低、抗干扰能力强等特点。
1 非接触式IC 卡内部结构和工作原理MIFARE卡的电气部分只由一个天线和ASIC(特殊应用IC)组成。
卡片内无任何电源,仅有一个LC串联谐振电路,其频率与IC卡读卡器发射的频率相同,为13.56MHz。
工作时的电源能量由IC卡读卡器天线发送无线电载波信号耦合到卡片上的天线而产生电压,当电压达到2V时,卡片中的芯片将卡内数据发送出去或接收基站对卡片的操作[1]。
2 读卡器硬件电路设计2.1 读卡器电路组成图1 读卡器电路组成原理框图非接触式IC卡读卡器的硬件电路主要包括:微处理器PIC16F876、射频IC卡读写模块MFRC500、通信转换模块、天线电路等,其原理见图1。
其中,非接触式IC卡读写模块MFRC500是整个读卡器的核心,它将完成读写非接触式IC卡的所有必需功能,包括RF信号的产生、调制、解调、安全认证和防重叠等[2]。
微处理器MCU是通过对非接触式IC卡读写模块RC500内核特殊的内存寄存器的读写来控制RC500的。
读取RC500,一般是指向MIFARE卡请求。
RC500实际上是MCU与射频卡之间进行信息交换的媒介。
任何卡片上数据读写均须通过RC500来传递。
传送不同类型的指令给RC500,就能实现对RC500的控制。
RC500与非接触式IC卡之间能量的传递和数据双向传输的过程是初级和次级2个线圈之间的耦合过程,从读卡器发射给卡的数据信息在调制前采用的是米勒编码,而从卡到读卡器的数据信息采用的是曼彻斯特编码。
2.2 读卡器天线及影响天线读写距离的因素电感耦合式射频识别系统的读卡器天线用于产生磁通量,而磁通量用于向非接触式IC卡提供电源并在读卡器与非接触式IC卡之间传输信息。
因此,对读卡器天线的构造就有3个基本要求:1)使天线线圈的电流最大,用于产生最大的磁通量;2)功率匹配,最大程度地利用产生磁通量的可用能量;3)足够的带宽,无失真地传送用数据调制的载波信号。
品质因数Q和谐振频率是电感耦合式射频识别系统读卡器天线的特征值,由于品质因数Q会影响天线读写距离,所以是天线设计中的一个重要参数,它可以通过电感线圈的电抗与电阻的比值计算出来[3],即Q=(2πf0燈Lcoil)/Rcoil 较高的品质因数,会得到较高的读卡器天线电压,可增加应答器即IC卡的能量传输。
与之相反,天线的传输带宽与品质因数Q值成反比。
选择的品质因数过高,会导致带宽缩小,从而明显地减弱应答器接收到的调制边带。
此外,由于MIFARE卡是无源非接触式IC卡,其能量是通过天线感应来的。
而且由于受到卡形状的限制,卡中不可能封装很大的天线,使得接收的能量较小,从而决定了读卡器天线读写距离很短,一般在100mm以内。
3 读卡器软件设计读卡器软件设计是使用PIC汇编程序来完成对MIFARE卡的操作,包括:主控程序、PIC单片机初始化、读卡器核心模块RC500初始化、RC500读写子程序、防冲突子程序、数据块操作子程序等[4]。
图2 读卡器与MIFARE卡通信流程图PIC单片机和MIFARE卡进行通信是通过天线发送协议ISO14443A所规定的指令代码和数据格式来实现的。
例如向卡片发送数据是通过向读卡器核心模块RC500内的FIFOData寄存器写入待发送数据,Command寄存器放入命令Transceive的代码0x1e,RC500就会将数据发送出去,卡中返回数据则存放在FIFO-Data寄存器中,由PIC单片机进行操作。
读卡器发Request命令给所有在天线场范围内的IC卡,通过防冲突循环,得到一张卡的序列号,选择此卡进行鉴别,通过后对存储器进行操作,通信流程如图2所示[5]。
典型交易时间不超过100ms。
读卡器对IC卡的操作流程如下:1)复位应答(answertorequest) MIFARE射频卡的通讯协议和通讯波特率是定义好的,当有卡片进入读卡器的操作范围时,读卡器以特定的协议与它通讯,以确定该卡是否为MIFARE射频卡,即验证卡片类型;09 武 汉 理 工 大 学 学 报 2004年12月图3 比特防冲突帧的位组织与传送2)防冲突机制(anticollisionloop) 当有多张卡进入读卡器天线感应范围时,防冲突机制将启动,会从多张卡中选择一张卡进行操作,未选中的则处于空闲模式等待下一次选卡,该过程会返回被选卡的序列号。
非接触式IC卡系统为了实现防冲突机制,采用位结构防冲突循环来解决冲突问题,并专门设计了防冲突指令。
标准指令结构包括7个字节长度数据,分为2部分:(1)读卡器传输给IC卡的数据为第1部分,包括1个字节的操作码SEL,1个字节的有效位个数NVB和卡序列号UID,第1部分数据最小长度为16位,最大长度为55位;(2)IC卡返回给读卡器的数据为第2部分,是IC卡返回的卡序列号。
如图3所示。
指令的工作流程是:(1)读卡器分配防冲突命令SEL的代码为93,有效位个数NVB代码为20(表示读卡器不发送卡序列号,并强制所有有效的IC卡返回各自完整的卡序列号)。
读卡器发送93和20,所有有效的IC卡返回各自完整的卡序列号。
如果有多于一张的IC卡响应,冲突就会出现;(2)读卡器应确认发生冲突的第1位的位置,读卡器分配有效位个数,其恒等于冲突前读卡器接收到的卡序列号位个数加1。
读卡器发送操作码93、有效位个数、冲突前接收到的有效卡序列号和一位“1”。
只有与读卡器发送序列号内容相同的IC卡才返回卡序列号剩余部分;(3)如果继续有冲突出现,重复步骤(2),最大循环次数为32。
如果没有冲突出现,读卡器分配有效位个数NVB代码为70(表示读卡器发送完整的卡序列号),和这40位卡序列号匹配的IC卡返回选择认可SAK,IC卡从准备就绪状态进入激活状态。
3)选择卡片(selecttag) 选择被选中卡的序列号,并同时返回卡的容量代码。
4)3次互相确认(3passauthentication) 选定要处理的卡片之后,读卡器就确定要访问的扇区号,并对该扇区密码进行密码校验,在3次相互认证之后就可以通过加密流进行通讯。
在选择另一扇区时,则必须进行另一扇区密码校验。
5)对数据块的操作 包括读块、写块、加值、减值操作、存储、传输、中止。
存储是将块中的内容存到数据寄存器中;传输则是将数据寄存器中的内容写入块中;中止是将卡置于暂停工作状态。
程序设计中应注意的问题:1)IC卡向读卡器发送数据帧是低位在前,高位在后,因此读卡器核心模块RC500内的FIFOData寄存器先接收到的是低位数据,后接收到的是高位数据;2)要满足相邻2个REQA命令的起始位之间的最小时间要求,即请求保护时间值为7000/f,射频场的频率f=13.56MHz;3)在读卡器寻卡过程中,可间断地打开和关闭射频输出,或通过设置RC500内Control寄存器的StandBy位,进入软件掉电模式,这样可降低读卡器功耗;4)通过添加监视定时器WDT和软件陷阱来防止程序失控,可提高系统抗干扰能力。