打印
[应用相关]

STM32+RC522 - 射频IC识别模块

[复制链接]
82|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、引言
在物联网和智能识别领域,射频识别(RFID)技术发挥着重要作用。RC522 是一款高度集成的非接触式读写卡芯片,工作在 13.56MHz 频率,支持 ISO/IEC 14443A 协议,可用于识别 Mifare 系列的射频卡。结合 STM32 微控制器强大的处理能力,我们可以实现一个高效、稳定的射频 IC 识别系统。本文将详细介绍如何使用 STM32 与 RC522 模块搭建射频 IC 识别系统,并给出相应的代码示例。

二、RC522 模块概述
2.1 主要特性
高集成度:内置了射频发射器、接收器、调制解调器和电源管理电路,可直接驱动天线。
多协议支持:支持 ISO/IEC 14443A/MIFARE 协议,能与多种类型的射频卡进行通信。
通信接口丰富:支持 SPI、I2C 和 UART 三种通信接口,方便与不同的微控制器连接。
2.2 引脚说明



三、硬件连接
以 STM32F103C8T6 为例,将 RC522 模块与 STM32 进行连接,具体连接方式如下:



四、STM32 与 RC522 通信的软件实现
4.1 SPI 接口初始化
在 STM32 中,我们使用 SPI 接口与 RC522 进行通信。以下是 SPI 接口初始化的代码:

#include "stm32f10x.h"

void SPI1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;

    // 使能 SPI1 和 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 SPI1 引脚:SCK、MISO、MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置 NSS 引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_4); // NSS 默认高电平

    // 配置 SPI1
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    // 使能 SPI1
    SPI_Cmd(SPI1, ENABLE);
}

// SPI 读写一个字节数据
u8 SPI1_ReadWriteByte(u8 TxData)
{
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, TxData);
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI1);
}



4.2 RC522 寄存器读写操作
RC522 通过寄存器来配置和控制其工作状态,以下是对 RC522 寄存器进行读写操作的代码:

// 向 RC522 寄存器写数据
void RC522_WriteReg(u8 reg, u8 data)
{
    GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 片选拉低
    SPI1_ReadWriteByte((reg << 1) & 0x7E);
    SPI1_ReadWriteByte(data);
    GPIO_SetBits(GPIOA, GPIO_Pin_4); // 片选拉高
}

// 从 RC522 寄存器读数据
u8 RC522_ReadReg(u8 reg)
{
    u8 val;
    GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 片选拉低
    SPI1_ReadWriteByte(((reg << 1) & 0x7E) | 0x80);
    val = SPI1_ReadWriteByte(0x00);
    GPIO_SetBits(GPIOA, GPIO_Pin_4); // 片选拉高
    return val;
}



4.3 RC522 初始化
在使用 RC522 之前,需要对其进行初始化,配置相关寄存器:

// RC522 复位
void RC522_Reset(void)
{
    RC522_WriteReg(CommandReg, PCD_RESETPHASE);
}

// RC522 初始化
void RC522_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能 GPIOB 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 配置 RST 引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB, GPIO_Pin_0); // RST 默认高电平

    SPI1_Init();
    RC522_Reset();

    // 初始化寄存器
    RC522_WriteReg(TModeReg, 0x8D);
    RC522_WriteReg(TPrescalerReg, 0x3E);
    RC522_WriteReg(TReloadRegL, 30);
    RC522_WriteReg(TReloadRegH, 0);
    RC522_WriteReg(TxAutoReg, 0x40);
    RC522_WriteReg(ModeReg, 0x3D);

    // 开启天线
    RC522_WriteReg(TxControlReg, 0x03);
}



4.4 寻卡操作
寻卡是识别射频卡的第一步,通过发送特定的命令来检测附近是否有卡存在:

// 寻卡函数
u8 RC522_Request(u8 reqMode, u8 *TagType)
{
    u8 status;
    u16 backBits;

    RC522_WriteReg(BitFramingReg, 0x07);

    TagType[0] = reqMode;
    status = RC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);

    if ((status != MI_OK) || (backBits != 0x10))
    {
        status = MI_ERR;
    }

    return status;
}



4.5 防冲突操作
当多个射频卡同时出现在感应范围内时,需要进行防冲突操作,以确保能够正确识别每张卡:

// 防冲突函数
u8 RC522_Anticoll(u8 *serNum)
{
    u8 status;
    u8 i, serNumCheck = 0;
    u16 backBits;

    RC522_WriteReg(BitFramingReg, 0x00);

    serNum[0] = PICC_ANTICOLL1;
    serNum[1] = 0x20;
    status = RC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &backBits);

    if (status == MI_OK)
    {
        for (i = 0; i < 4; i++)
        {
            serNumCheck ^= serNum;
        }
        if (serNumCheck != serNum[4])
        {
            status = MI_ERR;
        }
    }

    return status;
}



4.6 选卡操作
在防冲突后,需要选择一张卡进行后续的读写操作:

// 选卡函数
u8 RC522_SelectTag(u8 *serNum)
{
    u8 i;
    u8 status;
    u8 buf[6];
    u16 backBits;

    buf[0] = PICC_SElECTTAG;
    buf[1] = 0x70;
    for (i = 0; i < 5; i++)
    {
        buf[i + 2] = *(serNum + i);
    }
    CalulateCRC(buf, 7, &buf[7]);

    status = RC522_ToCard(PCD_TRANSCEIVE, buf, 9, buf, &backBits);

    if ((status == MI_OK) && (backBits == 0x18))
    {
        // 选卡成功
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}



五、主函数实现
int main(void)
{
    u8 status;
    u8 TagType[2];
    u8 serNum[5];

    RC522_Init();

    while (1)
    {
        // 寻卡
        status = RC522_Request(PICC_REQIDL, TagType);
        if (status == MI_OK)
        {
            // 防冲突
            status = RC522_Anticoll(serNum);
            if (status == MI_OK)
            {
                // 选卡
                status = RC522_SelectTag(serNum);
                if (status == MI_OK)
                {
                    // 选卡成功,可以进行后续读写操作
                }
            }
        }
    }
}



六、总结
通过以上步骤,我们实现了基于 STM32 和 RC522 模块的射频 IC 识别系统。在实际应用中,还可以进一步扩展功能,如对卡片进行读写操作、与上位机进行通信等。同时,需要注意硬件连接的正确性和稳定性,以及软件代码的优化,以提高系统的性能和可靠性。

以上代码只是一个基本的示例,实际应用中可能需要根据具体需求进行调整和扩展。希望本文能帮助你快速掌握 STM32 与 RC522 模块的使用方法。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/duierrorshuobu/article/details/146056086

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

90

帖子

0

粉丝