简介:STM32F103C8T6驱动RC522-RFID模块源码介绍。
开发平台:KEIL ARM
MCU型号:STM32F103C8T6
传感器型号:RC522-RFID
特别提示:驱动内可能使用了某些其他组件,比如delay等,在文末外设模板下载地址内有。
1积分源码下载地址在文末!!!
接口图:
使用举例:
#include <stdio.h>
#include "SPI.h"
#include "RC522.h"
int main()
{
uint8_t cardID[4] = {0};
SPIClass.SPI1_Init(); // SPI初始化
MFRC522_Init(); // RC522初始化
while(1) {
if(!RC522_cardScan(cardID)) {
printf("card scan success, id:0x%02X%02X%02X%02X\n", cardID[0], cardID[1], cardID[2], cardID[3]);
} else {
printf("card scan failure\n");
}
}
}
驱动源码:
SPI.c
#include "main.h"
static void SPI1_Init(void);
static void SPI2_Init(void);
static uint8_t SPI_WriteRead(SPI_TypeDef* SPIx, uint8_t data, uint32_t timeout);
static void SPI_CS_WritePin(SPI_TypeDef* SPIx, BitAction bitVal);
SPIClassStruct SPIClass = {
.SPI1_Init = SPI1_Init,
.SPI2_Init = SPI2_Init,
.WriteRead = SPI_WriteRead,
.WriteCSPin = SPI_CS_WritePin
};
// SPI1 CS
#define SPI1_CS_GPIO_PORT GPIOB
#define SPI1_CS_GPIO_CLK RCC_APB2Periph_GPIOB
#define SPI1_CS_GPIO_PIN GPIO_Pin_0
// SPI2 CS
#define SPI2_CS_GPIO_PORT GPIOA
#define SPI2_CS_GPIO_CLK RCC_APB2Periph_GPIOA
#define SPI2_CS_GPIO_PIN GPIO_Pin_0
/**
* @brief SPI1初始化
* @param None
* @retval None
*/
static void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// SPI1 SCK-PA5 MOSI-PA7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// SPI1 MISO-PA6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// software CS user write
RCC_APB2PeriphClockCmd(SPI1_CS_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = SPI1_CS_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SPI1_CS_GPIO_PORT, &GPIO_InitStructure);
GPIO_WriteBit(SPI1_CS_GPIO_PORT, SPI1_CS_GPIO_PIN, Bit_SET); // 拉高片选引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1时钟使能
SPI_Cmd(SPI1, DISABLE);
SPI_I2S_DeInit(SPI1);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // SPI设置为双线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 设置SPI为主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // SPI时钟空闲时为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 第一个时钟沿开始采样数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // CS信号由软件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // SPI波特率预分频值 72M / Prescaler
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); // 根据SPI_InitStruct中指定的参数初始化外设SPI寄存器
SPI_Cmd(SPI1, ENABLE); // 使能SPI
}
/**
* @brief SPI2初始化
* @param None
* @retval None
*/
static void SPI2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// SPI1 SCK-PB13 MOSI-PB15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// SPI1 MISO-PB14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// software CS user write
RCC_APB2PeriphClockCmd(SPI2_CS_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = SPI2_CS_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SPI2_CS_GPIO_PORT, &GPIO_InitStructure);
GPIO_WriteBit(SPI2_CS_GPIO_PORT, SPI2_CS_GPIO_PIN, Bit_SET); // 拉高片选引脚
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // SPI2时钟使能
SPI_Cmd(SPI2, DISABLE);
SPI_I2S_DeInit(SPI2);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // SPI设置为双线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 设置SPI为主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // SPI时钟空闲时为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 第一个时钟沿开始采样数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // CS信号由软件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // SPI波特率预分频值 36M / Prescaler
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); // 根据SPI_InitStruct中指定的参数初始化外设SPI寄存器
SPI_Cmd(SPI2, ENABLE); // 使能SPI
}
/**
* @brief SPI读写函数
* @param None
* @retval 0-超时
*/
static uint8_t SPI_WriteRead(SPI_TypeDef* SPIx, uint8_t data, uint32_t timeout)
{
uint32_t retry = 0;
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET) // 发送缓存标志位为空
{
retry++;
if(retry > timeout) return 0;
}
SPI_I2S_SendData(SPIx, data); // 通过外设SPI2发送一个数据
retry = 0;
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET) // 接收缓存标志位不为空
{
retry++;
if(retry > timeout) return 0;
}
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPIx); // 通过SPI2返回接收数据
}
/**
* @brief SPI读写函数
* @param None
* @retval 0-成功
*/
static void SPI_CS_WritePin(SPI_TypeDef* SPIx, BitAction bitVal)
{
if(SPIx == SPI1) {
GPIO_WriteBit(SPI1_CS_GPIO_PORT, SPI1_CS_GPIO_PIN, bitVal);
} else if(SPIx == SPI2) {
GPIO_WriteBit(SPI2_CS_GPIO_PORT, SPI2_CS_GPIO_PIN, bitVal);
}
}
SPI.h
#ifndef __SPI_AS_H
#define __SPI_AS_H
#include "main.h"
typedef struct {
void (* SPI1_Init)(void);
void (* SPI2_Init)(void);
uint8_t (* WriteRead)(SPI_TypeDef *, uint8_t, uint32_t);
void (* WriteCSPin)(SPI_TypeDef *, BitAction);
} SPIClassStruct;
extern SPIClassStruct SPIClass;
#endif
RC522.c
// Mifare RC522 RFID Card reader 13.56 MHz
// MFRC522 STM32F103 DESCRIPTION
// CS (SDA) PB0 SPI1_NSS Chip select for SPI
// SCK PA5 SPI1_SCK Serial Clock for SPI
// MOSI PA7 SPI1_MOSI Master In Slave Out for SPI
// MISO PA6 SPI1_MISO Master Out Slave In for SPI
// IRQ - Irq
// GND GND Ground
// RST 3.3V Reset pin (3.3V)
// VCC 3.3V 3.3V power
#include "RC522.h"
/******template******/
// 0-255数字转换为字符 0xFF--"FF"
void char_to_hex(uint8_t data, uint8_t *retStr) {
uint8_t digits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
if (data < 16) {
retStr[0] = '0';
retStr[1] = digits[data];
} else {
retStr[0] = digits[(data & 0xF0)>>4];
retStr[1] = digits[(data & 0x0F)];
}
}
/**
* @brief 扫描RFID卡
* @param cardID 四字节数组
* @retval 0扫描到RFID卡
*/
uint8_t RC522_cardScan(uint8_t *cardID)
{
if(!MFRC522_Request(PICC_REQIDL, cardID)) {
if(!MFRC522_Anticoll(cardID)) {
#ifdef DEBUG_printf
uint8_t cardIDString[8] = {0};
for(uint8_t i = 0; i < 4; i++) {
char_to_hex(cardID[i], cardIDString+i*2);
}
printf("card id:%s\n", cardIDString);
#endif
return 0;
}
}
return 1;
}
/********************/
void SPI1_WriteReg(uint8_t address, uint8_t value) {
cs_reset();
SPISendByte(address);
SPISendByte(value);
cs_set();
}
uint8_t SPI1_ReadReg(uint8_t address) {
uint8_t val;
cs_reset();
SPISendByte(address);
val = SPISendByte(0x00);
cs_set();
return val;
}
void MFRC522_WriteRegister(uint8_t addr, uint8_t val) {
addr = (addr << 1) & 0x7E; // Address format: 0XXXXXX0
SPI1_WriteReg(addr, val);
}
uint8_t MFRC522_ReadRegister(uint8_t addr) {
uint8_t val;
addr = ((addr << 1) & 0x7E) | 0x80;
val = SPI1_ReadReg(addr);
return val;
}
uint8_t MFRC522_Check(uint8_t* id) {
uint8_t status;
status = MFRC522_Request(PICC_REQIDL, id); // Find cards, return card type
if (status == MI_OK) status = MFRC522_Anticoll(id); // Card detected. Anti-collision, return card serial number 4 bytes
MFRC522_Halt(); // Command card into hibernation
return status;
}
uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID) {
uint8_t i;
for (i = 0; i < 5; i++) {
if (CardID[i] != CompareID[i]) return MI_ERR;
}
return MI_OK;
}
void MFRC522_SetBitMask(uint8_t reg, uint8_t mask) {
MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) | mask);
}
void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask){
MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) & (~mask));
}
uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType) {
uint8_t status;
uint16_t backBits; // The received data bits
MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x07); // TxLastBists = BitFramingReg[2..0]
TagType[0] = reqMode;
status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);
if ((status != MI_OK) || (backBits != 0x10)) status = MI_ERR;
return status;
}
uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen) {
uint8_t status = MI_ERR;
uint8_t irqEn = 0x00;
uint8_t waitIRq = 0x00;
uint8_t lastBits;
uint8_t n;
uint16_t i;
switch (command) {
case PCD_AUTHENT: {
irqEn = 0x12;
waitIRq = 0x10;
break;
}
case PCD_TRANSCEIVE: {
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
}
MFRC522_WriteRegister(MFRC522_REG_COMM_IE_N, irqEn | 0x80);
MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80);
MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80);
MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE);
// Writing data to the FIFO
for (i = 0; i < sendLen; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, sendData[i]);
// Execute the command
MFRC522_WriteRegister(MFRC522_REG_COMMAND, command);
if (command == PCD_TRANSCEIVE) MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=1,transmission of data starts
// Waiting to receive data to complete
i = 2000; // i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms
do {
// CommIrqReg[7..0]
// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
n = MFRC522_ReadRegister(MFRC522_REG_COMM_IRQ);
i--;
} while ((i!=0) && !(n&0x01) && !(n&waitIRq));
MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=0
if (i != 0) {
if (!(MFRC522_ReadRegister(MFRC522_REG_ERROR) & 0x1B)) {
status = MI_OK;
if (n & irqEn & 0x01) status = MI_NOTAGERR;
if (command == PCD_TRANSCEIVE) {
n = MFRC522_ReadRegister(MFRC522_REG_FIFO_LEVEL);
lastBits = MFRC522_ReadRegister(MFRC522_REG_CONTROL) & 0x07;
if (lastBits) *backLen = (n-1)*8+lastBits; else *backLen = n*8;
if (n == 0) n = 1;
if (n > MFRC522_MAX_LEN) n = MFRC522_MAX_LEN;
for (i = 0; i < n; i++) backData[i] = MFRC522_ReadRegister(MFRC522_REG_FIFO_DATA); // Reading the received data in FIFO
}
} else status = MI_ERR;
}
return status;
}
uint8_t MFRC522_Anticoll(uint8_t* serNum) {
uint8_t status;
uint8_t i;
uint8_t serNumCheck = 0;
uint16_t unLen;
MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00); // TxLastBists = BitFramingReg[2..0]
serNum[0] = PICC_ANTICOLL;
serNum[1] = 0x20;
status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
if (status == MI_OK) {
// Check card serial number
for (i = 0; i < 4; i++) serNumCheck ^= serNum[i];
if (serNumCheck != serNum[i]) status = MI_ERR;
}
return status;
}
void MFRC522_CalculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData) {
uint8_t i, n;
MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04); // CRCIrq = 0
MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); // Clear the FIFO pointer
// Write_MFRC522(CommandReg, PCD_IDLE);
// Writing data to the FIFO
for (i = 0; i < len; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, *(pIndata+i));
MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_CALCCRC);
// Wait CRC calculation is complete
i = 0xFF;
do {
n = MFRC522_ReadRegister(MFRC522_REG_DIV_IRQ);
i--;
} while ((i!=0) && !(n&0x04)); // CRCIrq = 1
// Read CRC calculation result
pOutData[0] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_L);
pOutData[1] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_M);
}
uint8_t MFRC522_SelectTag(uint8_t* serNum) {
uint8_t i;
uint8_t status;
uint8_t size;
uint16_t recvBits;
uint8_t buffer[9];
buffer[0] = PICC_SElECTTAG;
buffer[1] = 0x70;
for (i = 0; i < 5; i++) buffer[i+2] = *(serNum+i);
MFRC522_CalculateCRC(buffer, 7, &buffer[7]); //??
status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits);
if ((status == MI_OK) && (recvBits == 0x18)) size = buffer[0]; else size = 0;
return size;
}
uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum) {
uint8_t status;
uint16_t recvBits;
uint8_t i;
uint8_t buff[12];
// Verify the command block address + sector + password + card serial number
buff[0] = authMode;
buff[1] = BlockAddr;
for (i = 0; i < 6; i++) buff[i+2] = *(Sectorkey+i);
for (i=0; i<4; i++) buff[i+8] = *(serNum+i);
status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);
if ((status != MI_OK) || (!(MFRC522_ReadRegister(MFRC522_REG_STATUS2) & 0x08))) status = MI_ERR;
return status;
}
uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData) {
uint8_t status;
uint16_t unLen;
recvData[0] = PICC_READ;
recvData[1] = blockAddr;
MFRC522_CalculateCRC(recvData,2, &recvData[2]);
status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);
if ((status != MI_OK) || (unLen != 0x90)) status = MI_ERR;
return status;
}
uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData) {
uint8_t status;
uint16_t recvBits;
uint8_t i;
uint8_t buff[18];
buff[0] = PICC_WRITE;
buff[1] = blockAddr;
MFRC522_CalculateCRC(buff, 2, &buff[2]);
status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);
if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
if (status == MI_OK) {
// Data to the FIFO write 16Byte
for (i = 0; i < 16; i++) buff[i] = *(writeData+i);
MFRC522_CalculateCRC(buff, 16, &buff[16]);
status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);
if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
}
return status;
}
void MFRC522_Init(void) {
MFRC522_Reset();
MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D);
MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E);
MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30);
MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0);
MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70); // 48dB gain
MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40);
MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D);
MFRC522_AntennaOn(); // Open the antenna
}
void MFRC522_Reset(void) {
MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE);
}
void MFRC522_AntennaOn(void) {
uint8_t temp;
temp = MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL);
if (!(temp & 0x03)) MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03);
}
void MFRC522_AntennaOff(void) {
MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03);
}
void MFRC522_Halt(void) {
uint16_t unLen;
uint8_t buff[4];
buff[0] = PICC_HALT;
buff[1] = 0;
MFRC522_CalculateCRC(buff, 2, &buff[2]);
MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen);
}
RC522.h
#ifndef __RC522_H
#define __RC522_H
#include "main.h"
// RC522 use SPIx define
#define RC522_SPI SPI1
// SPI write read define
#define SPISendByte(data) SPIClass.WriteRead(RC522_SPI, data, 1000)
// SPI CS define
#define cs_reset() SPIClass.WriteCSPin(RC522_SPI, Bit_RESET)
#define cs_set() SPIClass.WriteCSPin(RC522_SPI, Bit_SET)
// Status enumeration, Used with most functions
#define MI_OK 0
#define MI_NOTAGERR 1
#define MI_ERR 2
// MFRC522 Commands
#define PCD_IDLE 0x00 // NO action; Cancel the current command
#define PCD_AUTHENT 0x0E // Authentication Key
#define PCD_RECEIVE 0x08 // Receive Data
#define PCD_TRANSMIT 0x04 // Transmit data
#define PCD_TRANSCEIVE 0x0C // Transmit and receive data,
#define PCD_RESETPHASE 0x0F // Reset
#define PCD_CALCCRC 0x03 // CRC Calculate
// Mifare_One card command word
#define PICC_REQIDL 0x26 // find the antenna area does not enter hibernation
#define PICC_REQALL 0x52 // find all the cards antenna area
#define PICC_ANTICOLL 0x93 // anti-collision
#define PICC_SElECTTAG 0x93 // election card
#define PICC_AUTHENT1A 0x60 // authentication key A
#define PICC_AUTHENT1B 0x61 // authentication key B
#define PICC_READ 0x30 // Read Block
#define PICC_WRITE 0xA0 // write block
#define PICC_DECREMENT 0xC0 // debit
#define PICC_INCREMENT 0xC1 // recharge
#define PICC_RESTORE 0xC2 // transfer block data to the buffer
#define PICC_TRANSFER 0xB0 // save the data in the buffer
#define PICC_HALT 0x50 // Sleep
// MFRC522 Registers
// Page 0: Command and Status
#define MFRC522_REG_RESERVED00 0x00
#define MFRC522_REG_COMMAND 0x01
#define MFRC522_REG_COMM_IE_N 0x02
#define MFRC522_REG_DIV1_EN 0x03
#define MFRC522_REG_COMM_IRQ 0x04
#define MFRC522_REG_DIV_IRQ 0x05
#define MFRC522_REG_ERROR 0x06
#define MFRC522_REG_STATUS1 0x07
#define MFRC522_REG_STATUS2 0x08
#define MFRC522_REG_FIFO_DATA 0x09
#define MFRC522_REG_FIFO_LEVEL 0x0A
#define MFRC522_REG_WATER_LEVEL 0x0B
#define MFRC522_REG_CONTROL 0x0C
#define MFRC522_REG_BIT_FRAMING 0x0D
#define MFRC522_REG_COLL 0x0E
#define MFRC522_REG_RESERVED01 0x0F
// Page 1: Command
#define MFRC522_REG_RESERVED10 0x10
#define MFRC522_REG_MODE 0x11
#define MFRC522_REG_TX_MODE 0x12
#define MFRC522_REG_RX_MODE 0x13
#define MFRC522_REG_TX_CONTROL 0x14
#define MFRC522_REG_TX_AUTO 0x15
#define MFRC522_REG_TX_SELL 0x16
#define MFRC522_REG_RX_SELL 0x17
#define MFRC522_REG_RX_THRESHOLD 0x18
#define MFRC522_REG_DEMOD 0x19
#define MFRC522_REG_RESERVED11 0x1A
#define MFRC522_REG_RESERVED12 0x1B
#define MFRC522_REG_MIFARE 0x1C
#define MFRC522_REG_RESERVED13 0x1D
#define MFRC522_REG_RESERVED14 0x1E
#define MFRC522_REG_SERIALSPEED 0x1F
// Page 2: CFG
#define MFRC522_REG_RESERVED20 0x20
#define MFRC522_REG_CRC_RESULT_M 0x21
#define MFRC522_REG_CRC_RESULT_L 0x22
#define MFRC522_REG_RESERVED21 0x23
#define MFRC522_REG_MOD_WIDTH 0x24
#define MFRC522_REG_RESERVED22 0x25
#define MFRC522_REG_RF_CFG 0x26
#define MFRC522_REG_GS_N 0x27
#define MFRC522_REG_CWGS_PREG 0x28
#define MFRC522_REG__MODGS_PREG 0x29
#define MFRC522_REG_T_MODE 0x2A
#define MFRC522_REG_T_PRESCALER 0x2B
#define MFRC522_REG_T_RELOAD_H 0x2C
#define MFRC522_REG_T_RELOAD_L 0x2D
#define MFRC522_REG_T_COUNTER_VALUE_H 0x2E
#define MFRC522_REG_T_COUNTER_VALUE_L 0x2F
// Page 3:TestRegister
#define MFRC522_REG_RESERVED30 0x30
#define MFRC522_REG_TEST_SEL1 0x31
#define MFRC522_REG_TEST_SEL2 0x32
#define MFRC522_REG_TEST_PIN_EN 0x33
#define MFRC522_REG_TEST_PIN_VALUE 0x34
#define MFRC522_REG_TEST_BUS 0x35
#define MFRC522_REG_AUTO_TEST 0x36
#define MFRC522_REG_VERSION 0x37
#define MFRC522_REG_ANALOG_TEST 0x38
#define MFRC522_REG_TEST_ADC1 0x39
#define MFRC522_REG_TEST_ADC2 0x3A
#define MFRC522_REG_TEST_ADC0 0x3B
#define MFRC522_REG_RESERVED31 0x3C
#define MFRC522_REG_RESERVED32 0x3D
#define MFRC522_REG_RESERVED33 0x3E
#define MFRC522_REG_RESERVED34 0x3F
#define MFRC522_DUMMY 0x00 // Dummy byte
#define MFRC522_MAX_LEN 16 // Buf len byte
// RC522
uint8_t MFRC522_Check(uint8_t* id);
uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID);
void MFRC522_WriteRegister(uint8_t addr, uint8_t val);
uint8_t MFRC522_ReadRegister(uint8_t addr);
void MFRC522_SetBitMask(uint8_t reg, uint8_t mask);
void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask);
uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType);
uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen);
uint8_t MFRC522_Anticoll(uint8_t* serNum);
void MFRC522_CalulateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData);
uint8_t MFRC522_SelectTag(uint8_t* serNum);
uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum);
uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData);
uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData);
void MFRC522_Init(void);
void MFRC522_Reset(void);
void MFRC522_AntennaOn(void);
void MFRC522_AntennaOff(void);
void MFRC522_Halt(void);
// user template
uint8_t RC522_cardScan(uint8_t *cardID);
#endif