#测试环境
Arduino SPI接口
1、程序入口初始化printf打印,调用RFID接口 main.ino
int serial_putc(char c, struct __file*) {
Serial.write(c);
return c;
}
void printf_begin(void) {
fdevopen(&serial_putc, 0);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
printf_begin();
RC663_Init();
}
void loop() {
// put your main code here, to run repeatedly:
uint8_t uid[8];
printf("RC663_Version:");
printf("%2.2x\n", RC663_ReadReg(0x7f));
bt_rfid_query_14443a(uid);
delay(1000);
}
## 2、RFID读UID示例 librc663.ino
> Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本、小容量的卡片。低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片之一;小容量,是指其存储容量只有512bit(Mifare S50有8192bit)。
Mifare Ulitralight的卡序列号有7个字节,而Mifare S50的卡序列号只有4个字节,因此在卡片防冲突选择阶段需要两层(Cascade93H和95H)操作;
```c
#include <stdint.h>
#include "librc663.h"
#define SPI_PIN_NSS (49)
#define SPI_PIN_SCK (48)
#define SPI_PIN_MOSI (47)
#define SPI_PIN_MISO (46)
void RC663_Init(void) {
pinMode(SPI_PIN_NSS, OUTPUT);
pinMode(SPI_PIN_SCK, OUTPUT);
pinMode(SPI_PIN_MOSI, OUTPUT);
pinMode(SPI_PIN_MISO, INPUT);
}
void _delay() {
for (volatile uint32_t i = 0; i < 20; i++)
;
}
void RC663_WriteReg(uint8_t address, uint8_t value) {
uint8_t i;
digitalWrite(SPI_PIN_SCK, LOW);
digitalWrite(SPI_PIN_NSS, LOW);
address = (address << 1) & 0xfe; // 低位为0
for (i = 8; i > 0; i--) {
if (address & 0x80) {
digitalWrite(SPI_PIN_MOSI, HIGH);
} else {
digitalWrite(SPI_PIN_MOSI, LOW);
}
digitalWrite(SPI_PIN_SCK, HIGH);
_delay();
address <<= 1;
digitalWrite(SPI_PIN_SCK, LOW);
_delay();
}
for (i = 8; i > 0; i--) {
if (value & 0x80) {
digitalWrite(SPI_PIN_MOSI, HIGH);
} else {
digitalWrite(SPI_PIN_MOSI, LOW);
}
digitalWrite(SPI_PIN_SCK, HIGH);
_delay();
value <<= 1;
digitalWrite(SPI_PIN_SCK, LOW);
_delay();
}
digitalWrite(SPI_PIN_SCK, HIGH);
digitalWrite(SPI_PIN_NSS, HIGH);
}
uint8_t RC663_ReadReg(uint8_t ucAddr) {
uint8_t i;
uint8_t ucResult = 0;
digitalWrite(SPI_PIN_SCK, LOW);
digitalWrite(SPI_PIN_NSS, LOW);
_delay();
// 读寄存器需要地址转换
ucAddr = (ucAddr << 1) | 0x01; // 读最低位为1
for (i = 8; i > 0; i--) {
if (ucAddr & 0x80) {
digitalWrite(SPI_PIN_MOSI, HIGH);
} else {
digitalWrite(SPI_PIN_MOSI, LOW);
}
digitalWrite(SPI_PIN_SCK, HIGH);
_delay();
ucAddr <<= 1;
digitalWrite(SPI_PIN_SCK, LOW);
_delay();
}
for (i = 8; i > 0; i--) // 接收数据
{
digitalWrite(SPI_PIN_SCK, HIGH);
_delay();
ucResult <<= 1;
if (digitalRead(SPI_PIN_MISO)) {
ucResult |= 1;
}
digitalWrite(SPI_PIN_SCK, LOW);
_delay();
}
// printf("value:%x \n", ucResult);
digitalWrite(SPI_PIN_SCK, HIGH);
digitalWrite(SPI_PIN_NSS, HIGH);
return ucResult;
}
void RC663_SetBitMask(uint8_t reg, uint8_t mask) {
uint8_t tmp = RC663_ReadReg(reg);
RC663_WriteReg(reg, tmp | mask);
}
void RC663_ClearBitMask(uint8_t reg, uint8_t mask) {
uint8_t tmp = RC663_ReadReg(reg);
RC663_WriteReg(reg, tmp & ~mask);
}
void RC663_SetRawRC(uint8_t reg, uint8_t mask, uint8_t set) {
uint8_t 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(20);
RC663_FieldOn();
delay(20);
}
// extern uint8_t Status_INT;
uint8_t mode;
int8_t RC663_Command_Int(struct TranSciveBuffer *pi) {
uint16_t i;
uint8_t 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);
#if 0
Status_INT = 0;
RC663_WriteReg(rRegCommand, pi->Command);
while (Status_INT == 0)
; // wait for IRQ
Status_INT = 0;
#else
RC663_WriteReg(rRegCommand, pi->Command);
delay(1000);
delay(1000);
delay(1000);
#endif
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);
#if 0
printf("N:%x\n", n);
if (n > 64)
n = 64;
#endif
for (j = 0; j < n; j++)
pi->Data[j % 64] = RC663_ReadReg(rRegFIFOData);
return MI_OK;
}
int8_t RC663_CMD_LoadProtocol(uint8_t rx, uint8_t tx) {
struct TranSciveBuffer ComData;
ComData.Command = RC663_LoadProtocol;
ComData.Length = 2;
ComData.Data[0] = rx;
ComData.Data[1] = tx;
return RC663_Command_Int(&ComData);
}
int8_t RC663_CMD_LoadKey(uint8_t *pkey) {
struct TranSciveBuffer ComData;
ComData.Command = RC663_LoadKey;
ComData.Length = 6;
memcpy(ComData.Data, pkey, 6);
return RC663_Command_Int(&ComData);
}
int8_t RC663_CMD_MfcAuthenticate(uint8_t auth_mode, uint8_t block, uint8_t *pSnr) {
int8_t status;
uint8_t 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;
}
int8_t RC663_PcdConfigISOType(uint8_t type) {
// uint8_t 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
#if 1
RC663_WriteReg(rRegTxAmp, 0xC0); // 0x00
#else
RC663_WriteReg(rRegTxAmp, 0x40); // 0x00
#endif
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
#if 1
RC663_WriteReg(rRegRxThreshold, 0x55); // Set min-levels for Rx and phase shift //32
#else
RC663_WriteReg(rRegRxThreshold, 0x33); // Set min-levels for Rx and phase shift //32
#endif
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;
}
void reset() {
uint32_t volatile i;
// // RSET signal low
// RF_RST_GPIO_L();
// // delay of ~1,2 ms
// for (i = 0x2000; i > 0; i--)
// ;
// delay(10);
// // RSET signal high to reset the RC663 IC
// RF_RST_GPIO_H();
// // // delay of ~1,2 ms
// // for (i = 0x2000; i > 0; i--)
// // ;
// delay(10);
// // RSET signal low
// RF_RST_GPIO_L();
// // delay of ~1,2 ms
// for (i = 0x2000; i > 0; i--)
// ;
}
int8_t RC663_PcdComTransceive(struct TranSciveBuffer *pi) {
int8_t status = MI_ERR;
uint16_t i;
uint8_t reg1, temp, lastBits; // reg0,
uint8_t 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);
#if 1
i = 0;
do {
if (i++ > 0x800)
return MI_ERR; // 超时
reg1 = RC663_ReadReg(rRegIRQ1); // 07h //wait for TxIRQ
} while ((reg1 & 0x40) == 0); // GlobalIRQ
#else
do {
reg1 = RC663_ReadReg(rRegIRQ0); // 07h //wait for TxIRQ
if (reg1 & 0x8)
break; // TxIRQ
reg1 = RC663_ReadReg(rRegIRQ1); // 07h //wait for TxIRQ
if (reg1 & 0x2)
break; // Timer1IRQEn
} while (1); //(reg1 & 0x40) == 0); // GlobalIRQ
#endif
RC663_WriteReg(rRegIRQ0En, 0x54); // HiAlertIRQEN,IdleIRQEn,RxIRQEn
RC663_WriteReg(rRegIRQ1En, 0x42); // Global IRQ,Timer1IRQEn
for (i = 8000; i > 0; i--) {
#if 1
reg1 = RC663_ReadReg(rRegIRQ1); // 07h //wait for RxIRQ
if (reg1 & 0x40)
break; // GlobalIRQ
#else
reg1 = RC663_ReadReg(rRegIRQ0); // 07h //wait for RxIRQ
if (reg1 & 0x04)
break; // RxIRQEn
reg1 = RC663_ReadReg(rRegIRQ1); // 07h //wait for RxIRQ
if (reg1 & 0x02)
break; // Timer1IRQEn
#endif
}
RC663_WriteReg(rRegIRQ0En, 0);
RC663_WriteReg(rRegIRQ1En, 0);
errReg = RC663_ReadReg(rRegError);
// printf("errReg %x\n", errReg);
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;
}
int8_t RC663_PcdHaltA(void) {
int8_t 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;
}
int8_t RC663_PcdRequestA(uint8_t req_code, uint8_t *pTagType) {
int8_t 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;
status = RC663_PcdComTransceive(pi);
if (status == MI_OK) {
// printf("ComData.Length:%d\n", ComData.Length);
if (ComData.Length == 0x10) {
*pTagType = ComData.Data[0];
*(pTagType + 1) = ComData.Data[1];
} else
status = MI_VALERR;
}
// RC663_WriteReg(rRegTxDataNum,0x08);
return status;
}
int8_t RC663_PcdAnticoll(uint8_t *pSnr) {
/*
| ATQA | Type |
| :----: | :----------------- |
| 0x4400 | Mifare_UltraLight |
| 0x0400 | Mifare_One(M1 S50) |
| 0x0200 | Mifare_One(M1 S70) |
| 0x0800 | Mifare_Pro(X) |
| 0x4403 | Mifare_DESFire |
Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本、小容量的卡片。低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片之一;小容量,是指其存储容量只有512bit(Mifare S50有8192bit)。
Mifare Ulitralight的卡序列号有7个字节,而Mifare S50的卡序列号只有4个字节,因此在卡片防冲突选择阶段需要两层(Cascade93H和95H)操作;
*/
int8_t status;
uint8_t i;
uint8_t ucBits, ucBytes;
uint8_t snr_check = 0;
uint8_t ucCollPosition = 0;
uint8_t ucTemp;
uint8_t ucSNR[5] = { 0, 0, 0, 0, 0 };
struct TranSciveBuffer ComData, *pi = &ComData;
uint16_t t = 0;
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;
}
if (t++ > 0x8000) // 超时
{
return MI_ERR;
}
} 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;
}
int8_t RC663_PcdAnticoll2(uint8_t *pSnr) {
/*
| ATQA | Type |
| :----: | :----------------- |
| 0x4400 | Mifare_UltraLight |
| 0x0400 | Mifare_One(M1 S50) |
| 0x0200 | Mifare_One(M1 S70) |
| 0x0800 | Mifare_Pro(X) |
| 0x4403 | Mifare_DESFire |
Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本、小容量的卡片。低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片之一;小容量,是指其存储容量只有512bit(Mifare S50有8192bit)。
Mifare Ulitralight的卡序列号有7个字节,而Mifare S50的卡序列号只有4个字节,因此在卡片防冲突选择阶段需要两层(Cascade93H和95H)操作;
*/
int8_t status;
uint8_t i;
uint8_t ucBits, ucBytes;
uint8_t snr_check = 0;
uint8_t ucCollPosition = 0;
uint8_t ucTemp;
uint8_t ucSNR[5] = { 0, 0, 0, 0, 0 };
struct TranSciveBuffer ComData, *pi = &ComData;
uint16_t t = 0;
RC663_WriteReg(rRegTxDataNum, 0x08);
#if 1 // 必须有,否则读不到UID
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
#endif
ComData.Command = RC663_Transceive;
ComData.Data[0] = PICC_ANTICOLL2;
ComData.Data[1] = 0x20;
ComData.Length = 2;
status = RC663_PcdComTransceive(pi);
// printf("RC663_PcdAnticoll2-RC663_PcdComTransceive :%d \n", status);
// for (i = 0; i < ComData.Length / 8; i++)
// printf("%2.2X ", ComData.Data[i]);
// printf("\n");
if (status == MI_OK) {
for (i = 0; i < 4; i++) {
*(pSnr + i) = ComData.Data[i];
snr_check ^= pSnr[i];
}
// printf("snr_check:%2.2X =? %2.2X\n",snr_check,ComData.Data[i]);
if (snr_check != ComData.Data[i])
status = MI_COM_ERR;
}
// printf("RC663_PcdAnticoll2 :%d \n", status);
return status;
}
int8_t RC663_PcdSelect(uint8_t *pSnr, uint8_t *pSize) {
int8_t status;
uint8_t 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);
}
#if 0
ComData.Data[3] = 0xab;
#endif
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;
}
// int8_t RC663_PcdSelect2(uint8_t *pSnr, uint8_t *pSize) {
// int8_t status;
// uint8_t 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_ANTICOLL2;
// 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;
// }
#define RFID_DEBUG
uint8_t bt_rfid_query_14443a(uint8_t *uid) {
int8_t status;
uint8_t reg;
uint8_t dSize;
uint8_t M1_Data[12]; // CT:2 SN:4 SAK:1
static uint8_t KEY[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
#if 0
/*
VERSION Reg:
bit7~4
CLRC66301: 0x1
CLRC66302: 0x1
CLRC66303: 0x1
bit3~0
CLRC66301: 0x8
CLRC66302: 0x8
CLRC66303: 0xA
*/
reg = RC663_ReadReg(rRegVersion);
// 版本寄存器读错误 重启
if ((reg != 0x1A) && (reg != 0x18)) {
#ifdef RFID_DEBUG
printf("rfid reset...\n");
#endif
reset();
delay(100);
}
#endif
#ifdef RFID_DEBUG
printf("RC663_PcdConfigISOType...\n");
#endif
RC663_PcdConfigISOType('A');
///mifare S50
/*
| ATQA | Type |
| :----: | :----------------- |
| 0x4400 | Mifare_UltraLight |
| 0x0400 | Mifare_One(M1 S50) |
| 0x0200 | Mifare_One(M1 S70) |
| 0x0800 | Mifare_Pro(X) |
| 0x4403 | Mifare_DESFire |
Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本、小容量的卡片。低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片之一;小容量,是指其存储容量只有512bit(Mifare S50有8192bit)。
Mifare Ulitralight的卡序列号有7个字节,而Mifare S50的卡序列号只有4个字节,因此在卡片防冲突选择阶段需要两层(Cascade93H和95H)操作;
*/
uint8_t i;
status = RC663_PcdRequestA(PICC_REQALL, M1_Data);
#ifdef RFID_DEBUG
printf("ATQA: %d_", status);
if (status == MI_OK)
printf("CardTyep:%02X %02X", M1_Data[1], M1_Data[0]);
printf("\n");
#endif
if (status != MI_OK) {
// 关闭场
RC663_FieldOff();
return 1;
}
if (M1_Data[0] == 0x44 && M1_Data[1] == 0x00) {
status = RC663_PcdAnticoll(&M1_Data[2]);
if (status != MI_OK) {
// 关闭场
RC663_FieldOff();
return 1;
}
printf("UID-1: %02X %02X %02X ", M1_Data[3], M1_Data[4], M1_Data[5]);
status = RC663_PcdSelect(&M1_Data[2], &dSize);
printf("Selete1_Status: %d_\n", status);
if (status != MI_OK) {
// 关闭场
RC663_FieldOff();
return 1;
}
status = RC663_PcdAnticoll2(&M1_Data[6]);
// printf("Anticoll-2: %d_\n", status);
// printf("UID-2:%02X %02X %02X %02X\n", M1_Data[6], M1_Data[7], M1_Data[8], M1_Data[9]);
printf("Mifare Ultralight UID:");
for (i = 0; i < 7; i++)
printf("%2.2X ", M1_Data[3 + i]);
printf("\n");
if (status != MI_OK) {
// 关闭场
RC663_FieldOff();
return 1;
}
} else {
status = RC663_PcdAnticoll(&M1_Data[2]);
printf("Anticoll-1: %d_\n", status);
if (status != MI_OK) {
// 关闭场
RC663_FieldOff();
return 1;
}
#ifdef RFID_DEBUG
printf("Mifare Classic 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) {
memcpy(uid, &M1_Data[2], 8);
} else {
memset(&uid, 0, 8);
}
// 关闭场
RC663_FieldOff();
return status;
}
## 3、寄存器定义 librc663.ino
```c
#ifndef _LIBRC663_H
#define _LIBRC663_H
#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
//M1,ISO14443A
/
#define PICC_REQIDL 0x26 //Ѱ��������δ��������״̬
#define PICC_REQALL 0x52 //Ѱ��������ȫ����
#define PICC_ANTICOLL1 0x93 //����ײ
#define PICC_ANTICOLL2 0x95 //����ײ
#define PICC_AUTHENT1A 0x60 //��֤A��Կ
#define PICC_AUTHENT1B 0x61 //��֤B��Կ
#define PICC_READ 0x30 //����
#define PICC_WRITE 0xA0 //�
#define PICC_DECREMENT 0xC0 //�ۿ�
#define PICC_INCREMENT 0xC1 //��ֵ
#define PICC_RESTORE 0xC2 //�������ݵ�������
#define PICC_TRANSFER 0xB0 //���滺����������
#define PICC_HALT 0x50 //����
/ISO14443B
#define PICC_ANTI 0x05
#define PICC_ATTRIB 0x1D
/
#define MI_OK 0
#define MI_CHK_OK 0
#define MI_NOTAGERR (-1)
#define MI_CHK_FAILED (-1)
#define MI_CRCERR (-2)
#define MI_CHK_COMPERR (-2)
#define MI_EMPTY (-3)
#define MI_AUTHERR (-4)
#define MI_PARITYERR (-5)
#define MI_CODEERR (-6)
#define MI_SERNRERR (-8)
#define MI_KEYERR (-9)
#define MI_NOTAUTHERR (-10)
#define MI_BITCOUNTERR (-11)
#define MI_BYTECOUNTERR (-12)
#define MI_IDLE (-13)
#define MI_TRANSERR (-14)
#define MI_WRITEERR (-15)
#define MI_INCRERR (-16)
#define MI_DECRERR (-17)
#define MI_READERR (-18)
#define MI_OVFLERR (-19)
#define MI_POLLING (-20)
#define MI_FRAMINGERR (-21)
#define MI_ACCESSERR (-22)
#define MI_UNKNOWN_COMMAND (-23)
#define MI_COLLERR (-24)
#define MI_RESETERR (-25)
#define MI_INITERR (-25)
#define MI_INTERFACEERR (-26)
#define MI_ACCESSTIMEOUT (-27)
#define MI_NOBITWISEANTICOLL (-28)
#define MI_QUIT (-30)
#define MI_RECBUF_OVERFLOW (-50)
#define MI_SENDBYTENR (-51)
#define MI_SENDBUF_OVERFLOW (-53)
#define MI_BAUDRATE_NOT_SUPPORTED (-54)
#define MI_SAME_BAUDRATE_REQUIRED (-55)
#define MI_WRONG_PARAMETER_VALUE (-60)
#define MI_BREAK (-99)
#define MI_NY_IMPLEMENTED (-100)
#define MI_NO_MFRC (-101)
#define MI_MFRC_NOTAUTH (-102)
#define MI_WRONG_DES_MODE (-103)
#define MI_HOST_AUTH_FAILED (-104)
#define MI_WRONG_LOAD_MODE (-106)
#define MI_WRONG_DESKEY (-107)
#define MI_MKLOAD_FAILED (-108)
#define MI_FIFOERR (-109)
#define MI_WRONG_ADDR (-110)
#define MI_DESKEYLOAD_FAILED (-111)
#define MI_WRONG_SEL_CNT (-114)
#define MI_WRONG_TEST_MODE (-117)
#define MI_TEST_FAILED (-118)
#define MI_TOC_ERROR (-119)
#define MI_COMM_ABORT (-120)
#define MI_INVALID_BASE (-121)
#define MI_MFRC_RESET (-122)
#define MI_WRONG_VALUE (-123)
#define MI_VALERR (-124)
#define MI_COM_ERR (-125)
#define MI_ERR (-126)
#define DEF_FIFO_LENGTH 64 //FIFO size=64byte
struct TranSciveBuffer {
uint8_t Command;
uint16_t Length;
uint8_t Data[DEF_FIFO_LENGTH];
};
#endif