STM32F103C8T6 RC522模块驱动程序详解 - 附示例代码
STM32F103C8T6 RC522模块驱动程序详解
以下是一个STM32F103C8T6的RC522模块驱动程序的示例代码,包含初始化、请求、防碰撞、选择卡片、认证、读写等常用功能的代码实现。
代码示例
#include 'stm32f10x.h'
#include 'rc522.h'
void RC522_Init(void)
{
SPI2_Init(); // 初始化SPI2
RC522_Reset(); // 复位RC522
RC522_WriteReg(TModeReg, 0x8D); // 设置定时器的预分频因子和重载值
RC522_WriteReg(TPrescalerReg, 0x3E);
RC522_WriteReg(TReloadRegL, 30);
RC522_WriteReg(TReloadRegH, 0);
RC522_WriteReg(TxAutoReg, 0x40); // 使能自动计算CRC校验
RC522_WriteReg(ModeReg, 0x3D); // 配置RC522为ISO14443A模式
RC522_AntennaOn(); // 打开天线
}
uint8_t RC522_Request(uint8_t req_code, uint8_t *pTagType)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[2];
tx_data[0] = req_code;
tx_data[1] = 0x0;
RC522_WriteReg(BitFramingReg, 0x07); // 配置发送位帧和接收位帧的长度
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 2, pTagType, &len, &recv_bits);
if ((status != MI_OK) || (len != 0x10))
{
status = MI_ERR;
}
return status;
}
uint8_t RC522_Anticoll(uint8_t *pSnr)
{
uint8_t status, i, snr_check = 0;
uint16_t recv_bits;
uint8_t tx_data[2];
uint8_t tmp, len;
tx_data[0] = PICC_ANTICOLL1;
tx_data[1] = 0x20;
RC522_WriteReg(BitFramingReg, 0x00); // 关闭发送位帧和接收位帧的长度限制
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 2, pSnr, &len, &recv_bits);
if (status == MI_OK)
{
for (i = 0; i < 4; i++)
{
snr_check ^= pSnr[i];
}
if (snr_check != pSnr[i])
{
status = MI_ERR;
}
}
return status;
}
uint8_t RC522_SelectTag(uint8_t *pSnr)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[9];
tx_data[0] = PICC_SELECT1;
tx_data[1] = 0x70;
for (int i = 0; i < 5; i++)
{
tx_data[i + 2] = pSnr[i];
}
tx_data[7] = 0x0;
tx_data[8] = 0x0;
RC522_WriteReg(BitFramingReg, 0x00); // 关闭发送位帧和接收位帧的长度限制
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 9, pSnr, &len, &recv_bits);
if ((status != MI_OK) || (len != 0x18))
{
status = MI_ERR;
}
return status;
}
uint8_t RC522_Auth(uint8_t auth_mode, uint8_t block_addr, uint8_t *pKey, uint8_t *pSnr)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[12];
tx_data[0] = auth_mode;
tx_data[1] = block_addr;
for (int i = 0; i < 6; i++)
{
tx_data[i + 2] = pKey[i];
}
for (int i = 0; i < 4; i++)
{
tx_data[i + 8] = pSnr[i];
}
status = RC522_ToCard(PCD_AUTHENT, tx_data, 12, pSnr, &len, &recv_bits);
if ((status != MI_OK) || (!(RC522_ReadReg(Status2Reg) & 0x08)))
{
status = MI_ERR;
}
return status;
}
uint8_t RC522_Read(uint8_t block_addr, uint8_t *pData)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[4];
tx_data[0] = PICC_READ;
tx_data[1] = block_addr;
RC522_CalculateCRC(tx_data, 2, &tx_data[2]);
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 4, pData, &len, &recv_bits);
if ((status != MI_OK) || (len != 0x10))
{
status = MI_ERR;
}
return status;
}
uint8_t RC522_Write(uint8_t block_addr, uint8_t *pData)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[18];
tx_data[0] = PICC_WRITE;
tx_data[1] = block_addr;
RC522_CalculateCRC(tx_data, 2, &tx_data[2]);
for (int i = 0; i < 16; i++)
{
tx_data[i + 4] = pData[i];
}
RC522_CalculateCRC(tx_data, 18, &tx_data[18]);
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 20, tx_data, &len, &recv_bits);
if ((status != MI_OK) || (len != 4) || ((tx_data[0] & 0x0F) != 0x0A))
{
status = MI_ERR;
}
return status;
}
uint8_t RC522_Halt(void)
{
uint8_t status, len;
uint16_t recv_bits;
uint8_t tx_data[4];
tx_data[0] = PICC_HALT;
tx_data[1] = 0x0;
RC522_CalculateCRC(tx_data, 2, &tx_data[2]);
status = RC522_ToCard(PCD_TRANSCEIVE, tx_data, 4, tx_data, &len, &recv_bits);
return MI_OK;
}
uint8_t RC522_ToCard(uint8_t cmd, uint8_t *pData, uint8_t data_len, uint8_t *pResp, uint8_t *pRespLen, uint16_t *pRecvBits)
{
uint8_t status = MI_ERR;
uint8_t irq_en = 0x0;
uint8_t wait_irq = 0x0;
uint8_t last_bits;
uint8_t n;
uint16_t i;
switch (cmd)
{
case PCD_AUTHENT:
irq_en = 0x12;
wait_irq = 0x10;
break;
case PCD_TRANSCEIVE:
irq_en = 0x77;
wait_irq = 0x30;
break;
default:
break;
}
RC522_WriteReg(CommIEnReg, irq_en | 0x80);
RC522_ClearBitMask(CommIrqReg, 0x80);
RC522_SetBitMask(FIFOLevelReg, 0x80);
RC522_WriteReg(CommandReg, PCD_IDLE);
for (i = 0; i < data_len; i++)
{
RC522_WriteReg(FIFODataReg, pData[i]);
}
RC522_WriteReg(CommandReg, cmd);
if (cmd == PCD_TRANSCEIVE)
{
RC522_SetBitMask(BitFramingReg, 0x80);
}
i = 2000;
while (1)
{
n = RC522_ReadReg(CommIrqReg);
i--;
if ((i == 0) || (n & 0x01) || (n & wait_irq))
{
break;
}
}
RC522_ClearBitMask(BitFramingReg, 0x80);
if (i != 0)
{
if (!(RC522_ReadReg(ErrorReg) & 0x1B))
{
status = MI_OK;
if (n & irq_en & 0x01)
{
status = MI_NOTAGERR;
}
if (cmd == PCD_TRANSCEIVE)
{
n = RC522_ReadReg(FIFOLevelReg);
last_bits = RC522_ReadReg(ControlReg) & 0x07;
if (last_bits)
{
*pRecvBits = (n - 1) * 8 + last_bits;
}
else
{
*pRecvBits = n * 8;
}
if (n == 0)
{
n = 1;
}
if (n > MAX_LEN)
{
n = MAX_LEN;
}
for (i = 0; i < n; i++)
{
pResp[i] = RC522_ReadReg(FIFODataReg);
}
*pRespLen = n;
}
}
else
{
status = MI_ERR;
}
}
return status;
}
void RC522_Reset(void)
{
RC522_WriteReg(CommandReg, PCD_RESETPHASE);
}
void RC522_WriteReg(uint8_t addr, uint8_t val)
{
RC522_CS_LOW();
SPI2_SendByte((addr << 1) & 0x7E);
SPI2_SendByte(val);
RC522_CS_HIGH();
}
uint8_t RC522_ReadReg(uint8_t addr)
{
uint8_t val;
RC522_CS_LOW();
SPI2_SendByte(((addr << 1) & 0x7E) | 0x80);
val = SPI2_SendByte(0x0);
RC522_CS_HIGH();
return val;
}
void RC522_SetBitMask(uint8_t addr, uint8_t mask)
{
uint8_t val;
val = RC522_ReadReg(addr);
RC522_WriteReg(addr, val | mask);
}
void RC522_ClearBitMask(uint8_t addr, uint8_t mask)
{
uint8_t val;
val = RC522_ReadReg(addr);
RC522_WriteReg(addr, val & ~mask);
}
void RC522_AntennaOn(void)
{
uint8_t val;
val = RC522_ReadReg(TxControlReg);
if (!(val & 0x03))
{
RC522_SetBitMask(TxControlReg, 0x03);
}
}
void RC522_AntennaOff(void)
{
RC522_ClearBitMask(TxControlReg, 0x03);
}
void RC522_CalculateCRC(uint8_t *pData, uint8_t data_len, uint8_t *pCRC)
{
uint8_t i, n;
RC522_ClearBitMask(DivIrqReg, 0x04);
RC522_SetBitMask(FIFOLevelReg, 0x80);
for (i = 0; i < data_len; i++)
{
RC522_WriteReg(FIFODataReg, pData[i]);
}
RC522_WriteReg(CommandReg, PCD_CALCCRC);
i = 0xFF;
while (1)
{
n = RC522_ReadReg(DivIrqReg);
i--;
if ((i == 0) || (n & 0x04))
{
break;
}
}
pCRC[0] = RC522_ReadReg(CRCResultRegL);
pCRC[1] = RC522_ReadReg(CRCResultRegM);
}
uint8_t RC522_Check(uint8_t *pTagType)
{
uint8_t status;
uint8_t i;
uint8_t pSnr[MAX_LEN];
uint8_t sak;
status = RC522_Request(PICC_REQIDL, pTagType);
if (status == MI_OK)
{
status = RC522_Anticoll(pSnr);
if (status == MI_OK)
{
sak = RC522_SelectTag(pSnr);
if (sak != 0x08)
{
status = MI_ERR;
}
}
}
return status;
}
函数说明
RC522_Init(): 初始化RC522模块。RC522_Request(): 发送请求命令到卡片。RC522_Anticoll(): 防碰撞处理,获取卡片序列号。RC522_SelectTag(): 选择指定序列号的卡片。RC522_Auth(): 验证卡片密码。RC522_Read(): 读取指定块的数据。RC522_Write(): 写数据到指定块。RC522_Halt(): 置卡片于休眠状态。RC522_ToCard(): 向卡片发送命令并接收响应数据。RC522_Reset(): 复位RC522模块。RC522_WriteReg(): 写数据到RC522寄存器。RC522_ReadReg(): 读取RC522寄存器值。RC522_SetBitMask(): 设置RC522寄存器指定位。RC522_ClearBitMask(): 清除RC522寄存器指定位。RC522_AntennaOn(): 打开天线。RC522_AntennaOff(): 关闭天线。RC522_CalculateCRC(): 计算CRC校验码。RC522_Check(): 检测卡片是否存在。
注意事项
- 请根据实际硬件连接修改代码中的SPI和CS引脚配置。
- 使用前请确保已正确安装RC522库文件。
- 以上代码仅供参考,具体实现细节请根据实际情况进行调整。
原文地址: https://www.cveoy.top/t/topic/jmXl 著作权归作者所有。请勿转载和采集!