【STM32学习】(11)STM32 Mifare_One(S50) M1S50的使用(读、写、密钥修改,控制位解读)

最近在研究RFID(射频识别),我用的是 M1卡(Mifare_One(S50)),是一种常用的非接触式IC卡

基础知识不用多讲,网上资料一堆,讲的很详细。

现在我们就直入主题,首先介绍一下卡的执行流程图,如下图。

中文资料里的图,如下:

英文资料里的图,如下:

查资料会发现,所有的参考代码都是按照这个流程图写,很容易懂。不管你在写还是读的时候一定要选卡,放冲突,验卡等流程后才能实现读写操作。

再看一下他的存储结构:

*********引用一个博客文档  开始

我们可以根据控制字来确定卡的读写形式。

M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,前3个块是数据区,第4块是密钥区。每个块都能存储16个字节的数据,密钥区的16个字节数据是有特殊含义的:
6个字节的密码A + 4个字节密钥控制位 + 6个字节的密码B
其中密钥控制位决定这个扇区的读写规则,对于M1卡密钥控制位及控制规则的说明,这篇文章里面讲述得很清楚了:
https://wenku.baidu.com/view/76afde36312b3169a451a4e6.html
这里只是给没有耐心看文章朋友提炼一下,控制字的组合方式虽然多,但实际用得比较多的方案自认为无外乎四种:

1.默认方式 控制位为“FF 07 80 69”
这种方式下密钥A或密钥B都可以读写数据区,密钥A可写密钥区,优点是密钥控制字无需重新计算,读写方便,缺点是安全性能差,密钥A容易泄露。

2.密钥B写方式 控制位为“7F 07 88 69”
这种方式下密钥A或密钥B都可以读写数据区,而对于密钥区只能由密钥B来写。优点是密钥B权限最高,只要知道密钥B,无论密钥A写成什么都可以改写,由最高管理员掌握密钥B,可下发多种密钥A的一般管理员,一般不会废卡的。缺点是密钥B很重要,一旦忘记,卡就不能再改写密钥了。

3.A读B写方式 控制位为“08 77 8F 69”
这种方式下由密钥A读密钥B来写,可以说是上面一种方式的变体,对于密钥B有更强的保护。

4.只读不写方式 控制位为“FF 00 F0 69”
这种方式下密钥A或密钥B都可以读数据区,但都不能写数据区(数值可减少,不能增加),密钥A可以改写密钥区。这种方式对于数据是极大的保护,尤其是定额卡,里面的钱只能减少而不能增加。

 

以上是常用的几种控制方式,更多的组合方式可以利用“M1+卡控制字节生成工具.exe”工具来生成

结束   ******

1.完成RFID卡的读函数代码

/* 读取RFID卡片信息 **/
void Read_RFID_Card_wt(void)
{
	char status = MI_ERR;
	uint8_t CT[2];									//卡类型
	uint8_t SN[4]; 									//卡号
	uint8_t KEY[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //密钥	//	密钥已被我修改   2019.11.19  	  王艇
	uint8_t s = 0x01;       						  	
	#define  DATA_LEN    16                     	//定义数据字节长度	

	LED1 = 0;
	LED2 = 0;
	LED3 = 0;
	LED4 = 0;
	
		status = PcdRequest(PICC_REQALL,CT);		//寻卡
		//Send_ZigbeeData_To_Fifo(CT,2); // wt   2019.10.18
		if(status == MI_OK)							//寻卡成功
		{
			status=MI_ERR;
			LED1 = 1;
			status = PcdAnticoll(SN);				//防冲撞
			//Send_ZigbeeData_To_Fifo(SN,4); // wt    2019.10.18
			if(status == MI_OK)
			{
				status=MI_ERR;
				LED2 = 1;				
				status =PcdSelect(SN);				//选定此卡
				if(status == MI_OK)					//选定成功
				{
					status=MI_ERR;	
					LED3 = 1;
					MP_SPK = 1;					
					status =PcdAuthState(PICC_AUTHENT1A,0x03,KEY,SN);		//验证密钥
					if(status == MI_OK)
					{
						status = MI_ERR;
																	
						status=PcdRead(s,RXRFID);				//读卡 
						
						if(status == MI_OK)
						{
							status = MI_ERR;
							LED4 = 1;							//读卡成功
							MP_SPK = 0;								
							//Send_InfoData_To_Fifo(RXRFID,16);
							//Send_InfoData_To_Fifo("\n",2);  
							//Send_ZigbeeData_To_Fifo(RXRFID,16); 
						}						
					}
				}
			}
	}
}

这里我是读取0扇区第二块(0X01)的数据,其实读取其他也很简单,需要修改0X03(这个是0-15扇区的控制块,如:0扇区的控制块是0X03,1扇区的控制块是0X07 等等)

随后还要修改,s,这个s就是你要验证的哪个扇区的数据块地址还控制块地址(如:想读1扇区的0块数据,这个s的值就是0X04,我们这里读取的是0扇区第二块(0X01)的数据):

注意:一般新卡的默认密钥都是KEYA或KEYB   0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,但有时候密钥会被修改,那这时就要填写正确的key值,才能验证成功,这样也很容易理解,只有配上正确的密码才能激活卡片。

2.完成RFID卡的写函数代码

void Write_RFID_Card_wt(void)
{
	char status = MI_ERR;
	uint8_t CT[2];									//卡类型
	uint8_t SN[4]; 									//卡号
	uint8_t KEY[6]={0xff,0xff,0xff,0xff,0xff,0xff}; //{0x01,0xB2,0xC3,0xD4,0xE5,0xF6}; //密钥	//	密钥已被我修改   2019.11.19  	  王艇
	uint8_t s = 0x01;       						  	
	#define  DATA_LEN    16                     	//定义数据字节长度	

	LED1 = 0;
	LED2 = 0;
	LED3 = 0;
	LED4 = 0;
	
		status = PcdRequest(PICC_REQALL,CT);		//寻卡
		//Send_ZigbeeData_To_Fifo(CT,2); // wt   2019.10.18
		if(status == MI_OK)							//寻卡成功
		{
			status=MI_ERR;
			LED1 = 1;
			status = PcdAnticoll(SN);				//防冲撞
			//Send_ZigbeeData_To_Fifo(SN,4); // wt    2019.10.18
			if(status == MI_OK)
			{
				status=MI_ERR;
				LED2 = 1;				
				status =PcdSelect(SN);				//选定此卡
				if(status == MI_OK)					//选定成功
				{
					status=MI_ERR;	
					LED3 = 1;
					MP_SPK = 1;					
					status =PcdAuthState(PICC_AUTHENT1A,0x03,KEY,SN);		//验证密钥
					if(status == MI_OK)
					{
						status = MI_ERR;
											
						status = PcdWrite(s,TXRFID);			//写卡 
						if(status == MI_OK)
						{
							status = MI_ERR;
						}							
												
					}
				}
			}
	}
}

这里是给0扇区1数据块(0X01)写数据,这个写函数也是可以给其他扇区中数据块写数据的,如现在要给我1扇区,2块中写入数据:uint8_t TXRFID[16]  =  {0x7C,0x32,0x2F,0X30,0X33,0X2D,0X32,0X7C,0X7C,0X33,0X2F,0X30,0X35,0X2D,0X31,0X7C}

这里选择的是默认密钥,全F,验证A密钥(PICC_AUTHENT1A

下面的 0X03需要改成0X07(扇区1 控制块地址),因为控制块中包含密钥,需要验证

下面s要修改成0X06(表示1扇区,数据块2的地址)TXRFID 是所要写入的数据

这样就完成了对指定扇区,指定数据块中写入指定数据。
3.修改RFID卡的密钥代码

void Write_RFID_Card_wt(void)
{
	char status = MI_ERR;
	uint8_t CT[2];									//卡类型
	uint8_t SN[4]; 									//卡号
	uint8_t KEY[6]={0xff,0xff,0xff,0xff,0xff,0xff}; //{0x01,0xB2,0xC3,0xD4,0xE5,0xF6}; //密钥	//	密钥已被我修改   2019.11.19  	  王艇
	uint8_t s = 0x03;       						  	
	#define  DATA_LEN    16                     	//定义数据字节长度	

	LED1 = 0;
	LED2 = 0;
	LED3 = 0;
	LED4 = 0;
	
		status = PcdRequest(PICC_REQALL,CT);		//寻卡
		//Send_ZigbeeData_To_Fifo(CT,2); // wt   2019.10.18
		if(status == MI_OK)							//寻卡成功
		{
			status=MI_ERR;
			LED1 = 1;
			status = PcdAnticoll(SN);				//防冲撞
			//Send_ZigbeeData_To_Fifo(SN,4); // wt    2019.10.18
			if(status == MI_OK)
			{
				status=MI_ERR;
				LED2 = 1;				
				status =PcdSelect(SN);				//选定此卡
				if(status == MI_OK)					//选定成功
				{
					status=MI_ERR;	
					LED3 = 1;
					MP_SPK = 1;					
					status =PcdAuthState(PICC_AUTHENT1A,0x03,KEY,SN);		//验证密钥
					if(status == MI_OK)
					{
						status = MI_ERR;
											
						status = PcdWrite(s,TXRFID);			//写卡 
						if(status == MI_OK)
						{
							status = MI_ERR;
						}							
												
					}
				}
			}
	}
}

上面的代码仔细看可以发现和2.完成RFID卡的写函数代码,中的代码基本一致,也就是简单修改了几个参数。上面函数的功能是:将扇区0,控制块密钥修改0x01,0xB2,0xC3,0xD4,0xE5,0xF6,原来的密钥是0xff,0xff,0xff,0xff,0xff,0xff

当修改完成后,他的密钥就成了0x01,0xB2,0xC3,0xD4,0xE5,0xF6。

uint8_t TXRFID[16] = {0x01,0xB2,0xC3,0xD4,0xE5,0xF6,0xFF,0x07,0x80,0x69,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};    

现在假如需要修改扇区1的A密钥,之前扇区A的密钥为0xff,0xff,0xff,0xff,0xff,0xff,修改为:0x01,0xB2,0xC3,0xD4,0xE5,0xF6

所以需要修改成的地方有:

  修改控制块地址为0X07,这个地址就是扇区1,控制块地址

这边的控制块地址改成0X07

这个数组为:TXRFID[16] = {0x01,0xB2,0xC3,0xD4,0xE5,0xF6,0xFF,0x07,0x80,0x69,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; 

 

执行成功后,扇区1的密钥A的密码就被修改成功了。

 

这样就完成了数据的读取,和密钥的修改

后期对卡的扣款 充值操作就更容易一点。

 

  • 10
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小材大用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值