基于CV627的非接通讯系列之(一)
CV627读写M1卡
知识点:
- 芯片特性及通讯
- 14443协议
- 针对不同类型卡不同读写流程
- 卡类型区分
扩展:
PBOC协议
非接读卡技术火了多年,小熊猫最近也在研究,就准备了一期来介绍一下(只讲解开发RFID过程的大体流程及遇上的困难)。
硬件部分:我是使用的RC630(NXP)作为读卡的芯片,该芯片支持波特率101 212 424 848(kbit/s),将近100个寄存器,FIFO缓存512byte,支持NFC点对点传输。支持SPI,I2C,串口通讯方式。
我选择SPI作为硬件通讯渠道。众所周知,RFID通讯遵循14443协议。
读卡流程如下:
先寻卡——防碰撞——获取卡UID——选卡——往下就根据卡不同而不同了。如下图
这期先讲M1卡读卡,下期讲CPU卡:
上代码:
底层驱动:
#include "spi.h"
#include "MFRC630.h"
#include "stdio.h"
#define RF_RST_Write(N) HAL_GPIO_WritePin(RST_PDOWN_GPIO_Port, RST_PDOWN_Pin, N==1?GPIO_PIN_SET:GPIO_PIN_RESET)
#define SPI2_CS_Write(N) HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, N==1?GPIO_PIN_SET:GPIO_PIN_RESET)
/******************************************************************************
*模拟SPI读写一个字
*******************************************************************************
static uint8_t ret;
uint8_t SPI2_RW_Byte(uint8_t byte)
{
HAL_SPI_TransmitReceive(&hspi2, &byte, &ret, 1, 10);
return ret;
}
static void WriteByte(uint8_t addr,uint8_t v)
{
SPI2_CS_Write(0);
SPI2_RW_Byte(addr << 1);
SPI2_RW_Byte(v);
SPI2_CS_Write(1);
}
static uint8_t ReadByte(uint8_t addr)
{
uint8_t data;
SPI2_CS_Write(0);
SPI2_RW_Byte((addr << 1) | 1);
data = SPI2_RW_Byte(0x00);
SPI2_CS_Write(1);
return data;
}
/*****************************************************************************
*设置寄存器的位
******************************************************************************/
void SetBitMask(uint8_t addr, uint8_t mask)
{
uint8_t temp;
temp = ReadByte(addr); //
WriteByte(addr, temp | mask);
}
/******************************************************************************
*清除寄存器的位
******************************************************************************/
void ClrBitMask(uint8_t addr, uint8_t mask)
{
uint8_t temp;
temp = ReadByte(addr); //
WriteByte(addr, temp & ~mask);
}
void MFRC630_SetIRQpin(unsigned char value)
{
WriteByte(IRQ1En_Reg,0xc0);
WriteByte(IRQ0En_Reg,value);
}
/******************************************************************************
*中间函数
******************************************************************************/
int MFRC663_Exchange1(uint8_t *pTxBuffer,uint8_t wTxLength,uint8_t *pRxBuffer,uint8_t * pRxLength,int timeout,uint8_t crc)
{
uint8_t temp;
int i,j;
WriteByte(IRQ0_Reg,0x7f);
WriteByte(IRQ0En_Reg,0x18);
if(crc)
{
WriteByte(TxCrcPreset_Reg,0x19);
}
ExchangeCommand(PCD_TRANSCEIVE,pTxBuffer,wTxLength);
HAL_Delay(5);
uint8_t cError = ReadByte(Error_Reg);
for(i = 0 ; i < timeout ; i ++)
{
if((ReadByte(IRQ0_Reg) & 0x18) == 0x18)
break;
HAL_Delay(1);
}
if(i == timeout)
{
//printf("printf timeout");
if(crc)
{
WriteByte(TxCrcPreset_Reg,0x18);
}
return - 1;
}
if(crc)
{
temp = ReadByte(FIFOLength_Reg);
uint8_t n2 = ReadByte(RxBitCtrl_Reg) & 0x07;
if (n2 != 0)
{
temp = (temp - 1) * 8 + n2;
}
else ;
for (j = 0; j < temp; j++)
{
pRxBuffer[j] = ReadByte(FIFOData_Reg);
}
}
*pRxLength = temp;
if(crc)
{
WriteByte(TxCrcPreset_Reg,0x18);
}
return 0;
}
void ExchangeCommand(uint8_t cmd,uint8_t *buff,uint8_t len)
{
uint8_t i , temp ;
WriteByte(Command_Reg,PCD_IDLE);
temp = ReadByte(FIFOControl_Reg);
WriteByte(FIFOControl_Reg,temp | 0x10);
for(i = 0 ; i < len ; i ++)
{
WriteByte(FIFOData_Reg,buff[i]);
}
WriteByte(Command_Reg,cmd);
}
/******************************************************************************
*寄存器初始化
******************************************************************************/
static void Reg_Init(void)
{
WriteByte(DrvMode_Reg,0x8e);
WriteByte(TxAmp_Reg,0x12); //12
WriteByte(DrvCon_Reg,0x39);
WriteByte(TxI_Reg,0x0a);
WriteByte(TxCrcPreset_Reg,0x18);
WriteByte(RxCrcPreset_Reg,0x18);
WriteByte(TxDataNum_Reg,0x0f);
WriteByte(TxModWidth_Reg,0x21);
WriteByte(TxSym10BurstLen_Reg,0x00);
WriteByte(TXWaitCtrl_Reg,0xc0);
WriteByte(TxWaitLo_Reg,0x12);
WriteByte(FrameCon_Reg,0xcf);
WriteByte(RxSofD_Reg,0x00);
WriteByte(RxCtrl_Reg,0x04);
WriteByte(RxWait_Reg,0x90);
WriteByte(RxThreshold_Reg,0x5c);
WriteByte(Rcv_Reg,0x12);
}
void MFRC630_Init(void)
{
/*???*/
RF_RST_Write(1);
HAL_Delay(2);
RF_RST_Write(0);
HAL_Delay(2);
}
/******************************************************************************
*PCD初始化
******************************************************************************/
void PCD_Init(void)
{
MFRC630_Init();
uint8_t txbuff[] = {PICC_REQALL, 0x00,0x00, 0x00, 0x00, 0x00, 0x00};
HAL_Delay(10);
LoadProtocol(Protocol106,Protocol106);
Reg_Init();
}
/******************************************************************************
*设置协议
******************************************************************************/
void LoadProtocol(uint8_t rxProtocol,uint8_t txProtocol)
{
WriteByte(IRQ0_Reg,0x7f);
WriteByte(IRQ0En_Reg,0x10);
WriteByte(FIFOData_Reg,rxProtocol);
WriteByte(FIFOData_Reg,txProtocol);
WriteByte(Command_Reg,PCD_LOADPROTOCOL);
while(!(ReadByte(IRQ0_Reg) & 0x10));
}
/******************************************************************************
*寻卡
******************************************************************************/
uint8_t FindCard(uint8_t mode)
{
uint8_t txbuff ;
uint8_t rxbuff[2];
uint8_t rxLen = 2;
if(mode == 0)
{
txbuff = PICC_REQIDL;
}
else
{
txbuff = PICC_REQALL;
}
WriteByte(Status_Reg,0x00);
WriteByte(TxDataNum_Reg,0x0f);
if(MFRC663_Exchange(&txbuff,1,rxbuff,&rxLen,2,0) == 0)
{
WriteByte(TxDataNum_Reg,0x08);
return rxbuff[0];
}
WriteByte(TxDataNum_Reg,0x08);
return -1;
}
/******************************************************************************
*获取卡UID
******************************************************************************/
uint8_t GetCardUid(uint8_t *uid)
{
uint8_t txbuff[] = {PICC_ANTICOLL1,0x20};
uint8_t rxbuff[5];
uint8_t rxLen = 5;
uint8_t temp;
temp = ReadByte(RxBitCtrl_Reg);
WriteByte(RxBitCtrl_Reg,0x00);
if(MFRC663_Exchange(txbuff,2,rxbuff,&rxLen,10,0) == 0)
{
WriteByte(RxBitCtrl_Reg,temp);
temp = rxbuff[0] ^ rxbuff[1] ^ rxbuff[2] ^ rxbuff[3] ;
if(rxbuff[4] == temp)
{
uid[0] = rxbuff[0];
uid[1] = rxbuff[1];
uid[2] = rxbuff[2];
uid[3] = rxbuff[3];
return 4;
}
return -1;
}
WriteByte(RxBitCtrl_Reg,temp);
return -1;
}
/******************************************************************************
*选卡
******************************************************************************/
uint8_t SelectCard(uint8_t *uid)
{
uint8_t txbuff[9];
uint8_t rxlen = 18;
uint8_t rxbuff[0x18];
uint8_t i;
txbuff[0] = PICC_ANTICOLL1;
txbuff[1] = 0x70;
txbuff[6] = 0;
for(i = 0 ; i < 4 ; i ++)
{
txbuff[i+2] = uid[i];
txbuff[6] ^= uid[i];
}
if(MFRC663_Exchange(txbuff,7,rxbuff,&rxlen,100,1) == 0)
{
return 0;
}
return -1;
}
uint8_t LoadKey(uint8_t *key)
{
WriteByte(IRQ0_Reg,0x7f);
WriteByte(IRQ0En_Reg,0x10);
ExchangeCommand(PCD_LOADKEY,key,6);
while(!(ReadByte(IRQ0_Reg) & 0x10));
return 0;
}
/******************************************************************************
*认证
******************************************************************************/
uint8_t AuthentBlock(uint8_t mode,uint8_t block,uint8_t *uid,uint8_t *key)
{
uint8_t i;
uint8_t buff[6];
LoadKey(key);
if(mode == 0)
{
buff[0] = 0x60;
}
else
{
buff[0] = 0x61;
}
buff[1] = block;
memcpy(buff + 2,uid,4);
WriteByte(IRQ0_Reg,0x7f);
WriteByte(IRQ0En_Reg,0x18);
ExchangeCommand(PCD_MFAUTHENT,buff,6);
HAL_Delay(2);
if(i == 50)
{
//return - 1;
}
if(ReadByte(Status_Reg) & 0x20)
return 0;
return -1;
}
/******************************************************************************
*写区
******************************************************************************/
uint8_t WriteSection(uint8_t addr,uint8_t *pData)
{
uint8_t txbuff[2];
uint8_t rxlen = 3;
uint8_t rxbuff[3];
txbuff[0] = PICC_WRITE;
txbuff[1] = addr;
if(MFRC663_Exchange(txbuff,2,rxbuff,&rxlen,100,1) == -1)
{
return -1;
}
if((rxbuff[0] & 0x0F) != 0x0A)
{
return -1;
}
rxlen = 3;
if(MFRC663_Exchange(pData,16,rxbuff,&rxlen,100,1) == -1)
{
return -1;
}
if((rxbuff[0] & 0x0F) != 0x0A){
return -1;
}
return 0;
}
/******************************************************************************
*读区
******************************************************************************/
uint8_t ReadSection(uint8_t addr,uint8_t *pData)
{
uint8_t txbuff[2];
uint8_t rxlen = 16;
txbuff[0] = PICC_READ;
txbuff[1] = addr;
if(MFRC663_Exchange(txbuff,2,pData,&rxlen,100,1) == -1)
{
return -1;
}
return 0;
}
Main调用
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "MFRC630.h"
void SystemClock_Config(void);
/*=================================================================
=================================================================*/
void SetArray(uint8_t* A,uint8_t value,uint8_t length)
{
uint8_t i;
for(i=0; i<length; i++)
{
A[i] = value;
}
}
/*=================================================================
=================================================================*/
uint8_t CompareArray(uint8_t* A,uint8_t* B,uint8_t length)
{
uint8_t i;
for(i=0; i<length; i++)
{
if(A[i] != B[i])
return 0;
}
return 1;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_UART4_Init();
MX_SPI2_Init();
uint8_t rfID[16] = {0x00,0x00,0x00,0x00};//
uint8_t label[17] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//
uint8_t labelW[17] = "0123456789ABCDEF";//
uint8_t myl_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
PCD_Init();
SetArray(label,0x00,16);
while (1)
{
HAL_Delay(500);
if((FindCard(0) != -1) && (GetCardUid(rfID) != -1))
{
if((SelectCard(rfID) == 0) && (AuthentBlock(0,20,rfID,myl_key) == 0))
//写标签
if(WriteSection(4,labelW) == 0)
{
printf("WriteSectionSuccess");
}
}
}
}
//以下是测试读标签
while (1)
{
HAL_Delay(500);
if((FindCard(0) != -1) && (GetCardUid(rfID) != -1))
{
if((SelectCard(rfID) == 0) && (AuthentBlock(0,20,rfID,myl_key) == 0))
//读标签
if((ReadSection(20,label) == 0) && CompareArray(label,labelW,16)) {
printf("\n ReadSectionSuccess LabelR %s\n",label);
}
}
}
}
各位朋友你会了吗?不会可以下载工程源代码(提示:解压密码要收5元)
链接: https://pan.baidu.com/s/1DlVZoxglz9-P5c-vNpJNaw?pwd=vgqu
提取码: vgqu
标签:return,cv627,0x00,uint8,非接,txbuff,M1,WriteByte,Reg From: https://www.cnblogs.com/simaSoft/p/16755543.html