基本介绍
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)nmsfac_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(statusMI_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轮询函数了
轮询思路
控制寄存器,使能芯片,天线工作识别芯片返回数据
检查返回数据是否正常