RFID(NFC) CLRC663非接触读取芯片GD32/STM32 SPI读取

基本介绍

CLRC663 是高度集成的收发器芯片,用于 13.56 兆赫兹的非接触式通讯。CLRC663 收发器芯片支
持下列操作模式
• 读写模式支持 ISO/IEC 14443A/MIFARE
• 读写模式支持 SO/IEC 14443IB
• JIS X 6319-4 读写模式支持(等效于FeliCa1
方案,请参阅章节 21.5)
• 相应于 ISO/IEC 18092 的被动发起方模式
• 读写模式支持 ISO/IEC 15693
• 读写模式支持 ICODE EPC UID/EPC OTP
• 读写模式支持 ISO/IEC 18000-3 mode 3/ EPC Class-1 H
CLRC663 能够透过内建发射器直接驱动外置天线与 ISO/IEC 14443A 或 MIFARE 卡片进行通信,而无
需附加有源电路。数字模块负责全部的 ISO/IEC 14443A 组帧和错误检测功能(奇偶校验和 CRC 循環
冗餘校驗)。
CLRC663支持MIFARE Classic 1K,MIFARE Classic 4K,MIFARE Ultralight,MIFARE Ultralight C,
MIFARE PLUS和 MIFARE DESFire产品。CLRC663支持MIFARE高达848k位元/秒的更高双向传输速
度。
CLRC663支持ISO/IEC 14443B第2和第3层的读写通信方案,除了防碰撞(Anti-collision)功能。防碰
撞功能需在主机控制器的固件及更上层中执行。
CLRC663能进行FeliCa编码信号的解调和解码。FeliCa接收器器件提供为FeliCa编码信号的解调和解码
电路。CLRC663处理,如CRC的FeliCa的制定和错误检测。CLRC663支持FeliCa高达424k位元/秒的更
高速双向传输速度

芯片引脚如下
在这里插入图片描述
硬件连接如下
在这里插入图片描述

硬件配置连接

1供电VBAT和TVDD_INO给的3.3V
2 IFSEL1=1、IFSEL0=0
3 PD拉低
4PVDD高 TVDD高 VDD高
5IRQ拉低
6SPI按照标准4线进行连接

硬件连接详解

供电要求
VDD(PVDD)的伏特必须与VDD一样或更低

IFSEL1=1、IFSEL0=0 主要是用来设置SPI通讯,该芯片支持I2C UART SPI通讯
在这里插入图片描述

IRQ是中断请求,输出信号以示意中断事件,可以用来识别触发,可以配置成外部触发,当然直接拉低不使用也可以

SPI连接如图
在这里插入图片描述

程序代码

具体代码可以淘宝购买开发板提供。或者csdn搜索资源下载
阿松大

main.c主程序

#include <stdio.h>
#include "stm32f10x.h"
#include "RC663.h"

void System_Init(void);
int main()
{
	System_Init();
	
	RC663_Init();
	printf("reset!!!!\n");
	LED_1;

	while(1)
	{
		RC663_MifareClassic();	//ISO14443A
		RC663_ID2();	//ISO14443B 
		RC663_Felica();	//
		RC663_ISO15693();
		delay_ms(100);
	}
}

int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (uint8_t) ch);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
	return ch;
}

void System_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);
	RCC_PCLK1Config(RCC_HCLK_Div2);
	RCC_PCLK2Config(RCC_HCLK_Div1); 
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );
	
	UART1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = 115200;  		
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

	USART_Init(USART1, &USART_InitStructure);
	//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);			//Enable UART1 receive interrupt
	USART_Cmd(USART1, ENABLE);
	USART_ClearFlag(USART1, USART_FLAG_TC); 
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;				//flag pb10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	FLAG_0;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;				//led pc13
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	LED_0;
	delay_init(72);
}

RC663.h

#ifndef __RC663_H
#define __RC663_H

#include "stm32f10x.h"

#define UART_PRINT

#define	 RC663_NSS	 	GPIO_Pin_12				//PB12
#define	 RC663_NSS_0	 GPIO_ResetBits(GPIOB,RC663_NSS)
#define	 RC663_NSS_1	 GPIO_SetBits(GPIOB,RC663_NSS)

#define	 RC663_IRQ	 	GPIO_Pin_11			//PB11   

#define	 PDOWN	 		GPIO_Pin_8			//PA8
#define	 PDOWN_0	 	GPIO_ResetBits(GPIOA,PDOWN)
#define	 PDOWN_1	 	GPIO_SetBits(GPIOA,PDOWN)

#define	 FLAG_0	 	GPIO_ResetBits(GPIOB,GPIO_Pin_10)
#define	 FLAG_1	 	GPIO_SetBits(GPIOB,GPIO_Pin_10)

#define	 LED_0	 	GPIO_ResetBits(GPIOC,GPIO_Pin_13)
#define	 LED_1	 	GPIO_SetBits(GPIOC,GPIO_Pin_13)

/
#define rRegCommand 					0x00 // Starts and stops command execution
#define rRegHostCtrl 				0x01 // Host control register
#define rRegFIFOControl 			0x02 // Control register of the FIFO
#define rRegWaterLevel 			0x03 // Level of the FIFO underflow and overflow warning
#define rRegFIFOLength 			0x04 // Length of the FIFO
#define rRegFIFOData 				0x05 // Data In/Out exchange register of FIFO buffer
#define rRegIRQ0 						0x06 // Interrupt register 0
#define rRegIRQ1 						0x07 // Interrupt register 1
#define rRegIRQ0En 					0x08 // Interrupt enable register 0
#define rRegIRQ1En 					0x09 // Interrupt enable register 1
#define rRegError 						0x0A // Error bits showing the error status of the last command execution
#define rRegStatus 					0x0B // Contains status of the communication
#define rRegRxBitCtrl 				0x0C // Control register for anticollision adjustments for bit oriented protocols
#define rRegRxColl 					0x0D // Collision position register
#define rRegTControl 				0x0E // Control of Timer 0..3
#define rRegT0Control 				0x0F // Control of Timer0
#define rRegT0ReloadHi 			0x10 // High register of the reload value of Timer0
#define rRegT0ReloadLo 			0x11 // Low register of the reload value of Timer0
#define rRegT0CounterValHi 	0x12 // Counter value high register of Timer0
#define rRegT0CounterValLo 	0x13 // Counter value low register of Timer0
#define rRegT1Control 				0x14 // Control of Timer1
#define rRegT1ReloadHi 			0x15 // High register of the reload value of Timer1
#define rRegT1ReloadLo 			0x16 // Low register of the reload value of Timer1
#define rRegT1CounterValHi 	0x17 // Counter value high register of Timer1
#define rRegT1CounterValLo 	0x18 // Counter value low register of Timer1
#define rRegT2Control 				0x19 // Control of Timer2
#define rRegT2ReloadHi 			0x1A // High byte of the reload value of Timer2
#define rRegT2ReloadLo 			0x1B // Low byte of the reload value of Timer2
#define rRegT2CounterValHi 	0x1C // Counter value high byte of Timer2
#define rRegT2CounterValLo 	0x1D // Counter value low byte of Timer2
#define rRegT3Control 				0x1E // Control of Timer3
#define rRegT3ReloadHi 			0x1F // High byte of the reload value of Timer3
#define rRegT3ReloadLo 			0x20 // Low byte of the reload value of Timer3
#define rRegT3CounterValHi 	0x21 // Counter value high byte of Timer3
#define rRegT3CounterValLo 	0x22 // Counter value low byte of Timer3
#define rRegT4Control 				0x23 // Control of Timer4
#define rRegT4ReloadHi 			0x24 // High byte of the reload value of Timer4
#define rRegT4ReloadLo 			0x25 // Low byte of the reload value of Timer4
#define rRegT4CounterValHi 	0x26 // Counter value high byte of Timer4
#define rRegT4CounterValLo 	0x27 // Counter value low byte of Timer4
#define rRegDrvMod 					0x28 // Driver mode register
#define rRegTxAmp 						0x29 // Transmitter amplifier register
#define rRegDrvCon 					0x2A // Driver configuration register
#define rRegTxl 							0x2B // Transmitter register
#define rRegTxCrcPreset 			0x2C // Transmitter CRC control register, preset value
#define rRegRxCrcPreset 			0x2D // Receiver CRC control register, preset value
#define rRegTxDataNum 				0x2E // Transmitter data number register
#define rRegTxModWidth 			0x2F // Transmitter modulation width register
#define rRegTxSym10BurstLen 	0x30 // Transmitter symbol 1 + symbol 0 burst length register
#define rRegTXWaitCtrl 			0x31 // Transmitter wait control
#define rRegTxWaitLo 				0x32 // Transmitter wait low
#define rRegFrameCon 				0x33 // Transmitter frame control
#define rRegRxSofD 					0x34 // Receiver start of frame detection
#define rRegRxCtrl 					0x35 // Receiver control register
#define rRegRxWait 					0x36 // Receiver wait register
#define rRegRxThreshold 			0x37 // Receiver threshold register
#define rRegRcv 							0x38 // Receiver register
#define rRegRxAna 						0x39 // Receiver analog register
#define rRegRFU_3A						0x3A // -
#define rRegSerialSpeed 			0x3B // Serial speed register
#define rRegLFO_Trimm 				0x3C // Low-power oscillator trimming register
#define rRegPLL_Ctrl 				0x3D // IntegerN PLL control register, for microcontroller clock output adjustment
#define rRegPLL_DivOut 			0x3E // IntegerN PLL control register, for microcontroller clock output adjustment
#define rRegLPCD_QMin 				0x3F // Low-power card detection Q channel minimum threshold
#define rRegLPCD_QMax 				0x40 // Low-power card detection Q channel maximum threshold
#define rRegLPCD_IMin 				0x41 // Low-power card detection I channel minimum threshold
#define rRegLPCD_I_Result 		0x42 // Low-power card detection I channel result register
#define rRegLPCD_Q_Result 		0x43 // Low-power card detection Q channel result register
#define rRegPadEn 						0x44 // PIN enable register
#define rRegPadOut 					0x45 // PIN out register
#define rRegPadIn 						0x46 // PIN in register
#define rRegSigOut 					0x47 // Enables and controls the SIGOUT Pin
#define rRegTxBitMod 				0x48 // Transmitter bit mode register
#define rRegRFU_49						0x49 // -
#define rRegTxDataCon 				0x4A // Transmitter data configuration register
#define rRegTxDataMod 				0x4B // Transmitter data modulation register
#define rRegTxSymFreq 				0x4C // Transmitter symbol frequency
#define rRegTxSym0H 					0x4D // Transmitter symbol 0 high register
#define rRegTxSym0L 					0x4E // Transmitter symbol 0 low register
#define rRegTxSym1H 					0x4F // Transmitter symbol 1 high register
#define rRegTxSym1L 					0x50 // Transmitter symbol 1 low register
#define rRegTxSym2 					0x51 // Transmitter symbol 2 register
#define rRegTxSym3 					0x52 // Transmitter symbol 3 register
#define rRegTxSym10Len 			0x53 // Transmitter symbol 1 + symbol 0 length register
#define rRegTxSym32Len 			0x54 // Transmitter symbol 3 + symbol 2 length register
#define rRegTxSym10BurstCtrl 0x55 // Transmitter symbol 1 + symbol 0 burst control register
#define rRegTxSym10Mod 			0x56 // Transmitter symbol 1 + symbol 0 modulation register
#define rRegTxSym32Mod 			0x57 // Transmitter symbol 3 + symbol 2 modulation register
#define rRegRxBitMod 				0x58 // Receiver bit modulation register
#define rRegRxEofSym 				0x59 // Receiver end of frame symbol register
#define rRegRxSyncValH 			0x5A // Receiver synchronisation value high register
#define rRegRxSyncValL 			0x5B // Receiver synchronisation value low register
#define rRegRxSyncMod 				0x5C // Receiver synchronisation mode register
#define rRegRxMod 						0x5D // Receiver modulation register
#define rRegRxCorr 					0x5E // Receiver correlation register
#define rRegFabCal 					0x5F // Calibration register of the receiver, calibration performed at production
#define rReg_60 							0x60 //
#define rReg_61 							0x61 //
#define rReg_66 							0x66 //
#define rReg_6A 							0x6A //
#define rReg_6B 							0x6B //
#define rReg_6C 							0x6C //
#define rReg_6D 							0x6D //
#define rReg_6E 							0x6E //
#define rReg_6F 							0x6F //
#define rRegVersion 					0x7F // Version and subversion register
//
//		Command 			No. Parameter (bytes) 	Short description
#define RC663_Idle 				0x00 //- 					no action, cancels current command execution
#define RC663_LPCD 				0x01 //- 					low-power card detection
#define RC663_LoadKey 		0x02 //(keybyte1..6); 		reads a MIFARE key (size of 6 bytes) from FIFO buffer and puts it into Key buffer
#define RC663_MFAuthent 	0x03 //60h or 61h,(block address),(card serial number byte0..3) 	performs the MIFARE standard authentication in MIFARE read/write mode only
#define RC663_AckReq 			0x04 //- 					performs a query, an Ack and a Req-Rn for ISO/IEC 18000-3 mode 3/ EPC Class-1 HF
#define RC663_Receive 		0x05 //- 					activates the receive circuit
#define RC663_Transmit 		0x06 //- 					transmits data from the FIFO buffer
#define RC663_Transceive 	0x07 //- 					transmits data from the FIFO buffer and automatically activates the receiver after transmission finished
#define RC663_WriteE2 		0x08 //addressH, addressL, data; 	gets one byte from FIFO buffer and writes it to the internal EEPROM, 
#define RC663_WriteE2Page 0x09 //(page Address), data0, [data1..data63]; 	gets up to 64 bytes (one EEPROM page) from the FIFO buffer and writes it to the EEPROM
#define RC663_ReadE2 			0x0A // address H, addressL,length; 	reads data from the EEPROM and copies it into the FIFO buffer
#define RC663_LoadReg 		0x0C //(EEPROM addressL), (EEPROM addressH), RegAdr, (number of Register to be copied);  reads data from the internal EEPROM and initializes the CLRC663 registers. EEPROM address needs to be within EEPROM sector 2
#define RC663_LoadProtocol 0x0D //(Protocol number RX), (Protocol number TX);		reads data from the internal EEPROM and initializes the CLRC663 registers needed for a Protocol change
#define RC663_LoadKeyE2 	0x0E //KeyNr; 				copies a key of the EEPROM into the key buffer
#define RC663_StoreKeyE2 	0x0F //KeyNr, byte1..6;	stores a MIFARE key (size of 6 bytes) into the EEPROM
#define RC663_ReadRNR 		0x1C //- 					Copies bytes from the Random Number generator into the FIFO until the FiFo is full
#define RC663_Soft_Reset 	0x1F //- 					resets the CLRC663

//
void delay_init(u8 SYSCLK);
void delay_us(u32);
void delay_ms(u16);

void RC663_Init(void);
u8 RC663_ReadReg(u8);
void RC663_WriteReg(u8, u8);

s8 RC663_CMD_ReadE2(u16 addr,u8 len,u8 *pdat);
s8 RC663_CMD_WriteE2(u16 addr,u8 dat);
s8 RC663_CMD_LoadProtocol(u8 rx,u8 tx);
s8 RC663_PcdConfigISOType(u8 type);
void RC663_MifareClassic(void);
void RC663_ID2(void);
void RC663_Felica(void);
void RC663_ISO15693(void);

s8 RC663_Lpcd_Calib(u8 *pI,u8 *pQ);
s8 RC663_Lpcd_Det(u8 ValueI,u8 ValueQ);

#endif

#include “RC663.h”
#include “nfc.h”
#include <stdio.h>
#include <string.h>

static u8 fac_us=0;
static u16 fac_ms=0;

//delay
void delay_ns(u32 ns)
{
u32 i;
for(i=0;i<ns;i++)
{
__nop();
__nop();
__nop();
}
}

void delay_init(u8 SYSCLK) //unit:MHz
{
SysTick->CTRL &= 0xfffffffb;//select internal clk: HCLK/8
fac_us = SYSCLK/8;
fac_ms = (u16)fac_us*1000;
}

void delay_us(u32 Nus)
{
SysTick->LOAD=Nus*fac_us; //load time
SysTick->CTRL|=0x01; //start count
while(!(SysTick->CTRL&(1<<16)));//wait time out
SysTick->CTRL=0X00000000; //close counter
SysTick->VAL=0X00000000; //clear counter
}

void delay_ms(u16 nms) //nms <= 0xffffff8/SYSCLK; for 72M, Nms<=1864
{
SysTick->LOAD=(u32)nms
fac_ms;
SysTick->CTRL|=0x01;
while(!(SysTick->CTRL&(1<<16)));
SysTick->CTRL&=0XFFFFFFFE;
SysTick->VAL=0X00000000;
}

/
void RC663_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
u8 temp;

GPIO_InitStructure.GPIO_Pin = PDOWN;	 					//PA8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
GPIO_Init(GPIOA, &GPIO_InitStructure);
PDOWN_1;

GPIO_InitStructure.GPIO_Pin = RC663_IRQ;  					//PB11	
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

/* Enable AFIO clock */	
/* Connect EXTI9 Line to PC.9 pin */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);	 //IRQ
/* Configure EXTI6 line */
EXTI_InitStructure.EXTI_Line = EXTI_Line11; // pb11
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  	//falling edge of IRQ result interrupt
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);	

//IFSEL0,IFSEL1:0 1
//RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );
GPIO_InitStructure.GPIO_Pin = RC663_NSS;	 			
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
GPIO_Init(GPIOB, &GPIO_InitStructure);					 
RC663_NSS_1;			             

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;//SPI_BaudRatePrescaler_64;	
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	
SPI_InitStructure.SPI_CRCPolynomial = 7;	
SPI_Init(SPI2, &SPI_InitStructure);  
SPI_Cmd(SPI2, ENABLE); 

PDOWN_0;	//	->RESET
delay_ms(30);
temp = RC663_ReadReg(rRegVersion);

#ifdef UART_PRINT
printf(“version: %X\n”,temp);
#endif
}

//
u8 RC663_SPIWriteByte(u8 Byte)
{
while((SPI2->SR&0X02)==0);
SPI2->DR=Byte;
while((SPI2->SR&0X01)==0);
return SPI2->DR;
}

/

void RC663_WriteReg(u8 Address, u8 value)
{
RC663_NSS_0;
RC663_SPIWriteByte(Address<<1);
RC663_SPIWriteByte(value);
RC663_NSS_1;
delay_ns(10);
}

u8 RC663_ReadReg(u8 Address)
{
u8 ucResult=0;
RC663_NSS_0;
RC663_SPIWriteByte((Address<<1)|0x01);
ucResult = RC663_SPIWriteByte(0);
RC663_NSS_1;
delay_ns(10);
return ucResult;
}

void RC663_SetBitMask(u8 reg,u8 mask)
{
u8 tmp = RC663_ReadReg(reg);
RC663_WriteReg(reg,tmp | mask);
}

void RC663_ClearBitMask(u8 reg,u8 mask)
{
u8 tmp = RC663_ReadReg(reg);
RC663_WriteReg(reg, tmp & ~mask);
}

void RC663_SetRawRC(u8 reg,u8 mask,u8 set)
{
u8 temp = RC663_ReadReg(reg);
temp = (temp&mask)|set;
RC663_WriteReg(reg,temp);
}
///
void RC663_FlushFifo()
{
RC663_SetBitMask(rRegFIFOControl,0x10);
}

void RC663_FieldOn()
{
RC663_SetBitMask(rRegDrvMod,0x08);
}

void RC663_FieldOff()
{
RC663_ClearBitMask(rRegDrvMod,0x08);
}

void RC663_FieldReset()
{
RC663_FieldOff();
delay_ms(20);
RC663_FieldOn();
delay_ms(20);
}

extern u8 Status_INT;
u8 mode;
s8 RC663_Command_Int(struct TranSciveBuffer *pi)
{
u16 i;
u8 j,n;
RC663_WriteReg(rRegCommand,RC663_Idle);
RC663_SetBitMask(rRegFIFOControl,0x10); //FlushFifo
RC663_WriteReg(rRegIRQ0,0x7F);
RC663_WriteReg(rRegIRQ1,0x7F);

for(n=0;n<pi->Length;n++)
	RC663_WriteReg(rRegFIFOData, pi->Data[n]);
if(pi->Command&0x80)
{
	RC663_WriteReg(rRegIRQ0En,0x90);		
	if(mode)
		RC663_WriteReg(rRegIRQ1En,0xE0);		
	else
		RC663_WriteReg(rRegIRQ1En,0xE8);		
	
	Status_INT=0;
	RC663_WriteReg(rRegCommand, pi->Command);
	while(Status_INT==0);				//wait for IRQ
	Status_INT=0;
	
	RC663_WriteReg(rRegIRQ0En,0x10);		
	if(mode)
		RC663_WriteReg(rRegIRQ1En,0x20);		
	else
		RC663_WriteReg(rRegIRQ1En,0x28);		
}
else
	RC663_WriteReg(rRegCommand, pi->Command);

for(i=2000;i>0;i--)
{
	n = RC663_ReadReg(rRegIRQ0);	
	if(n&0x10) break;		//IDLEIRQ
}
if(i==0)
	return MI_ERR;
n = RC663_ReadReg(rRegFIFOLength);
for(j=0;j<n;j++)
	pi->Data[j]= RC663_ReadReg(rRegFIFOData);
return MI_OK;

}

s8 RC663_CMD_LoadProtocol(u8 rx,u8 tx)
{
struct TranSciveBuffer ComData;

ComData.Command = RC663_LoadProtocol;
ComData.Length = 2;
ComData.Data[0] = rx;
ComData.Data[1] = tx;

return RC663_Command_Int(&ComData);

}

s8 RC663_CMD_LoadKey(u8* pkey)
{
struct TranSciveBuffer ComData;

ComData.Command = RC663_LoadKey;
ComData.Length = 6;
memcpy(ComData.Data,pkey,6);

return RC663_Command_Int(&ComData);

}

s8 RC663_CMD_MfcAuthenticate(u8 auth_mode,u8 block,u8 *pSnr)
{
s8 status;
u8 reg;
struct TranSciveBuffer ComData;

ComData.Command = RC663_MFAuthent;
ComData.Length = 6;
ComData.Data[0] = auth_mode;
ComData.Data[1] = block;
memcpy(&ComData.Data[2],pSnr,4);

status= RC663_Command_Int(&ComData);
if(status==MI_OK)
{
	reg = RC663_ReadReg(rRegStatus);
	if(!(reg&0x20))
		status=MI_AUTHERR;
}
return status;

}

s8 RC663_PcdConfigISOType(u8 type)
{
// u8 temp;
RC663_WriteReg(rRegT0Control,0x98); //Starts at the end of Tx. Stops after Rx of first data. Auto-reloaded. 13.56 MHz input clock.
RC663_WriteReg(rRegT1Control,0x92); //Starts at the end of Tx. Stops after Rx of first data. Input clock - cascaded with Timer-0.
RC663_WriteReg(rRegT2Control,0x20); //Timer used for LFO trimming
RC663_WriteReg(rRegT2ReloadHi,0x03); //
RC663_WriteReg(rRegT2ReloadLo,0xFF); //
RC663_WriteReg(rRegT3Control,0x00); //Not started automatically. Not reloaded. Input clock 13.56 MHz
if(type==‘A’)
{
RC663_WriteReg(rRegWaterLevel,0x10); //Set WaterLevel =(FIFO length -1)

	RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
	RC663_WriteReg(rRegDrvMod,0x80);	//Tx2Inv=1
	RC663_WriteReg(rRegTxAmp,0xC0);	// 0x00
	RC663_WriteReg(rRegDrvCon,0x09);	//01
	RC663_WriteReg(rRegTxl,0x05);	//
	RC663_WriteReg(rRegRxSofD,0x00);	//
	
	RC663_CMD_LoadProtocol(0,0);

	// Disable Irq 0,1 sources
	RC663_WriteReg(rRegIRQ0En,0);
	RC663_WriteReg(rRegIRQ1En,0);
	
	RC663_WriteReg(rRegFIFOControl,0xB0);

	RC663_WriteReg(rRegTxModWidth,0x20); // Length of the pulse modulation in carrier clks+1  
	RC663_WriteReg(rRegTxSym10BurstLen,0); // Symbol 1 and 0 burst lengths = 8 bits.
	RC663_WriteReg(rRegFrameCon,0xCF); // Start symbol=Symbol2, Stop symbol=Symbol3
	
	RC663_WriteReg(rRegRxCtrl,0x04); // Set Rx Baudrate 106 kBaud 
	RC663_WriteReg(rRegRxThreshold,0x55); // Set min-levels for Rx and phase shift  //32 
	RC663_WriteReg(rRegRcv,0x12);	//
	RC663_WriteReg(rRegRxAna,0x0A); //0
	
	RC663_WriteReg(rRegDrvMod,0x81);
	//> MIFARE Crypto1 state is further disabled.
	RC663_WriteReg(rRegStatus,0);
	//>  FieldOn
	RC663_WriteReg(rRegDrvMod,0x89);
}
else if(type=='B')
{
	RC663_WriteReg(rRegWaterLevel,0x10);	//Set WaterLevel =(FIFO length -1)
									 
	RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
	RC663_WriteReg(rRegDrvMod,0x8F);	//Tx2Inv=1
	RC663_WriteReg(rRegTxAmp,0x0C);	// 0xCC	
	RC663_WriteReg(rRegDrvCon,0x01);	
	RC663_WriteReg(rRegTxl,0x05);	
	RC663_WriteReg(rRegRxSofD,0x00);	
	
	RC663_CMD_LoadProtocol(4,4);

	// Disable Irq 0,1 sources
	RC663_WriteReg(rRegIRQ0En,0);
	RC663_WriteReg(rRegIRQ1En,0);
	
	RC663_WriteReg(rRegFIFOControl,0xB0);

	RC663_WriteReg(rRegTxModWidth,0x0A); // Length of the pulse modulation in carrier clks+1  
	RC663_WriteReg(rRegTxSym10BurstLen,0); // Symbol 1 and 0 burst lengths = 8 bits.
	RC663_WriteReg(rRegTXWaitCtrl,1);	
	RC663_WriteReg(rRegFrameCon,0x05); 
	RC663_WriteReg(rRegRxSofD,0xB2);
	
	RC663_WriteReg(rRegRxCtrl,0x34); // Set Rx Baudrate 106 kBaud 
	RC663_WriteReg(rRegRxThreshold,0x9F); // Set min-levels for Rx and phase shift  0x7F 
	RC663_WriteReg(rRegRcv,0x12);
	RC663_WriteReg(rRegRxAna,0x0a); //0x0a 0X0e
	
	RC663_WriteReg(rRegDrvMod,0x87);
	RC663_WriteReg(rRegStatus,0);
	//>  FieldOn
	RC663_WriteReg(rRegDrvMod,0x8F);
}
else if(type=='F')
{
	RC663_WriteReg(rRegWaterLevel,0x10);	//Set WaterLevel =(FIFO length -1)
									 
	RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
	RC663_WriteReg(rRegDrvMod,0x88);	//Tx2Inv=1
	RC663_WriteReg(rRegTxAmp,0x04);	//
	RC663_WriteReg(rRegDrvCon,0x01);	//
	RC663_WriteReg(rRegTxl,0x05);	//
	RC663_WriteReg(rRegRxSofD,0x00);	//
	
	RC663_CMD_LoadProtocol(8,8);

	// Disable Irq 0,1 sources
	RC663_WriteReg(rRegIRQ0En,0);
	RC663_WriteReg(rRegIRQ1En,0);
	
	RC663_WriteReg(rRegFIFOControl,0xB0);
	
	RC663_WriteReg(rRegTxModWidth,0x00); // Length of the pulse modulation in carrier clks+1  
	RC663_WriteReg(rRegTxSym10BurstLen,0x03); // Symbol 1 and 0 burst lengths = 8 bits.
	//RC663_WriteReg(rRegTXWaitCtrl,0xC0);	
	//RC663_WriteReg(rRegTxWaitLo,0);
	RC663_WriteReg(rRegFrameCon,0x01);
	
	//RC663_WriteReg(rRegRxSofD,0xB2);
	
	RC663_WriteReg(rRegRxCtrl,0x05); // Set Rx Baudrate 212 kBaud 
	RC663_WriteReg(rRegRxThreshold,0x5C); // Set min-levels for Rx and phase shift  0x3C 
	RC663_WriteReg(rRegRcv,0x12);
	RC663_WriteReg(rRegRxAna,0x02); //0xa  initial value 0x02
	
	RC663_WriteReg(rRegRxWait,0x86);
	
	RC663_WriteReg(rRegDrvMod,0x87);
	RC663_WriteReg(rRegStatus,0);
	//>  FieldOn
	RC663_WriteReg(rRegDrvMod,0x8F);
}
else if(type=='V')
{
	RC663_WriteReg(rRegWaterLevel,0x10);	//Set WaterLevel =(FIFO length -1)
									 
	RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
	RC663_WriteReg(rRegDrvMod,0x89);	//Tx2Inv=1 0x80
	RC663_WriteReg(rRegTxAmp,0x10);	//0	//0x04
	RC663_WriteReg(rRegDrvCon,0x09);	//0x01
	RC663_WriteReg(rRegTxl,0x0A);	//0x05
	RC663_WriteReg(rRegRxSofD,0x00);	//
	
	RC663_CMD_LoadProtocol(0x0A,0x0A);

	// Disable Irq 0,1 sources
	RC663_WriteReg(rRegIRQ0En,0);
	RC663_WriteReg(rRegIRQ1En,0);
	
	RC663_WriteReg(rRegFIFOControl,0xB0);
	
	RC663_WriteReg(rRegTxModWidth,0x00); // Length of the pulse modulation in carrier clks+1  
	RC663_WriteReg(rRegTxSym10BurstLen,0); // Symbol 1 and 0 burst lengths = 8 bits.
	//RC663_WriteReg(rRegTXWaitCtrl,0xC0);	//0x88
	//RC663_WriteReg(rRegTxWaitLo,0);	//0xa9
	RC663_WriteReg(rRegFrameCon,0x0F);
	
	//RC663_WriteReg(rRegRxSofD,0xB2);
	
	RC663_WriteReg(rRegRxCtrl,0x02); // Set Rx Baudrate 26 kBaud 
	RC663_WriteReg(rRegRxThreshold,0x74); // Set min-levels for Rx and phase shift  
	RC663_WriteReg(rRegRcv,0x12);
	RC663_WriteReg(rRegRxAna,0x07); 
	
	RC663_WriteReg(rRegRxWait,0x9C);	
	
	RC663_WriteReg(rRegDrvMod,0x81);
	RC663_WriteReg(rRegStatus,0);
	//>  FieldOn
	RC663_WriteReg(rRegDrvMod,0x89);
}
return MI_OK;

}

s8 RC663_PcdComTransceive(struct TranSciveBuffer *pi)
{
s8 status= MI_ERR;
u16 i;
u8 reg1,temp,lastBits; //reg0,
u8 errReg;
// Terminate any running command.
RC663_WriteReg(rRegCommand,RC663_Idle); // 0x00 // Starts and stops command execution
RC663_SetBitMask(rRegFIFOControl,0x10); //Flush_FiFo 0x02 // Control register of the FIFO
// Clear all IRQ 0,1 flags
RC663_WriteReg(rRegIRQ0,0x7F);
RC663_WriteReg(rRegIRQ1,0x7F);

for(i=0;i<pi->Length;i++)
	RC663_WriteReg(rRegFIFOData,pi->Data[i]);           //  0x05 // Data In/Out exchange register of FIFO buffer
// Idle interrupt(Command terminated), RC663_BIT_IDLEIRQ=0x10
RC663_WriteReg(rRegIRQ0En,0x18);	//IdleIRQEn,TxIRQEn
RC663_WriteReg(rRegIRQ1En,0x42);	//Global IRQ,Timer1IRQEn
//>  Start RC663 command "Transcieve"=0x07. Activate Rx after Tx finishes.
RC663_WriteReg(rRegCommand,RC663_Transceive);

do	

{
reg1 = RC663_ReadReg(rRegIRQ1); //07h //wait for TxIRQ
}while((reg1&0x40)==0); //GlobalIRQ

RC663_WriteReg(rRegIRQ0En,0x54);	//HiAlertIRQEN,IdleIRQEn,RxIRQEn
RC663_WriteReg(rRegIRQ1En,0x42);	//Global IRQ,Timer1IRQEn

for(i=8000;i>0;i--)
{
	reg1 = RC663_ReadReg(rRegIRQ1);	  //07h  //wait for RxIRQ
	if(reg1&0x40) break;	//GlobalIRQ
}

RC663_WriteReg(rRegIRQ0En,0);		
RC663_WriteReg(rRegIRQ1En,0);

errReg = RC663_ReadReg(rRegError);
if(i==0)
	status = MI_QUIT;
else if(reg1&0x02)		//Timer1IRQ
	status = MI_NOTAGERR;
else if( errReg)	  //0Bh
{
	if(errReg&0x04)
		status = MI_COLLERR;
	else if(errReg&0x01)
		status = MI_FRAMINGERR;
	else
		status = MI_ERR;
}
else
{
	status = MI_OK;
	if (pi->Command == RC663_Transceive)
	{
			temp = RC663_ReadReg(rRegFIFOLength);		 //04h
			lastBits = RC663_ReadReg(rRegRxBitCtrl) & 0x07;	 //0ch
			if (lastBits)
				pi->Length = (temp-1)*8 + lastBits;
			else
				pi->Length = temp*8;
			if (temp == 0)	temp = 1;
			if (temp > 250) temp = 250; //maxlen ...
			for (i=0; i<temp; i++)
				pi->Data[i] = RC663_ReadReg(rRegFIFOData);  //05h
	}
}
return status;

}
s8 RC663_PcdHaltA(void)
{
s8 status;
struct TranSciveBuffer ComData,*pi= &ComData;

ComData.Command = RC663_Transceive;
ComData.Length  = 2;
ComData.Data[0] = PICC_HALT;
ComData.Data[1] = 0;

status = RC663_PcdComTransceive(pi);
if(status == MI_NOTAGERR)		//halt command has no response
	status = MI_OK;
else
	status = MI_ERR;
return status;

}

s8 RC663_PcdRequestA(u8 req_code,u8 *pTagType)
{
s8 status;
struct TranSciveBuffer ComData,*pi= &ComData;

RC663_WriteReg(rRegTxCrcPreset,0x18);  //0x2C Transmitter CRC control register, preset value
RC663_WriteReg(rRegRxCrcPreset,0x18);
RC663_WriteReg(rRegStatus,0);           //  0x0B  Contains status of the communication

RC663_WriteReg(rRegTXWaitCtrl,0xC0);	//0x31  TxWaitStart at the end of Rx data
RC663_WriteReg(rRegTxWaitLo,0x0B);	// 0x32   Set min.time between Rx and Tx or between two Tx   
// Set timeout for this command cmd. Init reload values for timers-0,1 
RC663_WriteReg(rRegT0ReloadHi,0x08); 	//2196/fc        0x10 // High register of the reload value of Timer0
RC663_WriteReg(rRegT0ReloadLo,0x94);            //0x11 // Low register of the reload value of Timer0
RC663_WriteReg(rRegT1ReloadHi,0);                     //0x15 // High register of the reload value of Timer1
RC663_WriteReg(rRegT1ReloadLo,0x40);	//timerout ~= 10ms      	0x16 // Low register of the reload value of Timer1

RC663_WriteReg(rRegIRQ0,0x08);                          //	0x06 // Interrupt register 0
RC663_WriteReg(rRegRxWait,0x90);                            //0x36 // Receiver wait register
RC663_WriteReg(rRegTxDataNum,0x0F);  //7bit                      0x2E // Transmitter data number register

//> Send the ReqA command
ComData.Command = RC663_Transceive;           //0x07 //- transmits data from the FIFO buffer and automatically activates the receiver after transmission finished
ComData.Length  = 1;
ComData.Data[0] = req_code;
FLAG_1;
status = RC663_PcdComTransceive(pi);
FLAG_0;
if (status == MI_OK)
{
	if(ComData.Length == 0x10)
	{
		*pTagType     = ComData.Data[0];
		*(pTagType+1) = ComData.Data[1];
	}
	else
		status = MI_VALERR;
}
//RC663_WriteReg(rRegTxDataNum,0x08);
return status;

}

s8 RC663_PcdAnticoll(u8 *pSnr)
{
s8 status ;
u8 i;
u8 ucBits,ucBytes;
u8 snr_check = 0;
u8 ucCollPosition = 0;
u8 ucTemp;
u8 ucSNR[5] = {0, 0, 0, 0 ,0};
struct TranSciveBuffer ComData,*pi = &ComData;

	RC663_WriteReg(rRegTxDataNum,0x08);
do
{
		ucBits = (ucCollPosition) % 8;
		if (ucBits != 0)
		{
		    ucBytes = ucCollPosition / 8 + 1;
				RC663_SetRawRC(rRegRxBitCtrl, 0x8f,ucBits<<4);
				RC663_SetRawRC(rRegTxDataNum, 0xf8,ucBits);
		}
		else
		     ucBytes = ucCollPosition / 8;

		ComData.Command = RC663_Transceive;
		ComData.Data[0] = PICC_ANTICOLL1;
		ComData.Data[1] = 0x20 + ((ucCollPosition / 8) << 4) + (ucBits & 0x0F);
		for (i=0; i<ucBytes; i++)
		  ComData.Data[i + 2] = ucSNR[i];
		ComData.Length = ucBytes + 2;

    status = RC663_PcdComTransceive(pi);

    ucTemp = ucSNR[(ucCollPosition / 8)];
		if (status == MI_COLLERR)
		{
		  for (i=0; i < 5 - (ucCollPosition / 8); i++)
		     ucSNR[i + (ucCollPosition / 8)] = ComData.Data[i+1];
		  ucSNR[(ucCollPosition / 8)] |= ucTemp;
		  ucCollPosition = ComData.Data[0];
		}
		else if (status == MI_OK)
		{
	    for (i=0; i < (ComData.Length / 8); i++)
	       ucSNR[4 - i] = ComData.Data[ComData.Length/8 - i - 1];
	    ucSNR[(ucCollPosition / 8)] |= ucTemp;
		}
} while (status == MI_COLLERR);
		
if (status == MI_OK)
{
	 for (i=0; i<4; i++)
   {   
     *(pSnr+i)  = ucSNR[i];
     snr_check ^= ucSNR[i];
   }
   if (snr_check != ucSNR[i])
   	status = MI_COM_ERR;
}
return status;

}

s8 RC663_PcdSelect(u8 *pSnr,u8 *pSize)
{
s8 status;
u8 i,snr_check = 0;
struct TranSciveBuffer ComData,*pi = &ComData;

RC663_SetRawRC(rRegTxCrcPreset,0xfe,0x01);	//On
RC663_SetRawRC(rRegRxCrcPreset,0xfe,0x01);	//On

ComData.Command = RC663_Transceive;
ComData.Length  = 7;
ComData.Data[0] = PICC_ANTICOLL1;
ComData.Data[1] = 0x70;
for (i=0; i<4; i++)
{
	snr_check ^= *(pSnr+i);
	ComData.Data[i+2] = *(pSnr+i);
}
ComData.Data[6] = snr_check;

status = RC663_PcdComTransceive(pi);

if (status == MI_OK)
{
if (ComData.Length != 0x8)
	status = MI_BITCOUNTERR;
else
	*pSize = ComData.Data[0];
}
return status;

}

s8 RC663_PcdRead(u8 addr,u8 *pReaddata)
{
s8 status;
struct TranSciveBuffer ComData,*pi = &ComData;

RC663_SetRawRC(rRegTxCrcPreset,0xfe,0x01);	//on
RC663_SetRawRC(rRegRxCrcPreset,0xfe,0x00);	//off

ComData.Command = RC663_Transceive;
ComData.Length = 2;
ComData.Data[0] = PICC_READ;
ComData.Data[1] = addr;

status = RC663_PcdComTransceive(pi);

if (status == MI_OK)
{
if (ComData.Length != 0x90)
status = MI_BITCOUNTERR;
else
memcpy(pReaddata, &ComData.Data[0], 16);
}
return status;
}

s8 RC663_PcdWrite(u8 addr,u8 *pWritedata)
{
s8 status;
struct TranSciveBuffer ComData,*pi = &ComData;

ComData.Command = RC663_Transceive;
ComData.Length  = 2;
ComData.Data[0] = PICC_WRITE;
ComData.Data[1] = addr;

status = RC663_PcdComTransceive(pi);
if (status != MI_NOTAGERR)
{
		if(ComData.Length != 4)
			status=MI_BITCOUNTERR;
		else
		{
			 ComData.Data[0] &= 0x0F;
			 switch (ComData.Data[0])
			 {
					case 0x00:
						 status = MI_NOTAUTHERR;
						 break;
					case 0x0A:
						 status = MI_OK;
						 break;
					default:
						 status = MI_CODEERR;
						 break;
			 }
		}
}    
if (status == MI_OK)
{
		ComData.Command = RC663_Transceive;
		ComData.Length  = 16;
		memcpy(&ComData.Data[0], pWritedata, 16);
		
		status = RC663_PcdComTransceive(pi);
		if (status != MI_NOTAGERR)
		{
				ComData.Data[0] &= 0x0F;
				switch(ComData.Data[0])
				{
					 case 0x00:
							status = MI_WRITEERR;
							break;
					 case 0x0A:
							status = MI_OK;
							break;
					 default:
							status = MI_CODEERR;
							break;
			 }
		}
}
return status;

}

void RC663_MifareClassic(void)
{
s8 status;
u8 i;
u8 M1_Data[7],RD_Data[16]; //CT:2 SN:4 SAK:1
static u8 KEY[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

RC663_PcdConfigISOType('A');
//delay_ms(10);
///mifare S50	
status = RC663_PcdRequestA(PICC_REQALL,M1_Data);

#ifdef UART_PRINT
printf(“ATQA: %d_”,status);
if(status==MI_OK)
printf(" %02X %02X",M1_Data[1],M1_Data[0]);
printf(“\n”);
#endif
if(status!=MI_OK) return;

status = RC663_PcdAnticoll(&M1_Data[2]);

#ifdef UART_PRINT
printf(“UID: %d_”,status);
if(status==MI_OK)
printf(“%02X %02X %02X %02X”,M1_Data[2],M1_Data[3],M1_Data[4],M1_Data[5]);
printf(“\n”);
#endif
if(status!=MI_OK) return;

status = RC663_PcdSelect(&M1_Data[2],&M1_Data[6]);

#ifdef UART_PRINT
printf(“SELECT: %d_”,status);
if(status==MI_OK)
printf(“%02X”,M1_Data[6]);
printf(“\n”);
#endif
if(status!=MI_OK) return;

status = RC663_CMD_LoadKey(KEY);

#ifdef UART_PRINT
printf(“LoadKey: %d\n”,status);
#endif
if(status!=MI_OK) return;
status = RC663_CMD_MfcAuthenticate(0x60,0,&M1_Data[2]);
#ifdef UART_PRINT
printf(“Auth: %d\n”,status);
#endif
if(status!=MI_OK) return;

status=RC663_PcdRead(1,RD_Data);

#ifdef UART_PRINT
printf(“READ:%d_”,status);
for(i=0;i<16;i++)
printf(" %02X",RD_Data[i]);
printf(“\n”);
#endif
if(status!=MI_OK) return;
/RD_Data[15]++;
status=RC663_PcdWrite(1,RD_Data);
#ifdef UART_PRINT
printf(“Write:%d --\n”,status);
#endif
if(status!=MI_OK) return;
status=RC663_PcdRead(1,RD_Data);
#ifdef UART_PRINT
printf(“READ:%d --”,status);
for(i=0;i<16;i++)
printf(" %2X “,RD_Data[i]);
printf(”\n");
//printf(“Please remove card!\n”);
#endif
/
//if(status!=MI_OK) return;
do
{
RC663_FieldOff();
delay_ms(10);
RC663_FieldOn();
//status = RC663_PcdHaltA();
LED_1;
delay_ms(10);
status = RC663_PcdRequestA(PICC_REQALL,M1_Data);
if(statusMI_OK)
{
LED_0;
}
else
break;
}while(status
MI_OK);
}


代码解释

首先先需要配置SPI的基本通讯,基本通讯参考STM32/GD32常规通讯即可
需要配置GPIO
1管脚
2SPI接口
3模式0或者模式3
可以配置外部触发,不过我没有配置,不影响通讯

void RC663_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef  SPI_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	u8 temp;

	GPIO_InitStructure.GPIO_Pin = PDOWN;	 					//PA8
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	PDOWN_1;
	
	GPIO_InitStructure.GPIO_Pin = RC663_IRQ;  					//PB11	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* Enable AFIO clock */	
	/* Connect EXTI9 Line to PC.9 pin */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);	 //IRQ
	/* Configure EXTI6 line */
	EXTI_InitStructure.EXTI_Line = EXTI_Line11; // pb11
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  	//falling edge of IRQ result interrupt
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	
	
	//IFSEL0,IFSEL1:0 1
	//RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );
	GPIO_InitStructure.GPIO_Pin = RC663_NSS;	 			
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOB, &GPIO_InitStructure);					 
	RC663_NSS_1;			             
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;//SPI_BaudRatePrescaler_64;	
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	
	SPI_InitStructure.SPI_CRCPolynomial = 7;	
	SPI_Init(SPI2, &SPI_InitStructure);  
	SPI_Cmd(SPI2, ENABLE); 

	PDOWN_0;	//	->RESET
	delay_ms(30);
	temp = RC663_ReadReg(rRegVersion);
#ifdef UART_PRINT
	printf("version: %X\n",temp);
#endif
}

然后就是配置SPI发送和接收函数

u8 RC663_SPIWriteByte(u8 Byte)
{
	while((SPI2->SR&0X02)==0);		 
	SPI2->DR=Byte;	 	            
	while((SPI2->SR&0X01)==0);     
	return SPI2->DR;        	  
}

然后配置写寄存器和读寄存器,包括寄存器位设置

void RC663_WriteReg(u8   Address, u8   value)
{  
	RC663_NSS_0;
	RC663_SPIWriteByte(Address<<1);
	RC663_SPIWriteByte(value);
	RC663_NSS_1;
	delay_ns(10);
}

u8 RC663_ReadReg(u8   Address)
{
	u8  ucResult=0;
	RC663_NSS_0;
	RC663_SPIWriteByte((Address<<1)|0x01);
	ucResult = RC663_SPIWriteByte(0);
	RC663_NSS_1;
	delay_ns(10);
	return ucResult;
}

void RC663_SetBitMask(u8   reg,u8   mask)  
{
    u8  tmp = RC663_ReadReg(reg);
    RC663_WriteReg(reg,tmp | mask);  
}

void RC663_ClearBitMask(u8   reg,u8   mask)  
{
    u8  tmp = RC663_ReadReg(reg);
    RC663_WriteReg(reg, tmp & ~mask);  
}

void RC663_SetRawRC(u8   reg,u8 mask,u8 set)
{
	u8 temp = RC663_ReadReg(reg);
	temp = (temp&mask)|set;
	RC663_WriteReg(reg,temp);
}

然后就是配置CLRC663的SPI寄存器初始化

请注意,由于13.56mhz通讯协议包括ISO14443A
ISO14443B 或者ISO15693 ,这几种的配置如下

s8 RC663_PcdConfigISOType(u8 type)
{
//	u8 temp;
	RC663_WriteReg(rRegT0Control,0x98); //Starts at the end of Tx. Stops after Rx of first data. Auto-reloaded. 13.56 MHz input clock.
	RC663_WriteReg(rRegT1Control,0x92); //Starts at the end of Tx. Stops after Rx of first data. Input clock - cascaded with Timer-0.
	RC663_WriteReg(rRegT2Control,0x20); //Timer used for LFO trimming
	RC663_WriteReg(rRegT2ReloadHi,0x03);	//
	RC663_WriteReg(rRegT2ReloadLo,0xFF);	//
	RC663_WriteReg(rRegT3Control,0x00);	//Not started automatically. Not reloaded. Input clock 13.56 MHz	
	if(type=='A')
	{
		RC663_WriteReg(rRegWaterLevel,0x10);	//Set WaterLevel =(FIFO length -1)
										 
		RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
		RC663_WriteReg(rRegDrvMod,0x80);	//Tx2Inv=1
		RC663_WriteReg(rRegTxAmp,0xC0);	// 0x00
		RC663_WriteReg(rRegDrvCon,0x09);	//01
		RC663_WriteReg(rRegTxl,0x05);	//
		RC663_WriteReg(rRegRxSofD,0x00);	//
		
		RC663_CMD_LoadProtocol(0,0);

		// Disable Irq 0,1 sources
		RC663_WriteReg(rRegIRQ0En,0);
		RC663_WriteReg(rRegIRQ1En,0);
		
		RC663_WriteReg(rRegFIFOControl,0xB0);

		RC663_WriteReg(rRegTxModWidth,0x20); // Length of the pulse modulation in carrier clks+1  
		RC663_WriteReg(rRegTxSym10BurstLen,0); // Symbol 1 and 0 burst lengths = 8 bits.
		RC663_WriteReg(rRegFrameCon,0xCF); // Start symbol=Symbol2, Stop symbol=Symbol3
		
		RC663_WriteReg(rRegRxCtrl,0x04); // Set Rx Baudrate 106 kBaud 
		RC663_WriteReg(rRegRxThreshold,0x55); // Set min-levels for Rx and phase shift  //32 
		RC663_WriteReg(rRegRcv,0x12);	//
		RC663_WriteReg(rRegRxAna,0x0A); //0
		
		RC663_WriteReg(rRegDrvMod,0x81);
		//> MIFARE Crypto1 state is further disabled.
		RC663_WriteReg(rRegStatus,0);
		//>  FieldOn
		RC663_WriteReg(rRegDrvMod,0x89);
	}
	else if(type=='B')
	{
		RC663_WriteReg(rRegWaterLevel,0x10);	//Set WaterLevel =(FIFO length -1)
										 
		RC663_WriteReg(rRegRxBitCtrl,0x80);	//Received bit after collision are replaced with 1.
		RC663_WriteReg(rRegDrvMod,0x8F);	//Tx2Inv=1
		RC663_WriteReg(rRegTxAmp,0x0C);	// 0xCC	
		RC663_WriteReg(rRegDrvCon,0x01);	
		RC663_WriteReg(rRegTxl,0x05);	
		RC663_WriteReg(rRegRxSofD,0x00);	
		
		RC663_CMD_LoadProtocol(4,4);

		// Disable Irq 0,1 sources
		RC663_WriteReg(rRegIRQ0En,0);
		RC663_WriteReg(rRegIRQ1En,0);
		
		RC663_WriteReg(rRegFIFOControl,0xB0);

		RC663_WriteReg(rRegTxModWidth,0x0A); // Length of the pulse modulation in carrier clks+1  
		RC663_WriteReg(rRegTxSym10BurstLen,0); // Symbol 1 and 0 burst lengths = 8 bits.
		RC663_WriteReg(rRegTXWaitCtrl,1);	
		RC663_WriteReg(rRegFrameCon,0x05); 
		RC663_WriteReg(rRegRxSofD,0xB2);
		
		RC663_WriteReg(rRegRxCtrl,0x34); // Set Rx Baudrate 106 kBaud 
		RC663_WriteReg(rRegRxThreshold,0x9F); // Set min-levels for Rx and phase shift  0x7F 
		RC663_WriteReg(rRegRcv,0x12);
		RC663_WriteReg(rRegRxAna,0x0a); //0x0a 0X0e
		
		RC663_WriteReg(rRegDrvMod,0x87);
		RC663_WriteReg(rRegStatus,0);
		//>  FieldOn
		RC663_WriteReg(rRegDrvMod,0x8F);
	}

然后就可以编写CLRC663轮询函数了
轮询思路
控制寄存器,使能芯片,天线工作识别芯片返回数据
检查返回数据是否正常

NXP公司NFC读卡器IC CLRC663 设计参考原理图,内容包含CLRC663匹配电路。 NFC读卡IC CLRC663概述: 如果您需要最佳NFC性能或最低功耗,可使用这个常高效、高度灵活的前端来进一步推动您的设计。它提供了扩展的温度范围、与CLRC663系列(MFRC630,SLRC610)的引脚到引脚兼容性,以及节省时间的软件工具。 NFC读卡IC CLRC663是门禁、支付、游戏和工业等具有高性能要求的NFC应用的完美选择。 NFC读卡IC CLRC663的特性: 高性能和更灵活的天线设计 最大发射机电流:350 mA,工作电流限值为500 mA 免费可编程的6 kB EEPROM 电池使用时间较长 电源电压范围:2.5至5.5 V 省电模式:硬停机、待机、扩展LPCD选项 工业/汽车 温度范围(-40至+105 °C) 多个接口,可支持广泛的微控制器和高安全性读卡器 主机接口:SPI、I2C、UART 高达8个通用IO SAM接口 512字节FIFO缓冲器可降低主机控制器的性能要求 快速开发 支持NFC Cockpit和NFC读卡器库 完整的开发套件 包括许可 包括NXP ISO/IEC14443-A和Innovatron ISO/IEC14443-B知识产权许可权限 EMVCo就绪 符合EMVCo 2.6 L1模拟和数字规范 完全符合射频标准 ISO/IEC 14443A/MIFARE ISO/IEC 14443B JIS X 6319-4 (可与FeliCa1方案相媲美) ISO/IEC 15693 (ICODE® SLIX系列,ICODE® DNA) ISO/IEC 18000-3模式3/ EPC类-1 HF (ICODE® ILT系列) 对等模式:ISO/IEC 18092无源启动器 兼容所有恩智浦智能卡产品 整个MIFARE®系列:Ultralight、Classic 1K & 4K、DESFire EV1 & EV2和Plus EV1 整个NTAG®系列,含NTAG I2C+ 整个SmartMX®系列,含SmartMX2 P40 & P60 紧凑、省时的封装 HVQFN32带有可湿性侧翼,支持高产量
### 回答1: 以下是一个使用stm32驱动clrc663读取标签物理卡号的程序示例: 首先,需要在工程中引入相关的头文件和库文件。例如: #include "stm32f10x.h" #include "clrc663.h" ... 在主函数中,建立主要的驱动逻辑: int main(void) { // 初始化clrc663 CLRC663_Init(); while (1) { // 等待检测到标签 while (!CLRC663_Polling()); // 读取标签物理卡号 uint8_t cardID[4]; CLRC663_ReadCardID(cardID); // 打印卡号 printf("Card ID: %02X %02X %02X %02X\n", cardID[0], cardID[1], cardID[2], cardID[3]); } } 在CLRC663_Init函数中,进行clrc663的初始化设置,包括寄存器的初始化、SPI通信的配置等。可以参考相关的clrc663驱动库文件的文档或示例代码来完成该部分的编写。 在CLRC663_Polling函数中,进行标签的检测,当检测到标签存在时返回true,否则返回false。可以通过读取相关的寄存器状态来实现。 在CLRC663_ReadCardID函数中,通过与标签进行通信,读取标签的物理卡号信息。具体的读取方法请参考clrc663的相关文档或示例代码。 以上是一个简单的驱动clrc663读取标签物理卡号的stm32程序示例,可以根据实际需求进行适当的调整和拓展。 ### 回答2: 驱动CLRC663读取标签物理卡号的STM32程序主要包括以下步骤: 1. 初始化:设置STM32芯片的引脚和SPI总线的参数,以便与CLRC663通信。 2. 寻卡:发送寻卡命令给CLRC663,并等待回应。CLRC663会搜索附近的射频场,检测到标签后会向STM32返回相关信息。 3. 选卡:根据寻卡的回应结果,选择要操作的标签卡。发送选卡命令给CLRC663,使其针对选择的卡进行后续操作。 4. 读取标签卡物理卡号:通过发送读取命令给CLRC663,请求读取标签卡的物理卡号。CLRC663会与标签卡进行通信,并将物理卡号数据返回给STM32。 5. 数据处理:STM32接收到标签卡的物理卡号数据后,可以进行进一步的处理,例如存储到内存中或者发送给其他设备进行处理。 6. 结束操作:完成读取物理卡号后,可以发送结束命令给CLRC663,使其结束当前的操作。 需要注意的是,上述步骤只是程序的基本框架,具体实现过程可能会根据具体芯片型号、通信协议等存在差异。因此,在编写驱动CLRC663读取标签物理卡号的STM32程序之前,需参考芯片CLRC663的相关文档和程序示例,确保正确理解并实现相关功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

超级馒头神

看看谁给我第一个打赏。太感谢您

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

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

打赏作者

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

抵扣说明:

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

余额充值