一、简介

MF RC522 是应用于 13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员。是 NXP 公司针对“三表”应用推出的一款低电压、低成本、体积小的非接触式读写卡芯片,是智能仪表和便携式手持设备研发的较好选择。

MFRC522数据手册: https://pan.baidu.com/s/10v68Z7sCFFSwPgrZ2eHtXw?pwd=d4fw 提取码:d4fw

二、硬件连接

功能口 引脚
MISO 19
MOSI 23
SCLK 18
CS 5
RST 25

三、添加SPI驱动

查看 ESP32学习笔记(19)——SPI(主机)接口使用

四、工程代码

百度网盘:https://pan.baidu.com/s/1gCtsGrn28ZfV1OinTolJPw?pwd=d3po 提取码:d3po

将文件解压到 esp-idf/examples 目录下:

4.1 board_gpio.c

/********************************************************************** INCLUDES*/
#include "driver/gpio.h"#include "board_gpio.h"/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief NFC复位引脚初始化@param 无@return 无
*/
void NFC_GPIO_Init(void)
{gpio_pad_select_gpio(NFC_RST_GPIO_PIN);                 // 选择一个GPIOgpio_set_direction(NFC_RST_GPIO_PIN, GPIO_MODE_OUTPUT); // 把这个GPIO作为输出NFC_GPIO_Write(NFC_RST_HIGH);
}/**@brief 配置NFC复位引脚工作模式@param mode -[in] 工作模式@return 无
*/
void NFC_GPIO_Write(uint8_t mode)
{gpio_set_level(NFC_RST_GPIO_PIN, mode);
}

4.2 board_gpio.h

#ifndef _BOARD_GPIO_H_
#define _BOARD_GPIO_H_/********************************************************************** INCLUDES*/
#include "driver/gpio.h"/********************************************************************** DEFINITIONS*/
#define NFC_RST_GPIO_PIN                GPIO_NUM_25         // NFC复位
#define NFC_RST_LOW                     0x00
#define NFC_RST_HIGH                    0x01/********************************************************************** API FUNCTIONS*/
void NFC_GPIO_Init(void);
void NFC_GPIO_Write(uint8_t mode);#endif /* _BOARD_GPIO_H_ */

4.3 board_spi.c

/********************************************************************** INCLUDES*/
#include <string.h>
#include "driver/spi_master.h"#include "board_spi.h"/********************************************************************** LOCAL VARIABLES*/
static spi_device_handle_t s_spiHandle;/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief NFC SPI驱动初始化@param 无@return 无
*/
void NFC_SPI_Init(void)
{esp_err_t ret;spi_bus_config_t spiBusConfig ={.miso_io_num = NFC_SPI_MISO_PIN,                    // MISO信号线.mosi_io_num = NFC_SPI_MOSI_PIN,                    // MOSI信号线.sclk_io_num = NFC_SPI_SCLK_PIN,                    // SCLK信号线.quadwp_io_num = -1,                                // WP信号线,专用于QSPI的D2.quadhd_io_num = -1,                                // HD信号线,专用于QSPI的D3.max_transfer_sz = 64 * 8,                          // 最大传输数据大小};spi_device_interface_config_t spiDeviceConfig ={.clock_speed_hz = SPI_MASTER_FREQ_10M,              // Clock out at 10 MHz,.mode = 0,                                          // SPI mode 0/** The timing requirements to read the busy signal from the EEPROM cannot be easily emulated* by SPI transactions. We need to control CS pin by SW to check the busy signal manually.*/.spics_io_num = -1,.queue_size = 7,                                    // 传输队列大小,决定了等待传输数据的数量};//Initialize the SPI busret = spi_bus_initialize(SPI3_HOST, &spiBusConfig, DMA_CHAN);ESP_ERROR_CHECK(ret);ret = spi_bus_add_device(SPI3_HOST, &spiDeviceConfig, &s_spiHandle);ESP_ERROR_CHECK(ret);// 配置CS引脚gpio_pad_select_gpio(NFC_SPI_CS_PIN);                   // 选择一个GPIOgpio_set_direction(NFC_SPI_CS_PIN, GPIO_MODE_OUTPUT);   // 把这个GPIO作为输出
}/**@brief NFC SPI写入数据@param pData -[in] 写入数据@param dataLen -[in] 写入数据长度@return 无
*/
void NFC_SPI_Write(uint8_t *pData, uint32_t dataLen)
{esp_err_t ret;spi_transaction_t t;if(0 == dataLen)                                        // no need to send anything{return;}memset(&t, 0, sizeof(t));                               // Zero out the transactiont.length = dataLen * 8;                                 // Len is in bytes, transaction length is in bits.t.tx_buffer = pData;                                    // Dataret = spi_device_polling_transmit(s_spiHandle, &t);     // Transmit!assert(ret == ESP_OK);                                  // Should have had no issues.
}/**@brief NFC SPI读取数据@param pData -[out] 读取数据@param dataLen -[in] 读取数据长度@return 无
*/
void NFC_SPI_Read(uint8_t *pData, uint32_t dataLen)
{spi_transaction_t t;if(0 == dataLen)                                        // no need to receivce anything{return;}memset(&t, 0, sizeof(t));                               // Zero out the transactiont.length = dataLen * 8;                                 // Len is in bytes, transaction length is in bits.t.rx_buffer = pData;esp_err_t ret = spi_device_polling_transmit(s_spiHandle, &t);assert(ret == ESP_OK);
}/****************************************************END OF FILE****************************************************/

4.4 board_spi.h

#ifndef _BOARD_SPI_H_
#define _BOARD_SPI_H_/********************************************************************** INCLUDES*/
#include "driver/gpio.h"/********************************************************************** DEFINITIONS*/
#define NFC_SPI_MISO_PIN        GPIO_NUM_19
#define NFC_SPI_MOSI_PIN        GPIO_NUM_23
#define NFC_SPI_SCLK_PIN        GPIO_NUM_18
#define NFC_SPI_CS_PIN          GPIO_NUM_5#define DMA_CHAN                2#define SPI_CS_LOW              gpio_set_level(NFC_SPI_CS_PIN, 0)
#define SPI_CS_HIGH             gpio_set_level(NFC_SPI_CS_PIN, 1)/********************************************************************** API FUNCTIONS*/
void NFC_SPI_Init(void);
void NFC_SPI_Write(uint8_t *pData, uint32_t dataLen);
void NFC_SPI_Read(uint8_t *pData, uint32_t dataLen);#endif /* _BOARD_SPI_H_ */

4.5 board_mfrc522.c

/********************************************************************** INCLUDES*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"#include "board_gpio.h"
#include "board_spi.h"
#include "board_mfrc522.h"static char pcdRequest(uint8_t reqCode, uint8_t *pTagType);
static char pcdAnticoll(uint8_t *pSnr);
static char pcdSelect(uint8_t *pSnr);
static char pcdAuthState(uint8_t authMode, uint8_t addr, uint8_t *pKey, uint8_t *pSnr);
static char pcdRead(uint8_t addr, uint8_t *pData);
static char pcdWrite(uint8_t addr, uint8_t *pData);
static void pcdReset(void);
static void calulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData);
static char pcdComMF522(uint8_t command, uint8_t *pInData, uint8_t inLenByte, uint8_t *pOutData, uint32_t *pOutLenBit);
static void pcdAntennaOn(void);
static void pcdAntennaOff(void);
static void setBitMask(uint8_t reg, uint8_t mask);
static void clearBitMask(uint8_t reg, uint8_t mask);
static uint8_t readRawRc(uint8_t addr);
static void writeRawRc(uint8_t addr, uint8_t writeData);
static void delayMs(uint8_t time);/********************************************************************** LOCAL VARIABLES*/
static uint8_t s_cardType[2];                                                   // 卡类型
static uint8_t s_cardSerialNo[4];                                               // 卡序列号
static uint8_t s_defaultKeyA[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};         // 默认密码Astatic const char *TAG = "MFRC522";/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief MFRC522的初始化函数@param 无@return 无
*/
void MFRC522_Init(void)
{pcdReset();                                 // 复位delayMs(5);ESP_LOGI(TAG, "reg: %02x" ,readRawRc(Status1Reg));ESP_LOGI(TAG, "reg: %02x" ,readRawRc(Status2Reg));ESP_LOGI(TAG, "reg: %02x" ,readRawRc(WaterLevelReg));pcdAntennaOn();                             // 开启天线发射
}/**@brief MFRC522读取卡片块数据@param addr -[in] 块地址@return 状态值,0 - 成功;2 - 无卡;3 - 防冲撞失败;4 - 选卡失败;5 - 密码错误
*/
uint8_t MFRC522_ReadCardDataBlock(uint8_t addr)
{memset(s_cardSerialNo, 0, 4);if(pcdRequest(PICC_REQALL, s_cardType) == MI_OK){}else{ESP_LOGI(TAG, "ERR: 2");return 2;                               // 无卡}if(pcdAnticoll(s_cardSerialNo) == MI_OK){}else{ESP_LOGI(TAG, "ERR: 3");return 3;                               // 防冲撞失败}if(pcdSelect(s_cardSerialNo) == MI_OK){}else{ESP_LOGI(TAG, "ERR: 4");return 4;                               // 选卡失败}if(pcdAuthState(0x60, addr, s_defaultKeyA, s_cardSerialNo) == MI_OK){ESP_LOGI(TAG, "ERR: 0");return 0;}else{ESP_LOGI(TAG, "ERR: 5");return 5;                               // 密码错误}
}/**@brief 读取卡片序列号@param pCardSerialNo -[out] 卡片序列号@return 0 - 读卡成功;2 - 无卡
*/
uint8_t MFRC522_ReadCardSerialNo(uint8_t *pCardSerialNo)
{uint8_t status = MFRC522_ReadCardDataBlock(4);            memcpy(pCardSerialNo, s_cardSerialNo, 4);return status;
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief 寻卡@param reqCode -[in] 寻卡方式,0x52 寻感应区内所有符合1443A标准的卡,0x26 寻未进入休眠状态的卡@param pTagType -[out] 卡片类型代码0x4400 = Mifare_UltraLight0x0400 = Mifare_One(S50)0x0200 = Mifare_One(S70)0x0800 = Mifare_Pro(X)0x4403 = Mifare_DESFire@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdRequest(uint8_t reqCode, uint8_t *pTagType)
{char status;uint32_t len;uint8_t comMF522Buf[MAXRLEN];clearBitMask(Status2Reg, 0x08);writeRawRc(BitFramingReg, 0x07);setBitMask(TxControlReg, 0x03);comMF522Buf[0] = reqCode;status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 1, comMF522Buf, &len);    // 发送并接收数据if((status == MI_OK) && (len == 0x10)){ESP_LOGI(TAG, "mi_ok");*pTagType = comMF522Buf[0];*(pTagType+1) = comMF522Buf[1];}else{ESP_LOGI(TAG, "mi_err");status = MI_ERR;}return status;
}/**@brief 防冲撞@param pSnr -[out] 卡片序列号,4字节@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdAnticoll(uint8_t *pSnr)
{char status;uint8_t i, snrCheck = 0;uint32_t len;uint8_t comMF522Buf[MAXRLEN];clearBitMask(Status2Reg, 0x08);             // 寄存器包含接收器和发送器和数据模式检测器的状态标志writeRawRc(BitFramingReg, 0x00);            // 不启动数据发送,接收的LSB位存放在位0,接收到的第二位放在位1,定义发送的最后一个字节位数为8clearBitMask(CollReg, 0x80);                // 所有接收的位在冲突后将被清除comMF522Buf[0] = PICC_ANTICOLL1;comMF522Buf[1] = 0x20;status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 2, comMF522Buf, &len);if(status == MI_OK){for(i = 0; i < 4; i++){*(pSnr + i) = comMF522Buf[i];snrCheck ^= comMF522Buf[i];}if(snrCheck != comMF522Buf[i])          // 返回四个字节,最后一个字节为校验位{status = MI_ERR;}}setBitMask(CollReg, 0x80);return status;
}/**@brief 选定卡片@param pSnr -[in] 卡片序列号,4字节@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdSelect(uint8_t *pSnr)
{char status;uint8_t i;uint8_t comMF522Buf[MAXRLEN];uint32_t len;comMF522Buf[0] = PICC_ANTICOLL1;comMF522Buf[1] = 0x70;comMF522Buf[6] = 0;for(i = 0; i < 4; i++){comMF522Buf[i + 2] = *(pSnr + i);comMF522Buf[6] ^= *(pSnr + i);}calulateCRC(comMF522Buf, 7, &comMF522Buf[7]);clearBitMask(Status2Reg, 0x08);status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 9, comMF522Buf, &len);if((status == MI_OK ) && (len == 0x18)){status = MI_OK;}else{status = MI_ERR;}return status;
}/**@brief 验证卡片密码@param authMode -[in] 密码验证模式,0x60 验证A密钥,0x61 验证B密钥@param addr -[in] 块地址@param pKey -[in] 密码@param pSnr -[in] 卡片序列号,4字节@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdAuthState(uint8_t authMode, uint8_t addr, uint8_t *pKey, uint8_t *pSnr)
{char status;uint8_t i, comMF522Buf[MAXRLEN];uint32_t len;comMF522Buf[0] = authMode;comMF522Buf[1] = addr;for(i = 0; i < 6; i++){comMF522Buf[i + 2] = *(pKey + i);}for(i = 0; i < 6; i++){comMF522Buf[i + 8] = *(pSnr + i);}status = pcdComMF522(PCD_AUTHENT, comMF522Buf, 12, comMF522Buf, &len);if((status != MI_OK ) || ( ! (readRawRc(Status2Reg) & 0x08))){status = MI_ERR;}return status;
}/**@brief 读取M1卡一块数据@param addr -[in] 块地址@param pData -[out] 读出的数据,16字节@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdRead(uint8_t addr, uint8_t *pData)
{char status;uint8_t i, comMF522Buf[MAXRLEN];uint32_t len;comMF522Buf[0] = PICC_READ;comMF522Buf[1] = addr;calulateCRC(comMF522Buf, 2, &comMF522Buf[2]);status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 4, comMF522Buf, &len);if((status == MI_OK) && (len == 0x90)){for(i = 0; i < 16; i++){*(pData + i) = comMF522Buf[i];}}else{status = MI_ERR;}return status;
}/**@brief 写入M1卡一块数据@param addr -[in] 块地址@param pData -[out] 写入的数据,16字节@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdWrite(uint8_t addr, uint8_t *pData)
{char status;uint8_t i, comMF522Buf[MAXRLEN];uint32_t len;comMF522Buf[0] = PICC_WRITE;comMF522Buf[1] = addr;calulateCRC(comMF522Buf, 2, &comMF522Buf[2]);status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 4, comMF522Buf, &len);if((status != MI_OK) || (len != 4) || ((comMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}if(status == MI_OK){for(i = 0; i < 16; i++){comMF522Buf[i] = *(pData + i);}calulateCRC(comMF522Buf, 16, &comMF522Buf[16]);status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 18, comMF522Buf, &len);if((status != MI_OK) || (len != 4) || ((comMF522Buf[0] & 0x0F) != 0x0A)){status = MI_ERR;}}return status;
}/**@brief 复位RC522@return 无
*/
static void pcdReset(void)
{// 需先保持高电平,后给个下降沿NFC_GPIO_Write(NFC_RST_LOW);delayMs(5);NFC_GPIO_Write(NFC_RST_HIGH);delayMs(10);writeRawRc(CommandReg, PCD_RESETPHASE);     // 和MI卡通讯,CRC初始值0x6363delayMs(1);writeRawRc(ModeReg, 0x3D);writeRawRc(TReloadRegL, 30);writeRawRc(TReloadRegH, 0);writeRawRc(TModeReg, 0x8D);writeRawRc(TPrescalerReg, 0x3E);writeRawRc(TxASKReg, 0x40);
}/**@brief 用MF522计算CRC16@param pInData -[in] 计算CRC16的数组@param len -[in] 计算CRC16的数组字节长度@param pOutData -[out] 存放计算结果存放的首地址@return 无
*/
static void calulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData)
{uint8_t i, n;clearBitMask(DivIrqReg, 0x04);writeRawRc(CommandReg, PCD_IDLE);setBitMask(FIFOLevelReg, 0x80);for(i = 0; i < len; i++){writeRawRc(FIFODataReg, *(pInData + i));}writeRawRc(CommandReg, PCD_CALCCRC);i = 0xFF;do{n = readRawRc(DivIrqReg);i--;}while((i != 0) && ! (n & 0x04));pOutData[0] = readRawRc(CRCResultRegL);pOutData[1] = readRawRc(CRCResultRegM);
}/**@brief 通过MFRC522和ISO14443卡通讯@param command -[in] RC522命令字@param pInData -[in] 通过RC522发送到卡片的数据@param inLenByte -[in] 发送数据的字节长度@param pOutData -[out] 接收到的卡片返回数据@param pOutLenBit -[out] 返回数据的位长度@return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdComMF522(uint8_t command, uint8_t *pInData, uint8_t inLenByte, uint8_t *pOutData, uint32_t *pOutLenBit)
{char status = MI_ERR;uint8_t irqEn = 0x00;uint8_t waitFor = 0x00;uint8_t lastBits;uint8_t n;uint32_t i;uint8_t j;switch(command){case PCD_AUTHENT:irqEn = 0x12;waitFor = 0x10;break;case PCD_TRANSCEIVE:irqEn = 0x77;waitFor = 0x30;break;default:break;}writeRawRc(ComIEnReg, irqEn | 0x80);clearBitMask(ComIrqReg, 0x80);writeRawRc(CommandReg, PCD_IDLE);setBitMask(FIFOLevelReg, 0x80);             // 清空FIFOfor(i = 0; i < inLenByte; i++){writeRawRc(FIFODataReg, pInData[i]);    // 数据写入FIFO}writeRawRc(CommandReg, command);            // 命令写入命令寄存器if(command == PCD_TRANSCEIVE){setBitMask(BitFramingReg, 0x80);        // 开始发送}i = 6000;                                   // 根据时钟频率调整,操作M1卡最大等待时间25ms 2000?do{n = readRawRc(ComIrqReg);i--;}while((i != 0) && !(n & 0x01) && !(n & waitFor));clearBitMask(BitFramingReg, 0x80);if(i != 0){j = readRawRc(ErrorReg);if(!(j & 0x1B)){status = MI_OK;if(n & irqEn & 0x01){status = MI_NOTAGERR;}if(command == PCD_TRANSCEIVE){n = readRawRc(FIFOLevelReg);lastBits = readRawRc(ControlReg) & 0x07;if(lastBits){*pOutLenBit = (n - 1) * 8 + lastBits;}else{*pOutLenBit = n * 8;}if(n == 0){n = 1;}if(n > MAXRLEN){n = MAXRLEN;}for(i = 0; i < n; i++){pOutData[i] = readRawRc(FIFODataReg);}}}else{status = MI_ERR;}}setBitMask(ControlReg, 0x80);               // stop timer nowwriteRawRc(CommandReg, PCD_IDLE);return status;
}/**@brief 开启天线【每次启动或关闭天线发射之间至少有1ms的间隔】@return 无
*/
static void pcdAntennaOn(void)
{uint8_t temp;temp = readRawRc(TxControlReg);if(!(temp & 0x03)){setBitMask(TxControlReg, 0x03);}
}/**@brief 关闭天线@return 无
*/
static void pcdAntennaOff(void)
{clearBitMask(TxControlReg, 0x03);
}/**@brief 置RC522寄存器位@param reg -[in] 寄存器地址@param mask -[in] 置位值@return 无
*/
static void setBitMask(uint8_t reg, uint8_t mask)
{char temp = 0x00;temp = readRawRc(reg) | mask;writeRawRc(reg, temp | mask);               // set bit mask
}/**@brief 清RC522寄存器位@param reg -[in] 寄存器地址@param mask -[in] 清位值@return 无
*/
static void clearBitMask(uint8_t reg, uint8_t mask)
{char temp = 0x00;temp = readRawRc(reg) & (~mask);writeRawRc(reg, temp);                      // clear bit mask
}/**@brief 写RC522寄存器@param addr -[in] 寄存器地址@param writeData -[in] 写入数据@return 无
*/
static void writeRawRc(uint8_t addr, uint8_t writeData)
{SPI_CS_LOW;addr <<= 1;addr &= 0x7e;NFC_SPI_Write(&addr, 1);NFC_SPI_Write(&writeData, 1);SPI_CS_HIGH;
}/**@brief 读RC522寄存器@param addr -[in] 寄存器地址@return 读出一字节数据
*/
static uint8_t readRawRc(uint8_t addr)
{uint8_t readData;SPI_CS_LOW;addr <<= 1;addr |= 0x80;NFC_SPI_Write(&addr, 1);NFC_SPI_Read(&readData, 1);SPI_CS_HIGH;return readData;
}/**@brief 毫秒级延时函数@param time -[in] 延时时间(毫秒)@return 无
*/
static void delayMs(uint8_t time)
{vTaskDelay(time / portTICK_PERIOD_MS);
}/****************************************************END OF FILE****************************************************/

4.6 board_mfrc522.h

#ifndef _BOARD_MFRC522_H_
#define _BOARD_MFRC522_H_/********************************************************************** INCLUDES*//********************************************************************** DEFINITIONS*/
#define MAXRLEN                   18//******************************************************************/
// MFRC522命令字
//******************************************************************/
#define PCD_IDLE                  0x00           // 取消当前命令
#define PCD_AUTHENT               0x0E           // 验证密钥
#define PCD_RECEIVE               0x08           // 接收数据
#define PCD_TRANSMIT              0x04           // 发送数据
#define PCD_TRANSCEIVE            0x0C           // 发送并接收数据
#define PCD_RESETPHASE            0x0F           // 复位
#define PCD_CALCCRC               0x03           // CRC计算//******************************************************************/
// Mifare_One卡片命令字
//******************************************************************/
#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           // 休眠//******************************************************************/
// MFRC522 FIFO长度定义
//******************************************************************/
#define DEF_FIFO_LENGTH           64             // FIFO size=64byte//******************************************************************/
// MFRC522寄存器定义
//******************************************************************/
// PAGE 0
#define RFU00                     0x00
#define CommandReg                0x01
#define ComIEnReg                 0x02
#define DivlEnReg                 0x03
#define ComIrqReg                 0x04
#define DivIrqReg                 0x05
#define ErrorReg                  0x06
#define Status1Reg                0x07
#define Status2Reg                0x08
#define FIFODataReg               0x09
#define FIFOLevelReg              0x0A
#define WaterLevelReg             0x0B
#define ControlReg                0x0C
#define BitFramingReg             0x0D
#define CollReg                   0x0E
#define RFU0F                     0x0F
// PAGE 1
#define RFU10                     0x10
#define ModeReg                   0x11
#define TxModeReg                 0x12
#define RxModeReg                 0x13
#define TxControlReg              0x14
#define TxASKReg                  0x15
#define TxSelReg                  0x16
#define RxSelReg                  0x17
#define RxThresholdReg            0x18
#define DemodReg                  0x19
#define RFU1A                     0x1A
#define RFU1B                     0x1B
#define MifareReg                 0x1C
#define RFU1D                     0x1D
#define RFU1E                     0x1E
#define SerialSpeedReg            0x1F
// PAGE 2
#define RFU20                     0x20
#define CRCResultRegM             0x21
#define CRCResultRegL             0x22
#define RFU23                     0x23
#define ModWidthReg               0x24
#define RFU25                     0x25
#define RFCfgReg                  0x26
#define GsNReg                    0x27
#define CWGsCfgReg                0x28
#define ModGsCfgReg               0x29
#define TModeReg                  0x2A
#define TPrescalerReg             0x2B
#define TReloadRegH               0x2C
#define TReloadRegL               0x2D
#define TCounterValueRegH         0x2E
#define TCounterValueRegL         0x2F
// PAGE 3
#define RFU30                     0x30
#define TestSel1Reg               0x31
#define TestSel2Reg               0x32
#define TestPinEnReg              0x33
#define TestPinValueReg           0x34
#define TestBusReg                0x35
#define AutoTestReg               0x36
#define VersionReg                0x37
#define AnalogTestReg             0x38
#define TestDAC1Reg               0x39
#define TestDAC2Reg               0x3A
#define TestADCReg                0x3B
#define RFU3C                     0x3C
#define RFU3D                     0x3D
#define RFU3E                     0x3E
#define RFU3F                     0x3F//******************************************************************/
// MFRC522通讯返回错误代码
//******************************************************************/
#define MI_OK                     (char)0
#define MI_NOTAGERR               (char)(-1)
#define MI_ERR                    (char)(-2)/********************************************************************** API FUNCTIONS*/
void MFRC522_Init(void);
uint8_t MFRC522_ReadCardDataBlock(uint8_t addr);
uint8_t MFRC522_ReadCardSerialNo(uint8_t *pCardSerialNo);#endif /* _BOARD_MFRC522_H_ */

五、API调用

需包含头文件 board_mfrc522.h

5.1 MFRC522_Init()

功能 MFRC522初始化函数
函数定义 void MFRC522_Init(void)
参数
返回

5.2 MFRC522_ReadCardDataBlock()

功能 MFRC522读取卡片块数据
函数定义 uint8_t MFRC522_ReadCardDataBlock(uint8_t blockAddr)
参数 blockAddr:块地址
返回 状态值,0 - 成功;2 - 无卡;3 - 防冲撞失败;4 - 选卡失败;5 - 密码错误

5.3 MFRC522_ReadCardSerialNo()

功能 读取卡片序列号
函数定义 uint8_t MFRC522_ReadCardSerialNo(uint8_t *pCardSerialNo)
参数 pCardSerialNo:卡片序列号
返回 状态值,0 - 读卡成功;2 - 无卡

六、使用例子

1)添加头文件

#include "board_gpio.h"
#include "board_mfrc522.h"
#include "board_spi.h"

2)添加初始化代码(main.c的main函数中)
首先调用 NFC_GPIO_Init() 初始化 RFID RC522 模块的 RST 引脚,然后调用 NFC_SPI_Init() 初始化 SPI 通信,最后调用 MFRC522_Init() 初始化 RC522 模块。

/**@brief Application main function.*/
void app_main(void)
{ESP_ERROR_CHECK(nvs_flash_init());NFC_GPIO_Init();NFC_SPI_Init();MFRC522_Init();/*-------------------------- 创建线程 ---------------------------*/xTaskCreate(monitor_task, "monitor_task", 2048, NULL, 4, NULL);
}

3)添加任务,定时读取数据块4

static void monitor_task(void *arg)
{while(1)                                                                // 任务都是一个无限循环,不能返回{uint8_t card[4];MFRC522_ReadCardSerialNo(card);ESP_LOGI(TAG, "card: %02x%02x%02x%02x", card[0], card[1], card[2], card[3]);vTaskDelay(500 / portTICK_PERIOD_MS);                                                        // 100ms}
}

4)复位后,可通过读取以下三个寄存器,判断SPI是否通信成功

ESP_LOGI(TAG, "reg: %02x" ,readRawRc(Status1Reg));
ESP_LOGI(TAG, "reg: %02x" ,readRawRc(Status2Reg));
ESP_LOGI(TAG, "reg: %02x" ,readRawRc(WaterLevelReg));



查看打印,返回值与数据手册中描述一致

5)读取卡号


• 由 Leung 写于 2022 年 5 月 30 日

ESP32学习笔记(49)——RFID RC522使用相关推荐

  1. 关于esp32蓝牙模块的使用——esp32学习笔记

    关于esp32蓝牙模块的使用--esp32学习笔记 关于esp32蓝牙模块的使用--esp32学习笔记 关于esp32蓝牙模块的使用--esp32学习笔记 零.前言 一.经典蓝牙BT 二.低功耗蓝牙B ...

  2. ESP32学习笔记(1)——搭建环境、编译烧写(Windows+VS Code)

    Espressif-IDE 环境搭建参看 ESP32学习笔记(50)--搭建环境.编译烧写(Windows+Espressif-IDE) 一.搭建环境 1.1 官方资料 ESP-IDF 编程指南 1. ...

  3. ESP32学习笔记(27)——BLE GAP主机端扫描

    一.背景 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...

  4. ESP32学习笔记(七) 复位和时钟

    ESP32学习笔记(七) 复位和时钟 目录: ESP32学习笔记(一) 芯片型号介绍 ESP32学习笔记(二) 开发环境搭建 VSCode+platformio ESP32学习笔记(三) 硬件资源介绍 ...

  5. ESP32学习笔记(20)——SPI(从机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  6. ESP32学习笔记(一) 芯片型号介绍

    ESP32学习笔记(一) 芯片型号介绍 目录: ESP32学习笔记(一) 芯片型号介绍 ESP32学习笔记(二) 开发环境搭建 VSCode+platformio ESP32学习笔记(三) 硬件资源介 ...

  7. ESP32学习笔记(19)——SPI(主机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  8. ESP32学习笔记 - ESP32使用GUI-Guider制作LVGL图形界面

    上一篇文章讲述了如何移植嵌入式图形界面库LVGL到ESP32芯片平台,并成功在ESP32上面运行LVGL的官方demo,上一篇文章请参考以下链接. ESP32学习笔记 - 移植LVGL_EmbedIo ...

  9. ESP32学习笔记(51)——搭建环境、编译烧写(Windows+Espressif-IDE)

    VS Code 环境搭建参看 ESP32学习笔记(1)--搭建环境.编译烧写(Windows+VS Code) 一.搭建环境 1.1 官方资料 ESP-IDF 编程指南 1.2 下载Espressif ...

最新文章

  1. 机器学习数据预处理之缺失值:中位数填充
  2. 手写logback_springboot logback调整mybatis日志级别无效的解决
  3. 若依微服务版在Windows上通过jar包运行业务模块时提示:Failed to determine s suitable driver class
  4. 【基础】C#异常处理的总结
  5. iOS25个性能优化,和内存优化
  6. P(A)P(B|A)=P(B)P(A|B)
  7. oracle shutdown 默认,oracle shutdown 没有反应
  8. 深入理解前端跨域问题的解决方案——前端面试
  9. 求一批整数中出现最多的个位数字
  10. 微信公众号推送消息模板(抖音挺火的推送消息给女朋友)
  11. 简单获取apk的签名及shal码
  12. 表格控件SpreadJS助力上市企业明源云,打造更智慧的地产生态链
  13. Java编程:颜色色带图片的生成
  14. 选取最优模型--scikit-learn的Python中抽查回归机器学习算法
  15. final 修饰的成员变量必须手动初始化
  16. 【老本行的碎碎念】- - 关于新闻传播的整体认识和下一步规划 - - 开始继续充电趴!~ :D
  17. [JPA知识] 通过@Valu和@ConfigurationProperties注解去拿yml参数?
  18. 基本RS触发器(SR锁存器)
  19. c语言课题设计题目猜数字游戏,C语言课题设计报告(猜数字游戏)文档.doc
  20. LiveGBS GB28181流媒体服务-产品介绍及相关资源

热门文章

  1. 制作哔哩哔哩弹幕词云
  2. 大众汽车如何在智能电动汽车时代做好汽车安全?
  3. 关于计算机软件技术基础知识,《计算机软件技术基础》知识要点.doc
  4. win10系统重装win7注意
  5. 时域分析——无量纲特征值含义一网打尽
  6. 好用的老照片修复神器软件有哪些?这三个工具帮你留住回忆
  7. 1.2V转5V稳压芯片,低功耗电路
  8. 笔记:FPGA与VHDL语言学习2
  9. java回顾:JDBC、工具类、事务、SQL注入
  10. android动画机制,动画机制-《Android群英传》