MFRC522

目录

一、RFID

1.1 UID

1.2 IC卡的内存管理

1.3 存取控制

1.4 IC与读卡器的通信

二、功能介绍

三、实现

3.1 RC522射频模块外部接口

3.2 初始化

3.2.1 引脚初始化

3.2.2 初始化

3.3 发送接收信息

发送

接收

3.4 对RC522寄存器的操作

3.4.1 读取RC522指定寄存器的值

3.4.2 向RC522指定寄存器中写入指定的数据

3.4.3 置位RC522指定寄存器的指定位

3.4.4 清位RC522指定寄存器的指定位

3.5 对RC522的基础通信

3.5.1 开启天线

3.5.2 关闭天线

3.5.3 复位RC522

3.6 stm32控制RC522与ISO14443卡的通信

3.6.1 通过RC522和M4卡通信(数据的双向传输)

3.6.2 寻卡

3.6.3 防冲突

3.6.4 用RC522计算CRC

3.6.5 选定卡片

3.6.6 校验卡片密码

3.6.7 在M4卡的指定块地址写入指定数据

3.6.8 读取M4卡的指定块地址的数据

3.6.9 让卡片进入休眠模式

四、完成读写操作

4.1 写卡

4.2 读卡

4.3 测试

4.4 效果展示

五、仿照IC卡充值操作

5.1 封装卡片检测、防冲突、选择卡片和验证密码的通用函数

5.2 充值操作

5.3 读卡操作

5.4 实现效果

六、会员卡

结束语

一、RFID

射频识别,即RFID又称无线射频识别,由读写器和射频标签(应答器)

组成。

RC522是一种非接触式读写卡芯片,采用SPI协议,一般用于门禁卡、公交卡充值消费。

1.1 UID

在IC芯片当中(集成电路芯片中),UID即唯一识别码。在芯片制造过程中被写入芯片内部、全球唯一的数字编码,就像芯片的身份证,用于区分不同的芯片个体。通常由一串数字或数字与字母组合而成的代码,长度和格式根据芯片制造商以及具体应用场景有所不同。

1.2 IC卡的内存管理

IC卡中有1kB的存储空间,并且将存储空间分为了16个扇区,每个扇区分为4块,每块16个字节,以块为存储单位。

1kB -> 1024B ->16个扇区

1个扇区->64B->4个块

1个块->16B

将16个扇区的64个块按绝对地址编号为0x00-0x3F(0-63)

0-4B是卡片的序列号,第5字节是序列号的校验码,第6字节是卡片的容量"SIZE"字节,第7-8字节为卡片的类型号字节,其他字节由厂商另加定义。

每个扇区的块3为控制块,包括了密码A,存取控制,密码B ,空卡默认读写权限如下:

在空卡状态下,每个扇区的尾块数据(16进制)为:0x00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF

存取控制字节:

1.3 存取控制

要想对数据块进行操作,首先要看该数据块的控制位是否允许对数据块操作。如果允许操作,再看需要验证什么密码,只有验证密码正确后才可以对该数据执行相应操作。

根据上面的权限:块三:001

密码 A: 不可读,但通过密码 A 校验后,可改写密码 A。权限字节以及密码

B 的读写权限均可以使⽤密码 A 读写。

由上表⼜可以得到:密码 A 永远不可以被读,所以⼀旦设置必须记住。

1.4 IC与读卡器的通信

复位应答:复位RC522,开始检测靠近的卡片

防冲突机制:当有多张卡片进入读写器操作范围时,会从中选择一张卡片进行操作,并返回选中卡片的序列号。

三次相互确认:选定要处理的卡片后,读写器就要确定访问的扇区号,并且对扇区密码进行密码校验。在三次互相认证后就可以通过加密流进行通信。每次在选择扇区的时候都要进行扇区的密码校验。

对数据块的操作:

读:读一个块的数据

写:在一个块写

加:对数据块中的数值进行加值

减:对数据块中的数值进行减值

中止:暂停卡片的工作

二、功能介绍

使用RC522模块完成对IC卡卡号读取、卡类型区分、IC卡扇区密码修改、扇区数据读写等功能。

底层采用SPI模拟时序。并用串口打印对应信息。

三、实现

3.1 RC522射频模块外部接口

SDA <----->PA4--片选脚 -->后续用CS来表示 SCK <----->PA5--时钟线 MOSI<----->PA7--输出 MISO<----->PA6--输入

GND <----->GND RST <----->PB0--复位脚 VCC <----->VCC -->3.8v

#define MFRC522_GPIO_CS_PORT    GPIOA              
#define MFRC522_GPIO_CS_PIN     GPIO_Pin_4
​
#define MFRC522_GPIO_SCK_PORT   GPIOA              
#define MFRC522_GPIO_SCK_PIN    GPIO_Pin_5
​
#define MFRC522_GPIO_MOSI_PORT  GPIOA              
#define MFRC522_GPIO_MOSI_PIN   GPIO_Pin_7
​
#define MFRC522_GPIO_MISO_PORT  GPIOA              
#define MFRC522_GPIO_MISO_PIN   GPIO_Pin_6
​
#define MFRC522_GPIO_RST_PORT   GPIOB          
#define MFRC522_GPIO_RST_PIN    GPIO_Pin_0   

对应相应的接口拉高拉低

低电平有效,高电平空闲

//片选
#define     RC522_CS_Enable()       GPIO_ResetBits ( MFRC522_GPIO_CS_PORT, MFRC522_GPIO_CS_PIN )
#define     RC522_CS_Disable()      GPIO_SetBits ( MFRC522_GPIO_CS_PORT, MFRC522_GPIO_CS_PIN )
//复位        
#define     RC522_Reset_Enable()    GPIO_ResetBits( MFRC522_GPIO_RST_PORT, MFRC522_GPIO_RST_PIN )
#define     RC522_Reset_Disable()   GPIO_SetBits ( MFRC522_GPIO_RST_PORT, MFRC522_GPIO_RST_PIN )
//时钟        
#define     RC522_SCK_0()           GPIO_ResetBits( MFRC522_GPIO_SCK_PORT, MFRC522_GPIO_SCK_PIN )
#define     RC522_SCK_1()           GPIO_SetBits ( MFRC522_GPIO_SCK_PORT, MFRC522_GPIO_SCK_PIN )
//MOSI                  
#define     RC522_MOSI_0()          GPIO_ResetBits( MFRC522_GPIO_MOSI_PORT, MFRC522_GPIO_MOSI_PIN )
#define     RC522_MOSI_1()          GPIO_SetBits ( MFRC522_GPIO_MOSI_PORT, MFRC522_GPIO_MOSI_PIN )
//MISO      
#define     RC522_MISO_GET()        GPIO_ReadInputDataBit ( MFRC522_GPIO_MISO_PORT, MFRC522_GPIO_MISO_PIN )

3.2 初始化

时钟:因为外部接口用到了GPIOA和GPIOB,所以需要配置对应的时钟

SPI:RC522模块通常作为从机,stm32作为主机。

时钟SCK:由主机产生。

MISO:MISO(Master In Slave Out)引脚通常配置为浮空输入模式,这是因为MISO引脚仅在从设备需要向主设备发送数据时才有效,而在其他时间应该保持高阻抗状态,以避免干扰总线。

片选:选择某个从机,低电平有效

其余配置为推挽输出

3.2.1 引脚初始化

void SPI1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    /* 使能时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB, ENABLE);
    
    /* 配置 SPI_RC522_SPI 引脚:CS(SDA) */
    GPIO_InitStructure.GPIO_Pin = MFRC522_GPIO_CS_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_Init(MFRC522_GPIO_CS_PORT, &GPIO_InitStructure);
    
    /* 配置 SPI_RC522_SPI 引脚:SCK */
    GPIO_InitStructure.GPIO_Pin = MFRC522_GPIO_SCK_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_Init(MFRC522_GPIO_SCK_PORT, &GPIO_InitStructure);
    
    /* 配置 SPI_RC522_SPI 引脚:MOSI */
    GPIO_InitStructure.GPIO_Pin = MFRC522_GPIO_MOSI_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_Init(MFRC522_GPIO_MOSI_PORT, &GPIO_InitStructure);
    
    /* 配置 SPI_RC522_SPI 引脚:MISO */
    GPIO_InitStructure.GPIO_Pin = MFRC522_GPIO_MISO_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
    GPIO_Init(MFRC522_GPIO_MISO_PORT, &GPIO_InitStructure);
    
    /* 配置 SPI_RC522_SPI 引脚:RST */
    GPIO_InitStructure.GPIO_Pin = MFRC522_GPIO_RST_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_Init(MFRC522_GPIO_RST_PORT, &GPIO_InitStructure);
}

3.2.2 初始化

  • 各引脚的初始化

  • 复位失能

  • 片选失能

  • 复位

  • 设置工作模式

void MFRC522_Init ( void )
{
    SPI1_Init();
​
    RC522_Reset_Disable();
​
    RC522_CS_Disable();
​
    RC522_Reset ();
​
    RC522_Config_Type ( 'A' );//设置工作方式
}

3.3 发送接收信息

通过软件模拟SPI与RC522通信,SPI发送接收字节的代码如下(低位先行):

发送

void RC522_SPI_SendByte( uint8_t byte )
{ 
    uint8_t n;
    for( n=0;n<8;n++ )
    { 
        if( byte&0x80 )
            RC522_MOSI_1();//发送1
        else
            RC522_MOSI_0();//发送0
        Delay_us();
        RC522_SCK_0();//拉低,时钟开始工作
        Delay_us();
        RC522_SCK_1();//拉高,数据发送完毕
        Delay_us();
        byte<<=1;//一位数据已发送成功,移位
    }
}

接收

uint8_t RC522_SPI_ReadByte( void )
{ 
    uint8_t n,data;
    for( n=0;n<8;n++ )
    { 
        data<<=1;
        RC522_SCK_0();//拉低开始接收数据
        Delay_us();
        if( RC522_MISO_GET()==1 )
            data|=0x01;//获取数据位为1 
        Delay_us();
        RC522_SCK_1();//拉高时钟,结束这一位数据的接收
        Delay_us();
    }
    return data;
}

3.4 对RC522寄存器的操作

stm32是向RC522寄存器操作来驱动RC522,所以会存在以下几种基本操作:

3.4.1 读取RC522指定寄存器的值

/** * @brief :读取RC522指定寄存器的值 * @param :Address:寄存器的地址 * @retval :寄存器的值 */
uint8_t RC522_Read_Register( uint8_t Address )
{ 
​
    uint8_t data,Addr;
    Addr = ( (Address<<1)&0x7E )|0x80;
    RC522_CS_Enable();
    RC522_SPI_SendByte( Addr );
    data = RC522_SPI_ReadByte();//读取寄存器中的值
    RC522_CS_Disable();
    return data;
}

3.4.2 向RC522指定寄存器中写入指定的数据

/** * @brief :向RC522指定寄存器中写入指定的数据 * @param :Address:寄存器地址 data:要写入寄存器的数据 * @retval :无 */
void RC522_Write_Register( uint8_t Address, uint8_t data )
{ 
    uint8_t Addr;
    Addr = ( Address<<1 )&0x7E;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值