目录

  • 1 源码
  • 2 操作对象是什么?
    • 2.1 对象
      • 2.1.1 使用硬件
        • 2.1.1.1 RC522
        • 2.1.1.2 主控
        • 2.1.1.3 IC卡
      • 2.1.2 电路
      • 2.1.3 对象说明
        • 2.1.3.1 IC卡S50
        • 2.1.3.2 MFRC522
        • 2.1.3.3 STM32F103C8T6
  • 3 如何通讯
    • 3.1 射频接口
      • 3.1.1 IC卡的能量来源
      • 3.1.2 MFRC522如何与IC卡通信
    • 3.2 SPI接口
  • 4 软件结构
    • 4.1 MFRC522层
    • 4.2 Mifare1层
  • 5 源码实现
    • 5.1 串口助手发送的指令
    • 5.2 IC块的使用
      • 5.2.1 作用布局
    • 5.3 相关操作
      • 5.3.1 初始化卡
      • 5.3.2 尝试重复初始化
      • 5.3.3 读取卡
      • 5.3.4 减值
      • 5.3.5 加值
      • 5.3.6 将卡反初为白卡(恢复默认密码)

1 源码

不藏着掖着,直接上代码
链接: https://gitee.com/H0x9DEFA478/ic_mifare1-mfrc522.git.

2 操作对象是什么?

“废话,当然是IC卡了!” ,话可不能怎么说,我们得深入了解,至少的知道操作的IC卡到底是个什么东东,要操作具体内容是什么。

2.1 对象

2.1.1 使用硬件

2.1.1.1 RC522


图是网上随便找的图,这是我使用的模块,硬件电路已经接成SPI模式了

2.1.1.2 主控

主控是STM32F103C8T6,为什么是它,我手里的板子只有它是有排座引出引脚的。

2.1.1.3 IC卡

一张S50白卡。

2.1.2 电路

这玩意还需要电路?直接硬件SPI怼起来。

这是我的硬件连接

VCC----------3.3V--------3.3V

PA9----------------------RST

PA8----------------------IRQ (本例不使用,可不接)

PB14---------------------MISO (注意 不要接错)

PB15---------------------MOSI (注意 不要接错)

PB13---------------------SCK

PB12---------------------SDA(CS)

除了这些,还需要PA11,PA12用作USB功能,单片机用USB虚拟串口与电脑通信

2.1.3 对象说明

2.1.3.1 IC卡S50

M1卡是常见的IC卡类型, 而S50是M1卡的其中一种。

其内部可以存储1KB的数据。显而易见,我们就是要操作这1KB的数据


这是S50卡手册中对这1KB的描述,分为16个扇区,每个扇区4个块,每个块16字节。
可以发现,开头(图片底部的扇区)的扇区比较特殊,根据描述这个块出厂是被固化的,不可修改,用于存放UID之类的。
每个扇区尾部(第四个块)都有一个特殊的块,用来存放密钥A密钥B控制字控制字控制着它所在块的访问条件,这个里面的内容可以不先深究,暂且只需要知道它的默认值是FF 07 80 69 就行,对于这个控制字,代表这这个扇区仅需要验证密钥A就能随便访问整个扇区(读,写,增值减值等),其他控制字类型可以通过S50的说明文档找到。 剩下的就是数据块了,可以被我们自由使用的块。
具体怎么读写这些数据放到后面说。

2.1.3.2 MFRC522

用于与IC卡通信,就是一堆寄存器操作。这个玩意的通信方式有SPI,IIC,UART三种(我的代码给出了SPI和IIC的接口,但IIC的没有测试)

一翻RC522的手册,一看寄存器直接蒙了。这么那么多寄存器,我参考了一些网上的代码,发现都是同源的,操作基本都一致。我多次实验过后发现对于操作M1卡的初始化,只需要初始化一个寄存器就行,没错!就一个。这个后面会提到。

2.1.3.3 STM32F103C8T6

我觉得这个已经不需要说明

3 如何通讯

感觉也是废话,当然是用SPI通讯啊。不过看代码时要分清楚哪些是控制IC卡的通讯,哪些仅仅只是MCU与RC522之间的通讯。

3.1 射频接口

这里并不解释射频的底层原理(其实是我也不会,哈哈),但有一些基本的还是要知道的。

3.1.1 IC卡的能量来源

当然是从射频载波得到,频率为13.56MHz。为什么提到这个?MFRC522是可以控制载波是否开启的,也就是说我可以顺带控制IC卡是否有电。

3.1.2 MFRC522如何与IC卡通信

它们两个之间的通信也是通过载波进行,通过控制载波幅度来通信。(至于怎么控制的,我也不知道)。只需要知道这两者之间的通信是类似于串口的通讯方式,只不过物理层面是通过射频。

3.2 SPI接口

???

4 软件结构

谁不喜欢一层一层的结构呢?
软件分为Mifare1层MFRC522层Mifare1层负责将用户操作转为与IC卡操作的通讯流,在通过MFRC522层传到RC522上,再由RC522与IC卡通讯。
上层:Mifare1层
底层:MFRC522层

4.1 MFRC522层

此层负责将底层(SPI)与IC卡通讯连接起来,向底层调用SPI读写函数,向顶层提供IC卡读写函数。

具体代码见源码。下面为使用时需要包含的头文件。

#ifndef __MFRC522_H_
#define __MFRC522_H_
#include "H_Type.h"#define vMFRC522_ProtocolType_ISO14443_A  1#define vMFRC522_LL_Function_Type_SPI     1
#define vMFRC522_LL_Function_Type_IIC     2#define vMFRC522_MFAuthent_AuthentType_A  1
#define vMFRC522_MFAuthent_AuthentType_B  2//初始化时参数TxSequenceBuffer的长度
#define vMFRC522_TxSequenceBufferLength   19//初始化时参数RxSequenceBuffer的长度
#define vMFRC522_RxSequenceBufferLength   vMFRC522_TxSequenceBufferLengthtypedef struct{int Type;//底层传输类型void (*Delay)(int);//延时调用void (*Reset)();//复位调用union{void (*Transfer_SPI)(void*,void*,int,int);//传输序列 (发送序列,接收序列,长度,传输速度(0:高速 其他:低速))struct{int (*Write)(Hbyte,Hbyte*,int);//底层iic写操作 返回 0:成功 其他:失败 (7位器件地址,发送数据,发送数据长度)int (*Read)(Hbyte,Hbyte*,int,Hbyte*,int);//底层iic读操作 返回 0:成功 其他:失败 (7位器件地址,发送数据,发送数据长度,接收数据,接收数据长度)Hbyte deviceAddr;//器件7位地址}Transfer_IIC;}TransferSequence;}MFRC522_LL_Function;typedef struct _MFRC522{int ProtocolType;void* TxSequenceBuffer;//发送缓存void* RxSequenceBuffer;//接收缓存struct{Hbyte (*ReadReg)(struct _MFRC522*,Hbyte);void (*ReReadRegToArray)(struct _MFRC522*,Hbyte,Hbyte*,int);void (*ReadRegArray)(struct _MFRC522*,Hbyte,Hbyte*,int);void (*WriteReg)(struct _MFRC522*,Hbyte,Hbyte);void (*ReWriteRegFromArray)(struct _MFRC522*,Hbyte,Hbyte*,int);void (*WriteRegArray)(struct _MFRC522*,Hbyte,Hbyte*,int);}StaticFunction;int LL_Speed;MFRC522_LL_Function LL_Function;int MFCrypto1On;Hbyte Version;}MFRC522;//操作返回结果 #define vMFRC522_Result_RecvTimeOut                                4            //读取超时
#define vMFRC522_Result_RecvTooLong                                3            //接收数据过长
#define vMFRC522_Result_NoCard                                     2            //无响应 未发现卡
#define vMFRC522_Result_ParamError                                 1            //参数错误
#define vMFRC522_Result_Ok                                         0            //操作无错误
#define vMFRC522_Result_Error                                      -1           //出现错误 此情况下IC通信已经无法继续下去且无法恢复,需要复位后再次尝试通信//============================================================================================================================================
//
// 提供给外部的方法
//
//============================================================================================================================================/*** @brief 初始化RC522* @param _this 未使用的句柄* @param LL_Function 底层相关回调与信息* @param TxSequenceBuffer 底层发送缓存 长度vMFRC522_TxSequenceBufferLength字节* @param RxSequenceBuffer 底层接收缓存 长度vMFRC522_RxSequenceBufferLength字节* @param Type 协议类型 vMFRC522_ProtocolType_ISO14443_A可选* @return 返回执行结果*/
int MFRC522_Init(MFRC522* _this,MFRC522_LL_Function* LL_Function,void* TxSequenceBuffer,void* RxSequenceBuffer,int ProtocolType);/*** @brief 复位RC522 在通信出现错误时可以使用 复位后开启载波* @param _this RC522句柄* @return 无*/
void MFRC522_Reset(MFRC522* _this);/*** @brief 向卡发送数据* @param _this RC522句柄* @param TxData 发送的数据指针* @param TxBitLength 发送的长度 单位Bit 低位在前* @param WaitTime 最大等待时间* @return 返回执行结果*/
int MFRC522_Transmit(MFRC522* _this,Hbyte* TxData,Hbyte TxBitLength,int WaitTime);/*** @brief 接收卡发来的数据* @param _this RC522句柄* @param RxData 容纳接收数据的空间指针* @param MaxRxBitLengthPtr 最大接收长度 单位Bit* @param RxBitLengthPtr 用于返回接收到的长度 单位Bit 低位在前* @param WaitTime 最大等待时间* @return 返回执行结果*/
int MFRC522_Receive(MFRC522* _this,Hbyte* RxData,Hbyte MaxRxBitLengthPtr,Hbyte* RxBitLengthPtr,int WaitTime);/*** @brief 发送后接收数据* @param _this RC522句柄* @param TxData 发送的数据指针 *这个空间可与RxData为同一个* @param TxBitLength 发送的长度 单位Bit 低位在前* @param RxData 容纳接收数据的空间指针 *这个空间可与RxData为同一个* @param MaxRxBitLengthPtr 最大接收长度 单位Bit* @param RxBitLengthPtr 用于返回接收到的长度 单位Bit 低位在前* @param WaitTime 最大等待时间* @return 返回执行结果*/
int MFRC522_Transceive(MFRC522* _this,Hbyte* TxData,Hbyte TxBitLength,Hbyte* RxData,Hbyte MaxRxBitLengthPtr,Hbyte* RxBitLengthPtr,int WaitTime);/*** @brief 进行三轮认证* @param _this RC522句柄* @param SerialNumber 卡ID* @param BlockAddr 要验证的块地址* @param AuthentType 要验证的密码类型 vMFRC522_MFAuthent_AuthentType_A与vMFRC522_MFAuthent_AuthentType_B可选* @param Password 密码序列* @return 返回执行结果*/
int MFRC522_MFAuthent(MFRC522* _this,Hbyte* SerialNumber,Hbyte BlockAddr,int AuthentType,Hbyte* Password);/*** @brief 清除MFCrypto1On位 对一张卡处理完成后调用一次(清除加密状态)* @param _this RC522句柄* @return 无*/
void MFRC522_ClearMFCrypto1On(MFRC522* _this);//============================================================================================================================================
//
// 提供给外部的方法(不一定是顶层必要的方法)
//
//============================================================================================================================================/*** @brief 获取RC522版本号 可使用这个方法判定RC522是否存在* @param _this RC522句柄* @return 版本号*/
Hbyte MFRC522_Version(MFRC522* _this);/*** @brief 验证RC522是否存在* @param _this RC522句柄* @return 返回执行结果*/
int MFRC522_IsExist(MFRC522* _this);/*** @brief 设置RC522载波状态 可在空闲时关闭载波 节省能源消耗* @param _this RC522句柄* @param IsEn 是否使能载波* @return 无*/
void MFRC522_SetTxStatus(MFRC522* _this,int IsEn);#endif //__MFRC522_H_

MFRC522_Init(MFRC522* _this,MFRC522_LL_Function* LL_Function,void* TxSequenceBuffer,void* RxSequenceBuffer,int ProtocolType)中,会将句柄内部的一些函数指针指向对应的函数,以适应SPI或IIC方式,所有的底层调用通过LL_Function传入,这样即使有多个RC522需要控制,只需要创建多个句柄,分别在初始化的时候传入不同的LL_Function就行了。

//初始化寄存器
static void RegInit(MFRC522* _this){//ISO14443Aif(_this->ProtocolType==vMFRC522_ProtocolType_ISO14443_A){RegModify(_this,vMFRC522_RFCfgReg,vMFRC522_RFCfgReg_RxGain_Msk,0x7U<<vMFRC522_RFCfgReg_RxGain_Pos);//接收48dB//发送接收之间冷却延时设置RegModify(_this,vMFRC522_RxSelReg,vMFRC522_RxSelReg_RxWait_Msk,0x01U<<vMFRC522_RxSelReg_RxWait_Pos);//调制发送信号为100%ASK_this->StaticFunction.WriteReg(_this,vMFRC522_TxASKReg,vMFRC522_TxASKReg_Force100ASK);}}

在初始化方法中,void RegInit(MFRC522* _this)被调用。里面负责寄存器初始化。可以发现,里面有三个寄存器被修改。但只有一个寄存器是必须的,其他是可选的(一些无关紧要的设置),必须的寄存器是vMFRC522_TxASKReg,要将它的bit6置为1。

这个底层文件提供了直接(对于高层来说)与IC卡通讯的函数,还要一个三轮认证密码的数int MFRC522_MFAuthent(MFRC522* _this,Hbyte* SerialNumber,Hbyte BlockAddr,int AuthentType,Hbyte* Password),因为NXP官方并不公开三轮认证的加密算法(不然只需要与IC卡通讯的方法就足够了)。NXP只给射频芯片上加了个密码验证的功能,由RC522来完成认证过程,所以提供了这个函数来使用这个功能(不然这个功能应该是属于上层的)。认证完毕后,通信的数据也不需要我们自己加密,而是由RC522加密发送的数据,解密接收的数据。

4.2 Mifare1层

此层负责将用户想对卡的操作转换成通讯流通过底层的MFRC522层传送到IC卡上,完成操作。

具体代码见源码。下面为使用时需要包含的头文件。

#ifndef __IC_Mifare1_H_
#define __IC_Mifare1_H_
#include "H_Type.h"typedef struct{Hbyte* SerialNumber;int SerialNumberLength;Hbyte SAK;Huint16 ATQA;
}IC_Mifare1_CommunicationCallback_Param;typedef struct{void* v;//底层句柄//必须实现int (*Reset)(void*);//复位底层int (*Transmit)(void*,Hbyte*,Hbyte,int);//发送数据 (底层句柄,发送数据,发送位长度,最大等待时间)int (*Receive)(void*,Hbyte*,Hbyte,Hbyte*,int);//接收数据 (底层句柄,接收数据,最大接收位长度,接收位长度,最大等待时间)int (*Transceive)(void*,Hbyte*,Hbyte,Hbyte*,Hbyte,Hbyte*,int);//发送接收数据 (底层句柄,发送数据,发送位长度,接收数据,最大接收位长度,接收位长度,最大等待时间)int (*MFAuthent)(void*,Hbyte*,Hbyte,int,Hbyte*);//三轮认证 密钥认证 (底层句柄,卡ID,块地址,密钥)//可选实现(如果不需要 固定返回vIC_Mifare1_Result_Ok)int (*CallBeforeProbeCard)(void*);//在卡检测之前被调用int (*CallAfterHaltCard)(void*);//在卡操作完成之后被调用int (*BspIsValid)(void*);//底层有效性检查 返回vIC_Mifare1_Result_Ok表明底层硬件有效 否则底层硬件无效}IC_Mifare1_LL_Function;typedef struct _IC_Mifare1{int Status;//状态IC_Mifare1_CommunicationCallback_Param* Param;//只有在CommunicationCallback中有效IC_Mifare1_LL_Function LL_Function;//底层方法}IC_Mifare1;#define vIC_Mifare1_Result_NoCard                                  1            //无响应 未发现卡
#define vIC_Mifare1_Result_Ok                                      0            //操作无错误
#define vIC_Mifare1_Result_Error                                   -1           //出现错误 此情况下IC通信已经无法继续下去且无法恢复,需要复位后再次尝试通信
#define vIC_Mifare1_Result_StatusError                             -2           //状态错误 调用了在某些状态下不能调用的方法#define vIC_Mifare1_Status_Select                                  1            //卡选中状态
#define vIC_Mifare1_Status_Ready                                   0            //卡已准备好识别
#define vIC_Mifare1_Status_CommunicationError                      -1           //通信错误
#define vIC_Mifare1_Status_BspInvaild                              -2           //底层无效#define vIC_Mifare1_AuthentType_A                                  1
#define vIC_Mifare1_AuthentType_B                                  2#define vIC_Mifare1_ValueBlockGetValue_Value_Msk                   0x0FU
#define vIC_Mifare1_ValueBlockGetValue_Value_Ok                    0x00U        //数值完全正确
#define vIC_Mifare1_ValueBlockGetValue_Value_PartOk                0x01U        //数值部分正确, 能解析出数值
#define vIC_Mifare1_ValueBlockGetValue_Value_Error                 0x02U        //数值错误过多, 没有解析出数值
#define vIC_Mifare1_ValueBlockGetValue_Addr_Msk                    0xF0U
#define vIC_Mifare1_ValueBlockGetValue_Addr_Ok                     0x00U        //地址完全正确
#define vIC_Mifare1_ValueBlockGetValue_Addr_PartOk                 0x10U        //地址部分正确, 能解析出地址
#define vIC_Mifare1_ValueBlockGetValue_Addr_Error                  0x20U        //地址错误过多, 没有解析出地址//============================================================================================================================================
//
// 提供给外部的方法
//
//============================================================================================================================================/*** @brief 初始化IC_Mifare1控制器* @param _this 未使用的句柄* @param LL_Function 底层方法集合* @return 无*/
void IC_Mifare1_Init(IC_Mifare1* _this,IC_Mifare1_LL_Function* LL_Function);/*** @brief 尝试进行一次卡操作 如果寻卡成功CommunicationCallback被调用 此后卡被halt* @param _this IC_Mifare1句柄* @param CommunicationCallback IC_Mifare1句柄* @param IsAll 0:仅选中空闲的卡 其他:所有卡都在选中范围* @return 0: CommunicationCallback成功被调用 其他:CommunicationCallback没有被调用*/
int IC_Mifare1_Communication(IC_Mifare1* _this,void (*CommunicationCallback)(IC_Mifare1*,IC_Mifare1_CommunicationCallback_Param*),int IsAll);//============================================================================================================================================
//
// 提供给外部的方法 在IC_Mifare1_Communication()传入的CommunicationCallback()中调用
//
//============================================================================================================================================/*** @brief 密钥验证* @param _this IC_Mifare1句柄* @param BlockAddr 要验证的块地址* @param AuthentType 密码类型 要验证的密码类型 vIC_Mifare1_AuthentType_A与vIC_Mifare1_AuthentType_B可选* @param Password 密钥* @return 返回执行结果*/
int IC_Mifare1_Authent(IC_Mifare1* _this,Hbyte BlockAddr,int AuthentType,Hbyte* Password);/*** @brief 读一个块* @param _this IC_Mifare1句柄* @param BlockAddr 块地址* @param Dst 指向用于存放数据的内存 大小16字节* @return 返回执行结果*/
int IC_Mifare1_ReadBlock(IC_Mifare1* _this,Hbyte BlockAddr,Hbyte* Dst);/*** @brief 写一个块* @param _this IC_Mifare1句柄* @param BlockAddr 块地址* @param SrcData 要写入的数据 大小16字节* @return 返回执行结果*/
int IC_Mifare1_WriteBlock(IC_Mifare1* _this,Hbyte BlockAddr,Hbyte* SrcData);/*** @brief 数值块操作 数值块内的值 增加/减小/不加不减 到IC卡的数值缓冲区* @param _this IC_Mifare1句柄* @param BlockAddr IC_Mifare1句柄* @param IsDecrement 如果dValue不为0, 则该段有效: 0:加值 其他:减值* @param dValue 变化的值 如果为0 则使用Restore指令, 值不做变化的转到IC卡的数值缓冲区* @return 返回执行结果*/
int IC_Mifare1_ValueOperation(IC_Mifare1* _this,Hbyte BlockAddr,int IsDecrement,Huint32 dValue);/*** @brief 数值块操作 将IC卡的数值缓冲区的数值存储到块中* @param _this IC_Mifare1句柄* @param BlockAddr 要存储到的块地址* @return 返回执行结果*/
int IC_Mifare1_ValueTransfer(IC_Mifare1* _this,Hbyte BlockAddr);//============================================================================================================================================
//
// 附加给外部的方法 无调用条件 随便调用
//
//============================================================================================================================================/*** @brief 生成数组块数据* @param BlockData 生成的数据存放位置* @param BlockAddr 块地址* @param Value 数值* @return 无*/
void IC_Mifare1_MakeValueBlock(Hbyte* BlockData,Hbyte BlockAddr,Huint32 Value);/*** @brief 简单解析并获取块的数值和地址域的地址 (有更好的恢复方法(只是恢复概率更高) 但这个函数没有使用 其实也没什么必要)* @param BlockData 块数据* @param BlockAddr 用于返回地址域的地址* @param Value 用于返回数值* @return 结果有效性*/
Hbyte IC_Mifare1_ValueBlockGetValue(Hbyte* BlockData,Hbyte* BlockAddr,Huint32* Value);#endif //__IC_Mifare1_H_

执行void IC_Mifare1_Init(IC_Mifare1* _this,IC_Mifare1_LL_Function* LL_Function)时,LL_Function包含对MFRC522层的操作函数指针。
Mifare1层封装了对M1卡的操作,因为M1卡都是从寻卡开始,到Halt卡结束。所以这些过程被封装起来了,出了个
int IC_Mifare1_Communication(IC_Mifare1* _this,void (*CommunicationCallback)(IC_Mifare1*,IC_Mifare1_CommunicationCallback_Param*),int IsAll)函数,寻卡操作与Halt卡操作自动完成(其中Halt操作要在所有操作都成功的情况下会被使用,如果有操作失败,则不会被使用)。如果上次的调用这个函数时出现通讯错误,则本次调用时内部会首先复位底层的RC522,然后才开始寻卡操作。如果切顺利,在自动选中卡之后,传入该函数的
void (*CommunicationCallback)(IC_Mifare1*,IC_Mifare1_CommunicationCallback_Param*)被调用。这是用户传入的回调,在里面用户可以按照自己的需要调用验证密码,读、写、加值减值等操作。如果这个函数没有被调用(例如没有找到卡), 这个方法就返回非0值。

因为通信格式相同, Increment加值 \ Decrement减值 \ Restore不变, 这三个操作被int IC_Mifare1_ValueOperation(IC_Mifare1* _this,Hbyte BlockAddr,int IsDecrement,Huint32 dValue)这个函数包揽了。根据值是否为0,是否减少 来判定使用那条指令。这个函数调用成功后,被操作的值存在IC卡的缓冲区中(IC卡块里的数据并没有变化)。如果要保存操作后的数据(在IC卡的缓存里),需要调用int IC_Mifare1_ValueTransfer(IC_Mifare1* _this,Hbyte BlockAddr);来实现保存。该保存函数的成功意味着数据成功保存(啥,这都能失败那就是卡的问题了)。
*IC_Mifare1_ReadBlock()IC_Mifare1_WriteBlock()直接读取/写入块,没有缓冲区的事。

5 源码实现

STM32作为虚拟串口,接收主机的串口助手的指令。默认上电后不进行任何卡操作(仅初始化RC522)。

5.1 串口助手发送的指令

通过串口助手发送字符串进行操作,源码使用UTF8编码,串口助手要注意要设置为正确的编码。

单字符指令(注意大小写)

字符串: i 获取一些运行信息

字符串: v 获取MFRC522版本寄存器的值

字符串: I (i的大写)发送该指令后,进入初始化状态,进入范围的白卡都会被初始化,扇区1写入一些数据,并设置密钥

字符串: D 发送该指令后,进入反初始化状态,进入范围的卡都会被反初始化,密钥恢复为FFFFFFFFFFFF(只有指令I初始化的卡才能被反初始化)

字符串: R 发送该指令后,进入读取状态,可以读取初始化好的卡的内部数据

多字符指令(注意大小写)

字符串: Cxxx 该命令以C开头,xxx为10进制有符号整数,长度不限。对数值块进行加,减操作。成功操作后,自动进入读取状态。

例如: C-100 值减100

例如: C50 值加50

串口助手发送C命令不要选上发送回车(后果我也不知道)

5.2 IC块的使用

源码只使用了IC卡的第二个扇区,这个扇区的所有块都被使用了。该扇区通过I指令

5.2.1 作用布局

块0: 存放用户数据(存了一个字符串)
块1: 数值块(备份)
块2: 数值块
块3:控制块(修改密码)

数值块通过写块操作生成,只需要按照特定格式写入。

数值为整型数,位宽4字节,在块中小端排列,重复拍3次,其中第二次位取反。最后4个字节存放地址,存放备份的地址,但实际上这个地址似乎可以随便选。

5.3 相关操作

5.3.1 初始化卡

5.3.2 尝试重复初始化

疯狂回复操作失败,因为卡已经初始化了,密码已修改(如果操作失败,RC522重新初始化 IC卡被重新上电,导致重复检测)

5.3.3 读取卡

5.3.4 减值

5.3.5 加值

5.3.6 将卡反初为白卡(恢复默认密码)

IC卡探索记录- MFRC522+STM32F103C8 操作IC卡(M1卡) ---附代码相关推荐

  1. 【记录】文章相似度计算开发(附代码)

    写在前边:目前已经通过爬虫等手段获取了千万级的文章类数据,但是目前这些数据是只是简单的基于表层的应用,相对粗粒度的统计,文本之间的很多信息并没有被良好的利用起来.为了提高数据的使用率并获取更多有用信息 ...

  2. python画24色卡图及对比图,sRGB反gamma操作得到线性RGB数值(附代码)

    文章目录 1.已知24色卡的RGB数据,画出对应的图像 2.sRGB反gamma操作得到线性RGB数值 1.已知24色卡的RGB数据,画出对应的图像 比如两组RGB数据 list1 = [[115, ...

  3. 磁卡、ID卡、IC卡、M1卡、CPU卡的理解区分

    一.磁卡 磁卡是在一张塑料片上均匀地涂布上一层磁性微 粒材料制成的. 刚生产出来的磁卡上面的磁性微粒是不显磁性的, 这样的磁卡就象一张白纸, 人们需要在磁卡里输入一些信息才能使用. 那么信息是怎样被记 ...

  4. IC卡 M1卡 各个扇区 控制块 密码 详解

    该内容由部分转载和部分自己见解.整理出来方便小白和自己后期使用. M1卡介绍 这次我们主要介绍的是非接触式IC卡.M1卡就是非接触式IC卡中应用最广泛的卡.M1卡就是Mifare非接触式感应卡,M1卡 ...

  5. 非接触(IC卡、M1卡、CPU卡)ID卡的区别是什么

    集成电路芯片可以是存储器或微处理器.带有存储器的IC卡又称为记忆卡或存储卡,带有微处理器的IC卡又称为智能卡或智慧卡.记忆卡可以存储大量信息:智能卡则不仅具有记忆能力,而且还具有处理信息的功能.IC卡 ...

  6. 一卡通(M1卡)破解过程记录——理论篇

    前些日子在研究学校的一卡通安全,在此记录一下一卡通破解的全过程,仅用作学习交流,切勿用于违法用途 其他几篇: 一卡通(M1卡)破解过程记录--准备篇              获取扇区密钥      ...

  7. M1卡破解(自从学校升级系统之后,还准备在研究下)

    M1卡说明及使用proxmark3破解方法 看了网上写的一些关于M1卡的文章,多数有些误导之嫌.首先谈谈M1卡的规格,M1卡的容量为1KB,好多网上写8KB,这里其实是有个误区,应该是8K位.1Byt ...

  8. M1卡破解(自从学校升级系统之后,还准备在研究下)【转】

    本文转载自: M1卡说明及使用proxmark3破解方法 看了网上写的一些关于M1卡的文章,多数有些误导之嫌.首先谈谈M1卡的规格,M1卡的容量为1KB,好多网上写8KB,这里其实是有个误区,应该是8 ...

  9. M1卡 不能使用KeyB进行读写的问题

    前提知识: #M1卡控制位对应操作权限: M1卡即S50卡,存取控制(4字节,其中字节9为备用字节)结构如下所示: 数据块(块0.块1.块2)的存取控制如下: 控制位(X=0..2) 访 问 条 件 ...

最新文章

  1. asyncawait
  2. 【技术应用】【informix】 c++版 数据库通用操作
  3. alibaba cloud 打包_阿里也上VS Code船了,发布Alibaba Cloud Toolkit插件
  4. Android之Activity的四种启动模式
  5. 如何查询SAP C4C创建日期大于某日的所有lead数据
  6. django之auth模块
  7. java对jsonarray去重复_java 去除jsonarray里面jsonarray的重复和合并数据
  8. 虚拟打印的实现-安装
  9. 【逆向知识】开发WinDBG扩展DLL
  10. 传统白板行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  11. 【Python3爬虫】网易云音乐歌单下载
  12. Docker生产环境配置——设置direct-lvm模式
  13. Winows Phone 7 不温不火学习之《音乐播放示例》
  14. WAP 手机及开发技术调研(转)
  15. 怎样写工科研究生论文
  16. 台式电脑网络连接配置异常_电脑上不了网,360断网急救箱显示网络连接配置和网络存在問題,点击修复。网络连接配置修复了,网络存......
  17. 详版大数据报告_《2018抖音大数据报告》完整版,赶快收藏!
  18. 油猴天眼查公司链接获取(用油猴实现爬虫python版)
  19. 如何恢复android误删的文件夹,如何恢复误删的android手机文件
  20. 计算机三级嵌入式学习笔记(一)

热门文章

  1. 【练习七 字符串编程题1. 全字母短句】
  2. 新手小白如何做好亚马逊跨境电商?
  3. ​Java 常用英语汇总
  4. java重写hashcode_正确重写hashCode的办法
  5. python pandas 给dataframe添加列名
  6. vue vant Image组件 图片加载时 与 加载失败 的处理方法
  7. 年仅38岁!中科院研究员周传不幸去世,饶毅发文悼念:他还是我的学生时就指导过我!...
  8. 息县装修“黑白风格”
  9. 泛微OA E9 E8 开发 培训 ecology
  10. C#+AE缓冲区分析