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库文件。
  • 以上代码仅供参考,具体实现细节请根据实际情况进行调整。
STM32F103C8T6 RC522模块驱动程序详解 - 附示例代码

原文地址: https://www.cveoy.top/t/topic/jmXl 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录