基于STM32C8T6、RFID_RC522模块读写Mifare One(S50)卡

RFID_RC522模块

此模块运用射频识别技术与多种IC卡进行数据交互,并通过SPI与外界通信。

射频识别,又称为无线射频识别,英文简称为RFID(Radio Frequency Identification)。这是一种通信技术,它能够通过无线电讯号识别特定的目标,并且读取和写入相关的数据,无需识别系统和特定目标之间建立物理接触。一套完整的RFID硬件系统由Reader(如RC522)和Transponder(如IC卡)两部分组成。其工作原理是,Transponder接收Reader传送的微波信号,并通过内置的电磁感应线圈获取能量,进而进行信息交换。

MF RC522是一款由NXP公司推出的,应用于13.56MHz非接触式通信的高集成度读写卡芯片,这款芯片具有低电压、低成本、体积小的特点,是智能仪表和便携式手持设备的理想选择。

Mifare One(S50)卡

Mifare One(S50)卡是一种非接触式智能卡,通常简称为S50卡或Mifare 1K。

此卡的存储空间分为16个扇区,每个扇区为4块,每块为16个字节,读写数据以块为单位。每个扇的区前三块为数据块,最后一块控制块。我们也将16个扇区的64个块按绝对地址编号为0~63,存储结构如下图所示:

数据块可用作一般的数据保存,进行读、写操作;还可用作数据值,进行初始化值、加值、减值、读值操作。其中第0扇区的块0(即绝对地址0块),用于存放厂商代码,已经固化,不可更改。

控制块包括了密码A(0~5字节,共6字节)、存取控制码(6~9字节,共4字节)、密码B(10~15字节,共6字节) ,它们共同决定了该扇区数据的读写权限。从这也能看出,每个扇区的数据读写权限,只与自己的块3有关,与其他扇区无关。

存取控制码的具体结构如下:

注:字节9为占位符,无实际作用;Cxx_b是Cxx的取反

每3个对应的Cxx决定了对应块的数据读写权限,具体结构如下:

对于数据块:

注:KeyA|B 表示密码A或密码B,Never表示任何条件下不能实现

如:当块0的存取控制位C10 C20 C30 = 001时,验证密码A或密码B正确后可读,验证密码B正确后可写: 不能进行加值、减值操作。

对于控制块:

如:当块3的存取控制位C13 C23 C33 = 001时,表示:

        密码A:不可读,验证KEYA或KEYB正确后,可写

        存取控制:验证KEYA或KEYB正确后,可读、可写

        密码B:验证KEYA或KEYB正确后,可读、可写

手机APP查看卡信息

下载一个NFC的读卡软件,比如下图那个,先读一张卡,大概了解一下它的存储结构。

多数未使用的IC卡的原始数据都如下图(这里只截了一部分)所示。其中,FF 07 80 69为默认的存取控制位,密码A和B的每一位均为F。这也是这些软件能够在用户不输入密码和存取控制位的情况下,能直接读出卡中数据的原因。

用STM32C8T6最小系统板与RFID_RC522模块通信,以实现对Mifare One(S50)卡的读写

元件:

接线:

STM32

RFID-RC522

ST-LINK

USB-TTL

3V3

3.3V

3.3V

PA11

RST

GND

GND

GND

GND

PA6

MISO

PA7

MOSI

PA5

SCK

PA4

SDA

SWDIO

SWDIO

SWCLK

SWCLK

PA10

TX

PA9

RX

注:RFID-RC522的IRQ引脚不接;USB-TTL的VCC和5v接不接无所谓,USB-TTL只用于电脑与模块之间的串口通讯,只需使其知道参考电压(GND)即可(实际上,如果USB-TTL和ST-LINK均插在同一个电脑上,它们就已经共地了)

现象:

流程:

寻找卡片-->防冲撞(防止同时检测到多张卡)-->选择卡片-->验证卡片密码-->将数据写入指定块-->读出指定块的数据

代码:

//main.c


#include "stm32f10x.h"                  
#include "Serial.h"
#include "RC522.h"
#include "spi_driver.h"
#include "Delay.h"


unsigned char Card_Type[2] = {0x04,0x00};  	//Mifare One(S50)卡
unsigned char Card_ID[4]; 
unsigned char Card_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};   //默认密钥(A和B一样)
unsigned char Write_Block = 0x06;	//要写入的块地址
unsigned char Read_Block = 0x06;	//要读出的块地址
unsigned char Card_Write_Data[16] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde};  //要写入的数据
unsigned char Card_Read_Data[16];	//要读出的数据
unsigned char status;	//记录多种状态


int main(void)
{
	Serial_Init();
	printf("\r\n***************************** 串口测试  ****************************\r\n");
	
	RC522_IO_Init();
	PcdReset();  //复位RC522
	PcdAntennaOff();  //关闭天线
	Delay_ms(100);
	PcdAntennaOn();  //开启天线
	Delay_ms(100);
	printf("\r\n***************************** RC522启动 *****************************\r\n");
	
	while(1)
	{
		status = PcdRequest(0x52, Card_Type);//寻卡函数,如果成功返回MI_OK
		if(status == MI_OK)  
		{
			printf("\r\n");
			printf("寻卡成功\r\n");
			
			status = PcdAnticoll(Card_ID);//防冲撞 如果成功返回MI_OK
			if(status == MI_OK)
			{
				printf("卡号:%.2x %.2x %.2x %.2x\r\n",Card_ID[0],Card_ID[1],Card_ID[2],Card_ID[3]);					
			}
			else
			{
				printf("检测到多张卡片\r\n");			
			}
			
			status = PcdSelect(Card_ID);  //选卡 如果成功返回MI_OK
			if(status == MI_OK)
			{	
				printf("选卡成功\r\n");
			}
			else
			{
				printf("选卡失败\r\n");
			}
			
			status = PcdAuthState(0x60,0x05,Card_KEY,Card_ID); //验证卡片密码
			if(status == MI_OK)
			{
				printf("验证成功\r\n");
			}
			else
			{
				printf("验证失败\r\n");
			}
			
			status = PcdWrite(Write_Block,Card_Write_Data); //写指定块
			if(status == MI_OK)
			{
				printf("写指定块成功\r\n");
			}
			else
			{
				printf("写指定块失败\r\n");
			}
			
			status = PcdRead(Read_Block,Card_Read_Data); //读指定块
			if(status == MI_OK)
			{
				printf("读指定块成功");
				printf(",0x%.2x块的数据为:%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\r\n",Read_Block,*Card_Read_Data,*(Card_Read_Data+1),*(Card_Read_Data+2),*(Card_Read_Data+3),*(Card_Read_Data+4),*(Card_Read_Data+5),*(Card_Read_Data+6),*(Card_Read_Data+7),*(Card_Read_Data+8),*(Card_Read_Data+9),*(Card_Read_Data+10),*(Card_Read_Data+11),*(Card_Read_Data+12),*(Card_Read_Data+13),*(Card_Read_Data+14),*(Card_Read_Data+15));
			}
			else
			{
				printf("读指定块失败\r\n");
			}
			
			status = PcdHalt();  //卡片进入休眠状态
			if(status == MI_OK)
			{	
				printf("休眠成功\r\n");
			}
			else
			{
				printf("休眠失败\r\n");
			}
		}	
		else
		{
			//printf("寻卡失败\r\n");
		}
			
		Delay_s(1);
		
	}	
}

工程文件:

gitee:RFID_RC522模块: RFID_RC522

csdn:https://download.csdn.net/download/qq_44955826/88694159?spm=1001.2014.3001.5503

参考:

M1卡破解密码控制位及控制规则 - 百度文库

基础篇010.1 STM32驱动RC522 RFID模块之一:基础知识_spi rc522-CSDN博客

RC522(RFID)读写驱动-CSDN博客

基于RFID-RC522的智能门锁设计_基于rfid的智能门锁系统设计-CSDN博客

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值