关于RFID
说明:
1、16个扇区(015),64个块(063),其中每个扇区有4个块(块0~块3),所以16x4=64块。
2、每个扇区的第0块至第2块为数据块(其中第0扇区的第0块为无效块(卡片生产的时候已固定),第3块为密钥地址。
3、根据扇区与块地址关系表得到块地址与密钥地址的计算:
4、例如:求第12扇区第1块的块地址和密钥地址:
块地址为:(4x12)+1=49
密钥地址为:(4x12)+3=51
非加密卡和加密卡的区别就是,非加密卡中所有扇区的KEYA和KEYB数值都是默认值FFFFFFFFFFFF;而加密卡中,其中有扇区的KEYA和KEYB不等于FFFFFFFFFFFF,部分扇区加密的卡称半加密卡,所有扇区都加密的卡称全加密卡
//=================================================================================
#include <stdio.h>
#include <string.h>
#include "RC522.h"
uint8_t readUid[5]; //卡号
uint8_t CT[3]; //卡类型
uint8_t DATA[16]; //存放数据
uint8_t KEY_A[6]= {0xff,0xff,0xff,0xff,0xff,0xff};
uint8_t KEY_B[6]= {0xff,0xff,0xff,0xff,0xff,0xff};//非加密卡密钥
uint8_t NUM = 1;
uint8_t num = 0;
uint8_t status;
uint8_t addr ; // (4 * NUM ) + num NUM: 扇区(0~15) num: 块(0~3)
uint8_t myDATA[16];
MFRC_Init();
PCD_Reset();
uint32_t rfid_time=0;
void Cardcompare()
{
if(uwTick - rfid_time<200) return;
rfid_time = uwTick;
uint8_t i;
addr = (4 * NUM) + num ;//
status = PCD_Request(0x52, CT); //找到卡返回0
if(!status) //寻卡成功
{
status = PCD_ERR;
status = PCD_Anticoll(readUid);//防冲撞
}
if(!status) //防冲撞成功
{
status = PCD_ERR;
printf("卡的类型为:%x%x%x\r\n",CT[0],CT[1],CT[2]); //读取卡的类型 //读取卡的类型
printf("卡号:%x-%x-%x-%x\r\n",readUid[0],readUid[1],readUid[2],readUid[3]);
HAL_Delay(800);
status=PCD_Select(readUid);
}
if(!status) //选卡成功
{
status = PCD_ERR;
// 验证A密钥 块地址 密码 SN
status = PCD_AuthState(0x60, addr, KEY_A, readUid);
if(status == PCD_OK)//验证A成功
printf("A密钥验证成功\r\n");
else
printf("A密钥验证失败\r\n");
HAL_Delay(500);
// 验证B密钥 块地址 密码 SN
status = PCD_AuthState(0x61, addr, KEY_B, readUid);
if(status == PCD_OK)//验证B成功
printf("B密钥验证成功\r\n");
else
printf("B密钥验证失败\r\n");
}
HAL_Delay(500);
if(status == PCD_OK)//验证密码成功,接着读取0块
{
status = PCD_ERR;
status = PCD_ReadBlock(addr, DATA);
//PCD_WriteBlock(addr,myDATA);//写
if(status == PCD_OK)//读卡成功
{
printf("%d扇区%d块DATA:",NUM,num);
for(i = 0; i < 16; i++)
{
printf("%02x", DATA[i]);
}
printf("\r\n");
}
else
printf("读卡失败\r\n");
}
HAL_Delay(500);
}
//=================================================== 改进读写函数===============================================
//My_ReadBlock 函数用于读取某扇区的某块数据
/*
* BlockAddr : 地址 (4 * NUM ) + num NUM: 扇区(0~15) num: 块(0~3)
* *Data:储存数组
* num:需要读取几位数据,等于数组大小
* return: 返回1表示成功,2表示失败
*/
uint8_t My_ReadBlock(uint8_t BlockAddr, uint8_t *Data,uint8_t num)
{
uint16_t unLen;
uint8_t i, CmdFrameBuf[num+2];
CmdFrameBuf[0] = PICC_READ;
CmdFrameBuf[1] = BlockAddr;
MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
if((status == PCD_OK) && (unLen == 0x90))
{
for(i = 0; i < num; i++)
{
*(Data + i) = CmdFrameBuf[i];
}
}
else
{
return 2;
}
return 1;
}
//My_ReadBlock 函数用于写入某扇区的某块数据
/*
* BlockAddr : 地址 (4 * NUM ) + num NUM: 扇区(0~15) num: 块(0~3)
* *Data:写入的数组
* num:需要写入几位数据,等于数组大小
*/
void My_WriteBlock(uint8_t BlockAddr, uint8_t *pData,uint8_t num)
{
uint16_t unLen;
uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
CmdFrameBuf[0] = PICC_WRITE;
CmdFrameBuf[1] = BlockAddr;
MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
{
status = PCD_ERR;
}
if(status == PCD_OK)
{
for(i = 0; i < num; i++)
{
CmdFrameBuf[i] = *(pData + i);
}
MFRC_CalulateCRC(CmdFrameBuf, 16, &CmdFrameBuf[16]);
status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 18, CmdFrameBuf, &unLen);
if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
{
status = PCD_ERR;
}
}
}