STM32F103RCT6(基于HAL库)+RC522RFID模块开发读写模块

该例程参考自:从0开始设计_基于STM32F1的RC522读写卡-OpenEdv-开源电子网

STM32 (基于HAL库)MFRC-522 无线射频IC卡驱动教程(RFID)mfrc522如何与stm32开发嵌入式lover的博客-CSDN博客

首先准备好需要使用的硬件设备:正点原子MiniSTM32开发板一块,MiniRFID-RC522模块一个,杜邦线七条,miniUSB线一条,ST_Link一个(ST_Link是需要一根miniUSB线与20pin接口线的,也可采用4条杜邦线连接;也可换为J_Link),M1白卡一张,

如图

STM32 Cobe MX配置

代码部分:

rc522.c

/*************笔记****************
1、接线方式:
STM32            RFID
PA4     ->       SDA
PA5     ->       SCK
PA7     ->       MOSI  
PA6     ->       MISO
悬空    ->       IKQ
GND     ->       GND
PA3     ->       RST
3.3V    ->       3.3V
​
2、应用函数
    MFRC_Init();//初始化
    PCD_Reset();//器件复位
    PCD_Request(PICC_REQALL, RxBuffer);//返回值为0,代表寻卡成功;并把卡类型存入RxBuffer中
    PCD_Anticoll(RxBuffer);   //把(十六进制)的4个字节卡号存储在数组RxBuffer中
***********************************/
​
#include "rc522.h"
#include "usart.h"
​
​
extern SPI_HandleTypeDef hspi1;
​
/**************************************************************************************
* 函数名称:MFRC_Init
* 功能描述:MFRC初始化
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说    明:MFRC的SPI接口速率为0~10Mbps
***************************************************************************************/
void MFRC_Init(void)
{
    RS522_NSS(1);
    RS522_RST(1);
}
​
​
/**************************************************************************************
* 函数名称: SPI_RW_Byte
* 功能描述: 模拟SPI读写一个字节
* 入口参数: -byte:要发送的数据
* 出口参数: -byte:接收到的数据
***************************************************************************************/
static uint8_t ret;  //这些函数是HAL与标准库不同的地方【读写函数】
uint8_t SPI2_RW_Byte(uint8_t byte)
{
    HAL_SPI_TransmitReceive(&hspi1, &byte, &ret, 1, 10);//把byte 写入,并读出一个值,把它存入ret
    return   ret;//入口是byte 的地址,读取时用的也是ret地址,一次只写入一个值10
}
​
​
/**************************************************************************************
* 函数名称:MFRC_WriteReg
* 功能描述:写一个寄存器
* 入口参数:-addr:待写的寄存器地址
*           -data:待写的寄存器数据
* 出口参数:无
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void MFRC_WriteReg(uint8_t addr, uint8_t data)
{
    uint8_t AddrByte;
    AddrByte = (addr << 1 ) & 0x7E; //求出地址字节
    RS522_NSS(0);                   //NSS拉低
    SPI2_RW_Byte(AddrByte);         //写地址字节
    SPI2_RW_Byte(data);             //写数据
    RS522_NSS(1);                   //NSS拉高
}
​
​
/**************************************************************************************
* 函数名称:MFRC_ReadReg
* 功能描述:读一个寄存器
* 入口参数:-addr:待读的寄存器地址
* 出口参数:无
* 返 回 值:-data:读到寄存器的数据
* 说    明:无
***************************************************************************************/
uint8_t MFRC_ReadReg(uint8_t addr)
{
    uint8_t AddrByte, data;
    AddrByte = ((addr << 1 ) & 0x7E ) | 0x80;   //求出地址字节
    RS522_NSS(0);                               //NSS拉低
    SPI2_RW_Byte(AddrByte);                     //写地址字节
    data = SPI2_RW_Byte(0x00);                  //读数据
    RS522_NSS(1);                               //NSS拉高
    return data;
}
​
​
/**************************************************************************************
* 函数名称:MFRC_SetBitMask
* 功能描述:设置寄存器的位
* 入口参数:-addr:待设置的寄存器地址
*           -mask:待设置寄存器的位(可同时设置多个bit)
* 出口参数:无
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void MFRC_SetBitMask(uint8_t addr, uint8_t mask)
{
    uint8_t temp;
    temp = MFRC_ReadReg(addr);                  //先读回寄存器的值
    MFRC_WriteReg(addr, temp | mask);           //处理过的数据再写入寄存器
}
​
​
/**************************************************************************************
* 函数名称:MFRC_ClrBitMask
* 功能描述:清除寄存器的位
* 入口参数:-addr:待清除的寄存器地址
*           -mask:待清除寄存器的位(可同时清除多个bit)
* 出口参数:无
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void MFRC_ClrBitMask(uint8_t addr, uint8_t mask)
{
    uint8_t temp;
    temp = MFRC_ReadReg(addr);                  //先读回寄存器的值
    MFRC_WriteReg(addr, temp & ~mask);          //处理过的数据再写入寄存器
}
​
​
/**************************************************************************************
* 函数名称:MFRC_CalulateCRC
* 功能描述:用MFRC计算CRC结果
* 入口参数:-pInData:带进行CRC计算的数据
*           -len:带进行CRC计算的数据长度
*           -pOutData:CRC计算结果
* 出口参数:-pOutData:CRC计算结果
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void MFRC_CalulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData)
{
    //0xc1 1        2           pInData[2]
    uint8_t temp;
    uint32_t i;
    MFRC_ClrBitMask(MFRC_DivIrqReg, 0x04);                  //使能CRC中断
    MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE);              //取消当前命令的执行
    MFRC_SetBitMask(MFRC_FIFOLevelReg, 0x80);               //清除FIFO及其标志位
    for(i = 0; i < len; i++)                                //将待CRC计算的数据写入FIFO
    {
        MFRC_WriteReg(MFRC_FIFODataReg, *(pInData + i));
    }
    MFRC_WriteReg(MFRC_CommandReg, MFRC_CALCCRC);           //执行CRC计算
    i = 100000;
    do
    {
        temp = MFRC_ReadReg(MFRC_DivIrqReg);                //读取DivIrqReg寄存器的值
        i--;
    }
    while((i != 0) && !(temp & 0x04));                      //等待CRC计算完成
    pOutData[0] = MFRC_ReadReg(MFRC_CRCResultRegL);         //读取CRC计算结果
    pOutData[1] = MFRC_ReadReg(MFRC_CRCResultRegM);
}
​
​
/**************************************************************************************
* 函数名称:MFRC_CmdFrame
* 功能描述:MFRC522和ISO14443A卡通讯的命令帧函数
* 入口参数:-cmd:MFRC522命令字
*           -pIndata:MFRC522发送给MF1卡的数据的缓冲区首地址
*           -InLenByte:发送数据的字节长度
*           -pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
*           -pOutLenBit:MF1卡返回数据的位长度
* 出口参数:-pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
*           -pOutLenBit:用于MF1卡返回数据位长度的首地址
* 返 回 值:-status:错误代码(MFRC_OK、MFRC_NOTAGERR、MFRC_ERR)
* 说    明:无
***************************************************************************************/
char MFRC_CmdFrame(uint8_t cmd, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint16_t *pOutLenBit)
{
    uint8_t lastBits;
    uint8_t n;
    uint32_t i;
    char status = MFRC_ERR;
    uint8_t irqEn   = 0x00;
    uint8_t waitFor = 0x00;
​
    /*根据命令设置标志位*/
    switch(cmd)
    {
        case MFRC_AUTHENT:                  //Mifare认证
            irqEn = 0x12;
            waitFor = 0x10;                 //idleIRq中断标志
            break;
        case MFRC_TRANSCEIVE:               //发送并接收数据
            irqEn = 0x77;
            waitFor = 0x30;                 //RxIRq和idleIRq中断标志
            break;
    }
​
    /*发送命令帧前准备*/
    MFRC_WriteReg(MFRC_ComIEnReg, irqEn | 0x80);    //开中断
    MFRC_ClrBitMask(MFRC_ComIrqReg, 0x80);          //清除中断标志位SET1
    MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE);      //取消当前命令的执行
    MFRC_SetBitMask(MFRC_FIFOLevelReg, 0x80);       //清除FIFO缓冲区及其标志位
​
    /*发送命令帧*/
    for(i = 0; i < InLenByte; i++)                  //写入命令参数
    {
        MFRC_WriteReg(MFRC_FIFODataReg, pInData[i]);
    }
    MFRC_WriteReg(MFRC_CommandReg, cmd);            //执行命令
    if(cmd == MFRC_TRANSCEIVE)
    {
        MFRC_SetBitMask(MFRC_BitFramingReg, 0x80);  //启动发送
    }
    i = 300000;                                     //根据时钟频率调整,操作M1卡最大等待时间25ms
    do
    {
        n = MFRC_ReadReg(MFRC_ComIrqReg);
        i--;
    }
    while((i != 0) && !(n & 0x01) && !(n & waitFor));     //等待命令完成
    MFRC_ClrBitMask(MFRC_BitFramingReg, 0x80);          //停止发送
​
    /*处理接收的数据*/
    if(i != 0)
    {
        if(!(MFRC_ReadReg(MFRC_ErrorReg) & 0x1B))
        {
            status = MFRC_OK;
            if(n & irqEn & 0x01)
            {
                status = MFRC_NOTAGERR;
            }
            if(cmd == MFRC_TRANSCEIVE)
            {
                n = MFRC_ReadReg(MFRC_FIFOLevelReg);
                lastBits = MFRC_ReadReg(MFRC_ControlReg) & 0x07;
                if (lastBits)
                {
                    *pOutLenBit = (n - 1) * 8 + lastBits;
                }
                else
                {
                    *pOutLenBit = n * 8;
                }
                if(n == 0)
                {
                    n = 1;
                }
                if(n > MFRC_MAXRLEN)
                {
                    n = MFRC_MAXRLEN;
                }
                for(i = 0; i < n; i++)
                {
                    pOutData[i] = MFRC_ReadReg(MFRC_FIFODataReg);
                }
            }
        }
        else
        {
            status = MFRC_ERR;
        }
    }
​
    MFRC_SetBitMask(MFRC_ControlReg, 0x80);               //停止定时器运行
    MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE);            //取消当前命令的执行
​
    return status;
}
​
​
/**************************************************************************************
* 函数名称:PCD_Reset
* 功能描述:PCD复位
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void PCD_Reset(void)
{
    /*硬复位*/
    RS522_RST(1);//用到复位引脚
    osDelay(2);
    RS522_RST(0);
    osDelay(2);
    RS522_RST(1);
    osDelay(2);
​
    /*软复位*/
    MFRC_WriteReg(MFRC_CommandReg, MFRC_RESETPHASE);
    osDelay(2);
​
    /*复位后的初始化配置*/
    MFRC_WriteReg(MFRC_ModeReg, 0x3D);              //CRC初始值0x6363
    MFRC_WriteReg(MFRC_TReloadRegL, 30);            //定时器重装值
    MFRC_WriteReg(MFRC_TReloadRegH, 0);
    MFRC_WriteReg(MFRC_TModeReg, 0x8D);             //定时器设置
    MFRC_WriteReg(MFRC_TPrescalerReg, 0x3E);        //定时器预分频值
    MFRC_WriteReg(MFRC_TxAutoReg, 0x40);            //100%ASK
​
    PCD_AntennaOff();                               //关天线
    osDelay(2);
    PCD_AntennaOn();                                //开天线
}
​
​
/**************************************************************************************
* 函数名称:PCD_AntennaOn
* 功能描述:开启天线,使能PCD发送能量载波信号
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说    明:每次开启或关闭天线之间应至少有1ms的间隔
***************************************************************************************/
void PCD_AntennaOn(void)
{
    uint8_t temp;
    temp = MFRC_ReadReg(MFRC_TxControlReg);
    if (!(temp & 0x03))
    {
        MFRC_SetBitMask(MFRC_TxControlReg, 0x03);
    }
}
​
​
/**************************************************************************************
* 函数名称:PCD_AntennaOff
* 功能描述:关闭天线,失能PCD发送能量载波信号
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说    明:每次开启或关闭天线之间应至少有1ms的间隔
***************************************************************************************/
void PCD_AntennaOff(void)
{
    MFRC_ClrBitMask(MFRC_TxControlReg, 0x03);
}
​
​
/***************************************************************************************
* 函数名称:PCD_Init
* 功能描述:读写器初始化
* 入口参数:无
* 出口参数:无
* 返 回 值:无
* 说    明:无
***************************************************************************************/
void PCD_Init(void)
{
    MFRC_Init();      //MFRC管脚配置
    PCD_Reset();      //PCD复位  并初始化配置
    PCD_AntennaOff(); //关闭天线
    PCD_AntennaOn();   //开启天线
}
​
​
/***************************************************************************************
* 函数名称:PCD_Request
* 功能描述:寻卡
* 入口参数:-RequestMode:讯卡方式
*           PICC_REQIDL:寻天线区内未进入休眠状态
*           PICC_REQALL:寻天线区内全部卡
*           -pCardType:用于保存卡片类型
* 出口参数:-pCardType:卡片类型
*           0x4400:Mifare_UltraLight
*           0x0400:Mifare_One(S50)
*           0x0200:Mifare_One(S70)
*           0x0800:Mifare_Pro(X)
*           0x4403:Mifare_DESFire
​
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_Request(uint8_t RequestMode, uint8_t *pCardType)
{
    int status;
    uint16_t unLen;
    uint8_t CmdFrameBuf[MFRC_MAXRLEN];
​
    MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);//关内部温度传感器
    MFRC_WriteReg(MFRC_BitFramingReg, 0x07); //存储模式,发送模式,是否启动发送等
    MFRC_SetBitMask(MFRC_TxControlReg, 0x03);//配置调制信号13.56MHZ
​
    CmdFrameBuf[0] = RequestMode;
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 1, CmdFrameBuf, &unLen);
​
    if((status == PCD_OK) && (unLen == 0x10))
    {
        *pCardType = CmdFrameBuf[0];
        *(pCardType + 1) = CmdFrameBuf[1];
    }
​
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_Anticoll
* 功能描述:防冲突,获取卡号
* 入口参数:-pSnr:用于保存卡片序列号,4字节
* 出口参数:-pSnr:卡片序列号,4字节
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_Anticoll(uint8_t *pSnr)
{
    char status;
    uint8_t i, snr_check = 0;
    uint16_t  unLen;
    uint8_t CmdFrameBuf[MFRC_MAXRLEN];
​
    MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);
    MFRC_WriteReg(MFRC_BitFramingReg, 0x00);
    MFRC_ClrBitMask(MFRC_CollReg, 0x80);
​
    CmdFrameBuf[0] = PICC_ANTICOLL1;
    CmdFrameBuf[1] = 0x20;
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 2, CmdFrameBuf, &unLen);
​
    if(status == PCD_OK)
    {
        for(i = 0; i < 4; i++)
        {
            *(pSnr + i)  = CmdFrameBuf[i];
            snr_check ^= CmdFrameBuf[i];
        }
        if(snr_check != CmdFrameBuf[i])
        {
            status = PCD_ERR;
        }
    }
​
    MFRC_SetBitMask(MFRC_CollReg, 0x80);
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_Select
* 功能描述:选卡
* 入口参数:-pSnr:卡片序列号,4字节
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_Select(uint8_t *pSnr)
{
    char status;
    uint8_t i;
    uint16_t unLen;
    uint8_t CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = PICC_ANTICOLL1;
    CmdFrameBuf[1] = 0x70;
    CmdFrameBuf[6] = 0;
    for(i = 0; i < 4; i++)
    {
        CmdFrameBuf[i + 2] = *(pSnr + i);
        CmdFrameBuf[6]  ^= *(pSnr + i);
    }
    MFRC_CalulateCRC(CmdFrameBuf, 7, &CmdFrameBuf[7]);
​
    MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 9, CmdFrameBuf, &unLen);
​
    if((status == PCD_OK) && (unLen == 0x18))
    {
        status = PCD_OK;
    }
    else
    {
        status = PCD_ERR;
    }
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_AuthState
* 功能描述:验证卡片密码
* 入口参数:-AuthMode:验证模式
*           PICC_AUTHENT1A:验证A密码
*           PICC_AUTHENT1B:验证B密码
*           -BlockAddr:块地址(0~63)
*           -pKey:密码
*           -pSnr:卡片序列号,4字节
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:验证密码时,以扇区为单位,BlockAddr参数可以是同一个扇区的任意块
***************************************************************************************/
char PCD_AuthState(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr)
{
    char status;
    uint16_t unLen;
    uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
    CmdFrameBuf[0] = AuthMode;
    CmdFrameBuf[1] = BlockAddr;
    for(i = 0; i < 6; i++)
    {
        CmdFrameBuf[i + 2] = *(pKey + i);
    }
    for(i = 0; i < 4; i++)
    {
        CmdFrameBuf[i + 8] = *(pSnr + i);
    }
​
    status = MFRC_CmdFrame(MFRC_AUTHENT, CmdFrameBuf, 12, CmdFrameBuf, &unLen);
    if((status != PCD_OK) || (!(MFRC_ReadReg(MFRC_Status2Reg) & 0x08)))
    {
        status = PCD_ERR;
    }
​
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_WriteBlock
* 功能描述:读MF1卡数据块
* 入口参数:-BlockAddr:块地址
*           -pData: 用于保存待写入的数据,16字节
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_WriteBlock(uint8_t BlockAddr, uint8_t *pData)
{
    char status;
    uint16_t unLen;
    uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = PICC_WRITE;
    CmdFrameBuf[1] = BlockAddr;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
​
    if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
    {
        status = PCD_ERR;
    }
​
    if(status == PCD_OK)
    {
        for(i = 0; i < 16; i++)
        {
            CmdFrameBuf[i] = *(pData + i);
        }
        MFRC_CalulateCRC(CmdFrameBuf, 16, &CmdFrameBuf[16]);
​
        status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 18, CmdFrameBuf, &unLen);
​
        if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
        {
            status = PCD_ERR;
        }
    }
​
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_ReadBlock
* 功能描述:读MF1卡数据块
* 入口参数:-BlockAddr:块地址
*           -pData:         用于保存读出的数据,16字节
* 出口参数:-pData:      用于保存读出的数据,16字节
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_ReadBlock(uint8_t BlockAddr, uint8_t *pData)
{
    char status;
    uint16_t unLen;
    uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = PICC_READ;
    CmdFrameBuf[1] = BlockAddr;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
    if((status == PCD_OK) && (unLen == 0x90))
    {
        for(i = 0; i < 16; i++)
        {
            *(pData + i) = CmdFrameBuf[i];
        }
    }
    else
    {
        status = PCD_ERR;
    }
​
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_Value
* 功能描述:对MF1卡数据块增减值操作
* 入口参数:-BlockAddr:块地址
*           -pValue:四字节增值的值,低位在前
*           -mode:数值块操作模式
*           PICC_INCREMENT:增值
*           PICC_DECREMENT:减值
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_Value(uint8_t mode, uint8_t BlockAddr, uint8_t *pValue)
{
    //0XC1        1           Increment[4]={0x03, 0x01, 0x01, 0x01};
    char status;
    uint16_t unLen;
    uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = mode;
    CmdFrameBuf[1] = BlockAddr;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
​
    if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
    {
        status = PCD_ERR;
    }
​
    if(status == PCD_OK)
    {
        for(i = 0; i < 16; i++)
        {
            CmdFrameBuf[i] = *(pValue + i);
        }
        MFRC_CalulateCRC(CmdFrameBuf, 4, &CmdFrameBuf[4]);
        unLen = 0;
        status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 6, CmdFrameBuf, &unLen);
        if(status != PCD_ERR)
        {
            status = PCD_OK;
        }
    }
​
    if(status == PCD_OK)
    {
        CmdFrameBuf[0] = PICC_TRANSFER;
        CmdFrameBuf[1] = BlockAddr;
        MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
​
        status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
​
        if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
        {
            status = PCD_ERR;
        }
    }
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_BakValue
* 功能描述:备份钱包(块转存)
* 入口参数:-sourceBlockAddr:源块地址
*           -goalBlockAddr  :目标块地址
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:只能在同一个扇区内转存
***************************************************************************************/
char PCD_BakValue(uint8_t sourceBlockAddr, uint8_t goalBlockAddr)
{
    char status;
    uint16_t  unLen;
    uint8_t CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = PICC_RESTORE;
    CmdFrameBuf[1] = sourceBlockAddr;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
    if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
    {
        status = PCD_ERR;
    }
​
    if(status == PCD_OK)
    {
        CmdFrameBuf[0] = 0;
        CmdFrameBuf[1] = 0;
        CmdFrameBuf[2] = 0;
        CmdFrameBuf[3] = 0;
        MFRC_CalulateCRC(CmdFrameBuf, 4, &CmdFrameBuf[4]);
        status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 6, CmdFrameBuf, &unLen);
        if(status != PCD_ERR)
        {
            status = PCD_OK;
        }
    }
​
    if(status != PCD_OK)
    {
        return PCD_ERR;
    }
​
    CmdFrameBuf[0] = PICC_TRANSFER;
    CmdFrameBuf[1] = goalBlockAddr;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
    if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
    {
        status = PCD_ERR;
    }
​
    return status;
}
​
​
/***************************************************************************************
* 函数名称:PCD_Halt
* 功能描述:命令卡片进入休眠状态
* 入口参数:无
* 出口参数:无
* 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
* 说    明:无
***************************************************************************************/
char PCD_Halt(void)
{
    char status;
    uint16_t unLen;
    uint8_t CmdFrameBuf[MFRC_MAXRLEN];
​
    CmdFrameBuf[0] = PICC_HALT;
    CmdFrameBuf[1] = 0;
    MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
​
    status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
​
    return status;
}
​
​

rc522.h

#ifndef _RC522_H
#define _RC522_H
​
#include "main.h"
#include <stdint.h>
​
/*******************************************************************************
*                              rc522.c文件宏定义                                *
*********************************************************************************/
#define RC522_CS_GPIO_Port      GPIOA
#define RC522_CS_Pin                    GPIO_PIN_4//cs nss sda是一个东西
#define RC522_RST_GPIO_Port     GPIOA
#define RC522_RST_Pin                   GPIO_PIN_3
​
#define osDelay HAL_Delay
​
#define RS522_RST(N) HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, N==1?GPIO_PIN_SET:GPIO_PIN_RESET)
#define RS522_NSS(N) HAL_GPIO_WritePin(RC522_CS_GPIO_Port, RC522_CS_Pin, N==1?GPIO_PIN_SET:GPIO_PIN_RESET)
​
/***********************************************************************************
*                                           MFRC522驱动程序                                                                     *
************************************************************************************/
/*MFRC522寄存器定义*/
//PAGE0
#define MFRC_RFU00                      0x00    
#define MFRC_CommandReg                 0x01    
#define MFRC_ComIEnReg              0x02    
#define MFRC_DivlEnReg              0x03    
#define MFRC_ComIrqReg              0x04    
#define MFRC_DivIrqReg              0x05
#define MFRC_ErrorReg               0x06    
#define MFRC_Status1Reg             0x07    
#define MFRC_Status2Reg             0x08    
#define MFRC_FIFODataReg            0x09
#define MFRC_FIFOLevelReg           0x0A
#define MFRC_WaterLevelReg          0x0B
#define MFRC_ControlReg             0x0C
#define MFRC_BitFramingReg          0x0D
#define MFRC_CollReg                0x0E
#define MFRC_RFU0F                  0x0F
//PAGE1     
#define MFRC_RFU10                  0x10
#define MFRC_ModeReg                0x11
#define MFRC_TxModeReg              0x12
#define MFRC_RxModeReg              0x13
#define MFRC_TxControlReg           0x14
#define MFRC_TxAutoReg              0x15 //中文手册有误
#define MFRC_TxSelReg               0x16
#define MFRC_RxSelReg               0x17
#define MFRC_RxThresholdReg         0x18
#define MFRC_DemodReg               0x19
#define MFRC_RFU1A                  0x1A
#define MFRC_RFU1B                  0x1B
#define MFRC_MifareReg              0x1C
#define MFRC_RFU1D                  0x1D
#define MFRC_RFU1E                  0x1E
#define MFRC_SerialSpeedReg         0x1F
//PAGE2    
#define MFRC_RFU20                  0x20  
#define MFRC_CRCResultRegM          0x21
#define MFRC_CRCResultRegL          0x22
#define MFRC_RFU23                  0x23
#define MFRC_ModWidthReg            0x24
#define MFRC_RFU25                  0x25
#define MFRC_RFCfgReg               0x26
#define MFRC_GsNReg                 0x27
#define MFRC_CWGsCfgReg             0x28
#define MFRC_ModGsCfgReg            0x29
#define MFRC_TModeReg               0x2A
#define MFRC_TPrescalerReg          0x2B
#define MFRC_TReloadRegH            0x2C
#define MFRC_TReloadRegL            0x2D
#define MFRC_TCounterValueRegH      0x2E
#define MFRC_TCounterValueRegL      0x2F
//PAGE3      
#define MFRC_RFU30                  0x30
#define MFRC_TestSel1Reg            0x31
#define MFRC_TestSel2Reg            0x32
#define MFRC_TestPinEnReg           0x33
#define MFRC_TestPinValueReg        0x34
#define MFRC_TestBusReg             0x35
#define MFRC_AutoTestReg            0x36
#define MFRC_VersionReg             0x37
#define MFRC_AnalogTestReg          0x38
#define MFRC_TestDAC1Reg            0x39  
#define MFRC_TestDAC2Reg            0x3A   
#define MFRC_TestADCReg             0x3B   
#define MFRC_RFU3C                  0x3C   
#define MFRC_RFU3D                  0x3D   
#define MFRC_RFU3E                  0x3E   
#define MFRC_RFU3F                  0x3F
​
/*MFRC522的FIFO长度定义*/
#define MFRC_FIFO_LENGTH            64 
​
/*MFRC522传输的帧长定义*/
#define MFRC_MAXRLEN              18                
​
/*MFRC522命令集,中文手册P59*/
#define MFRC_IDLE                   0x00        //取消当前命令的执行
#define MFRC_CALCCRC                0x03    //激活CRC计算
#define MFRC_TRANSMIT               0x04    //发送FIFO缓冲区内容
#define MFRC_NOCMDCHANGE          0x07      //无命令改变
#define MFRC_RECEIVE                0x08    //激活接收器接收数据
#define MFRC_TRANSCEIVE             0x0C    //发送并接收数据
#define MFRC_AUTHENT                0x0E    //执行Mifare认证(验证密钥)
#define MFRC_RESETPHASE             0x0F    //复位MFRC522
​
/*MFRC522通讯时返回的错误代码*/
#define MFRC_OK                     (char)0
#define MFRC_NOTAGERR               (char)(-1)
#define MFRC_ERR                    (char)(-2)
​
/*MFRC522函数声明*/
void MFRC_Init(void);//初始化RC522
void MFRC_WriteReg(uint8_t addr, uint8_t data);//向RC522写寄存器
uint8_t MFRC_ReadReg(uint8_t addr);//读RC522寄存器
void MFRC_SetBitMask(uint8_t addr, uint8_t mask);//设置寄存器位
void MFRC_ClrBitMask(uint8_t addr, uint8_t mask);//清除寄存器位
void MFRC_CalulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData);//用MFRC计算CRC结果
char MFRC_CmdFrame(uint8_t cmd, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint16_t *pOutLenBit);//MFRC522和ISO14443A卡通讯的命令帧函数
​
/***********************************************************************************
*                           MFRC552与MF1卡通讯接口程序                                                                          *
************************************************************************************/
/*Mifare1卡片命令字*/
#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_TRANSFER           0xB0                //转存(传送)
#define PICC_RESTORE            0xC2                //恢复(重储)
#define PICC_HALT               0x50                //休眠
​
/*PCD通讯时返回的错误代码*/
#define PCD_OK                  (char)  0               //成功
#define PCD_NOTAGERR            (char)(-1)          //无卡
#define PCD_ERR                 (char)(-2)          //出错
​
/*PCD函数声明*/
void PCD_Init(void);//初始化PCD
void PCD_Reset(void);//复位PCD
void PCD_AntennaOn(void);//打开天线
void PCD_AntennaOff(void);//关闭天线
char PCD_Request(uint8_t RequestMode, uint8_t *pCardType);//寻卡,并返回卡的类型
char PCD_Anticoll(uint8_t *pSnr);//防冲突,返回卡号
char PCD_Select(uint8_t *pSnr);//选卡
char PCD_AuthState(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr); //验证密码(密码A和密码B)   
char PCD_WriteBlock(uint8_t BlockAddr, uint8_t *pData); //写数据
char PCD_ReadBlock(uint8_t BlockAddr, uint8_t *pData);  //读数据
char PCD_Value(uint8_t mode, uint8_t BlockAddr, uint8_t *pValue);   
char PCD_BakValue(uint8_t sourceBlockAddr, uint8_t goalBlockAddr); //备份卡                                
char PCD_Halt(void);//进入休眠状态
void StartIDcardTask(void const * argument);//启动ID卡任务
​
#endif
​

rfid.c

#include "rfid.h"
#include "rc522.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
​
​
int RFID_WritFlag = 0;//写RFID标志位
char RFID_FLAG = PCD_ERR;//RFID状态
uint8_t RFID_WriteData[16] = "1234567890ABCDEF";//需要写入IC卡内的数据
uint8_t key_A[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//密钥A
uint8_t key_B[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//密钥B
​
/*******************************************************************************
  *函数名      :RFID_Handl  RFID处理
  *补充           :此函数只做RFID逻辑处理
  *作者       :Li Xunjiu
*********************************************************************************/
void RFID_Handl(void)
{
    uint8_t CardType[4];//卡类型
  uint8_t Card_ID[4];//卡ID
    char RFID_ReadData[16];//读取卡内的数据
​
    
    RFID_FLAG = PCD_Request(PICC_REQIDL, CardType);//返回值为0,代表寻卡成功;并把卡类型存入CardType中
    if(RFID_FLAG == PCD_OK)
    {
        RFID_FLAG = PCD_ERR;
        
            AntiCollision(Card_ID);//进行防冲撞及获取ID
            
            SIM_Card(Card_ID);//选卡
            
            Key_Verification(PICC_AUTHENT1A,7,key_A,Card_ID);//验证
        
            WriteCard(6,RFID_WriteData);//写卡
        
            ReadCard(6,(uint8_t *)RFID_ReadData);//读卡
            
            PCD_Halt();//RFID进入休眠
        
            memset(Card_ID, 0, sizeof(Card_ID));//清空字符串
            memset(RFID_WriteData, 0, sizeof(RFID_WriteData));//清空字符串
            memset(RFID_ReadData, 0, sizeof(RFID_ReadData));//清空字符串
            HAL_Delay(1000);
    }
    HAL_Delay(100);
    return;
}
​
/*******************************************************************************
  * 函数名 :convertToUpper
  *函数参数 :str ->需要更改大小写的数组
  *补充           :将数组内的元素大写
  *作者       :Li Xunjiu
*********************************************************************************/
void convertToUpper(uint8_t *str) 
{
    int i = 0;
    while (str[i]) 
        {
        str[i] = toupper(str[i]);
        i++;
    }
}
/*******************************************************************************
  * 函数名 :SIM_Card 选择卡
  *函数参数 :cardID ->卡号ID
  *作者       :Li Xunjiu
*********************************************************************************/
void SIM_Card(uint8_t * cardID)
{
    RFID_FLAG = PCD_Select(cardID);//选卡
    if(RFID_FLAG == PCD_OK)
        {
                RFID_FLAG = PCD_ERR;
                printf("选卡成功\r\n");
                return;
        }
    else
        {
                printf("选卡失败\r\n");
                return;
        }
}
​
/*******************************************************************************
  * 函数名 :AntiCollision 防冲撞并获取卡ID
  *函数参数 :readUid 读取RFID的卡号
  *作者       :Li Xunjiu
*********************************************************************************/
​
void AntiCollision(uint8_t * cardID)
{
    RFID_FLAG = PCD_Anticoll(cardID);   //防冲撞,完成这步就可以简单地读取卡号,本次不涉及更高层次应用
    if(RFID_FLAG == PCD_OK)
    {
            char CardTem[4];
            RFID_FLAG = PCD_ERR;
            sprintf(CardTem,"%x%x%x%x",cardID[0],cardID[1],cardID[2],cardID[3]);
            convertToUpper((uint8_t *) CardTem);
            printf("ID=%s\r\n",(uint8_t *)CardTem);
        
            return;
    }
    
}
​
/*******************************************************************************
  * 函数名 :Key_Verification 密钥验证
  *函数参数 :authmode ->密钥验证模式(A或是B)
    *                    addr ->密钥验证地址(每个扇区的区块3)
    *          key  ->验证的密钥值
    *          UID  ->卡的序列号(4位)
  *作者       :Li Xunjiu
*********************************************************************************/
void Key_Verification(uint8_t authmode,uint8_t addr,uint8_t * key,uint8_t * UID)
{
​
    RFID_FLAG = PCD_AuthState(authmode, addr, key, UID);//解密
    if(RFID_FLAG == PCD_OK)
    {
            RFID_FLAG = PCD_ERR;
            printf("密钥验证成功\r\n");
            return;
    }
    else
    {
            printf("密钥验证成功\r\n");
            return;
    }
}
​
/*******************************************************************************
  * 函数名 :WriteCard 向IC卡内写数据
  *函数参数 :addr ->需要写入数据的区块地址
    *          RFID_WriteData ->需要写入的数据
  *作者       :Li Xunjiu
*********************************************************************************/
void WriteCard(uint8_t addr,uint8_t *RFID_WriteData)
{
    if(RFID_WritFlag == 1)
    {
        uint8_t EmptyStr[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        PCD_WriteBlock(addr,(uint8_t *)EmptyStr);
        printf("数据块已清空,开始写入新数据!\r\n");
        
        RFID_FLAG = PCD_WriteBlock(addr, (uint8_t *)RFID_WriteData);//写卡
        if(RFID_FLAG == PCD_OK)
            {
                    RFID_FLAG = PCD_ERR;
                    printf("写卡成功\r\n");
                    RFID_WritFlag = 0;
                    return;
            }
        else
            {
                    printf("写卡失败:%d\r\n",RFID_FLAG);
                    RFID_WritFlag = 0;
                    return;
            }
    }
    else printf("未开启RFID写标志!\r\n");
    
    RFID_WritFlag = 0;
    return;
}
​
/*******************************************************************************
  * 函数名 :ReadCard 读取卡的数据
  *函数参数 :addr ->需要读的区块地址0~15(8扇区每个扇区4个数据块一个数代表一个数据块)
    *                    RFID_ReadData ->卡内读出的数据
  *作者       :Li Xunjiu
*********************************************************************************/
void ReadCard(uint8_t addr,uint8_t *RFID_ReadData)
{
    char RFID_FLAG = PCD_ERR;
    
    RFID_FLAG = PCD_ReadBlock(addr, RFID_ReadData);//读卡
    if(RFID_FLAG == PCD_OK)
    {
            RFID_FLAG = PCD_ERR;
            printf("读卡成功:%s\r\n",(char *) RFID_ReadData);//这里输出的数据后面后跟所读数据的卡号
            HAL_Delay(500);
            return;
    }
    else
    {
            printf("读卡失败:%d\r\n",RFID_FLAG);
            return;
    }
    
}
​

rfid.h

#ifndef _RFID_H
#define _RFID_H
​
#include "main.h"
​
extern int RFID_WritFlag;
extern char RFID_FLAG;
​
extern uint8_t key_A[6];
extern uint8_t key_B[6];
extern uint8_t RFID_WriteData[16];
​
void RFID_Handl(void);//RFID处理函数
​
void convertToUpper(uint8_t *str); //将字符格式标注仅大写
​
void SIM_Card(uint8_t * cardID);//选卡
​
void AntiCollision(uint8_t * cardID);//防冲撞及获取ID
​
void Key_Verification(uint8_t authmode,uint8_t addr,uint8_t * key,uint8_t * UID);//验证密钥
​
void WriteCard(uint8_t addr,uint8_t *RFID_WriteData);//向卡内写入数据
​
void ReadCard(uint8_t addr,uint8_t *RFID_ReadData);//读卡数据
uint8_t RFIDReadCard(uint8_t *readUid, uint8_t *cardID);
​
​
​
#endif
​
​
​
​

usart.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
​
/* USER CODE BEGIN 0 */
#include "rfid.h"
​
int UartDataReceived = 0;//串口开启标志位
int UartFalg = 0;//串口接收数据标志
int UartRxLen =0;//串口接收数据长度
uint8_t Uart_Rx_Buf[1];//串口接收缓冲
uint8_t UartData[300];//串口数据
/* USER CODE END 0 */
​
UART_HandleTypeDef huart1;
​
/* USART1 init function */
​
void MX_USART1_UART_Init(void)
{
​
  /* USER CODE BEGIN USART1_Init 0 */
​
  /* USER CODE END USART1_Init 0 */
​
  /* USER CODE BEGIN USART1_Init 1 */
​
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
    __enable_irq();//使能串口中断
    HAL_UART_Receive_IT(&huart1, (uint8_t *)Uart_Rx_Buf, 1);
    
  /* USER CODE END USART1_Init 2 */
​
}
​
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
​
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */
​
  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
​
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
​
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
​
    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */
​
  /* USER CODE END USART1_MspInit 1 */
  }
}
​
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
​
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */
​
  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();
​
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
​
    /* USART1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */
​
  /* USER CODE END USART1_MspDeInit 1 */
  }
}
​
/* USER CODE BEGIN 1 */
/*******************************************************************************
  * 函数名 :printf
  *功能描述:输出函数
  *函数参数:ch,*p
  * 返回值 :ch
  *补充说明:该函数是标准库stdio.h内的输出函数,在这只是重定向其输出方向
  *作者    :Li Xunjiu
*********************************************************************************/
int fputc(int ch,FILE *p)
{
    char c = ch;
    HAL_UART_Transmit(&huart1,(unsigned char *)&c, 1, 50);
    return ch;
}
/*******************************************************************************
  * 函数名 :HAL_UART_RxCpltCallback
  *功能描述:串口回调函数
  *函数参数:
  * 返回值 :无
  *补充说明:该函数是HAL库内的函数,只是在这重写了
  *作者    :Li Xunjiu
*********************************************************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uint8_t Uart_Data_Buf[300];//串口数据缓冲
    
    
    if (huart == &huart1) // 处理串口1的数据
    {
        UartDataReceived = 1;//开启串标志位
            
        UartFalg++; //每接收到一个数据,进入回调数据长度加1
        Uart_Data_Buf[UartFalg-1] = Uart_Rx_Buf[0]; //把每次接收到的数据保存到缓存数组
​
        if (Uart_Data_Buf[UartFalg-1]== ';')//接收结束标志判断
        {
            memcpy(UartData, Uart_Data_Buf, UartFalg * sizeof(uint8_t)); //将数组Uart_Data_Buf中的数据转交给Uart_Data
                    
            memset(Uart_Data_Buf, 0, sizeof(Uart_Data_Buf)); //清空缓存数组
                    
            UartRxLen = UartFalg; //将UartFalg的值赋给UartRxLen
                    
            UartFalg = 0; //清空接收标志
        }
​
        Uart_Rx_Buf[0] = 0; //重置接收缓冲
​
        // 每接收一个数据,打开一次串口中断接收,否则只会接收一个数据就停止接收
        HAL_UART_Receive_IT(&huart1, (uint8_t *)Uart_Rx_Buf, 1);
    }
}
​
​
/*******************************************************************************
  * 函数名 :USART_Handl
  *功能描述:串口数据处理
  *函数参数:无
  * 返回值 :无
  *补充说明:该函数只做接收的的函数处理,所有串口数据皆在该函数内进行,外部只需调用即可
  *作者    :Li Xunjiu
*********************************************************************************/
void USART_Handl(void)
{
    if(UartDataReceived == 0)//串口标志未开启
    {
        HAL_UART_Receive_IT(&huart1, (uint8_t *)Uart_Rx_Buf, 1);
    }
    
    if(UartDataReceived == 1)//串口标志已开启
    {
        printf("串口开启接收数据成功!\r\n");
        if(memcmp(UartData, "Set_CardData:", 13) == 0)
        {
            if(UartRxLen-14<=16)
            {
                RFID_WritFlag = 1;//开启RFID写标志
                for(int i = 0;i<UartRxLen-14;i++)
                {
                    RFID_WriteData[i]=UartData[i+13];
                }
                printf("数据获取完成开始写数据:%s\r\n",RFID_WriteData);
                RFID_Handl();
            }
            else printf("只支持16位数据修改,您的数据不合法!\n\r");
            
        }
        UartDataReceived = 0;
    }
    return;
}
​
/* USER CODE END 1 */
​

main.c(注意:main.c这个文件因为cobe生成的代码太多部分以删除)

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
​
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "rc522.h"
#include "rfid.h"
/* USER CODE END Includes */
​
int main(void)
{
  /* USER CODE BEGIN 1 */
​
  /* USER CODE END 1 */
​
  /* MCU Configuration--------------------------------------------------------*/
​
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
​
  /* USER CODE BEGIN Init */
​
  /* USER CODE END Init */
​
  /* Configure the system clock */
  SystemClock_Config();
​
  /* USER CODE BEGIN SysInit */
    PCD_Init();//初始化RC522
  /* USER CODE END SysInit */
​
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
    LED0 = 0;
    LED1 = 1;
    
    printf("初始化完成,程序开始运行中...\r\n");
  /* USER CODE END 2 */
​
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        //USART_Handl();//串口处理函数
        
        RFID_Handl();//RFID处理函数
        
    /* USER CODE END WHILE */
​
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
​

最终实验现象

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于使用STM32F103RCT6RFID-RC522的示例程序,您可以参考以下步骤: 1. 首先,确保您已经配置好STM32F103RCT6开发环境,包括安装好Keil MDK软件和相应的STM32Cube库。 2. 下载并安装RFID-RC522的库文件。您可以在GitHub或其他资源网站上找到适用于STM32RFID-RC522库。确保选择与您的开发环境兼容的版本。 3. 创建一个新的Keil项目,并配置正确的芯片型号(STM32F103RCT6)和时钟设置。 4. 将RFID-RC522库文件添加到您的项目中。将库文件中提供的源代码和头文件复制到您的项目目录中,并在Keil中添加这些文件到您的项目中。 5. 根据您的硬件连接,配置GPIO引脚和SPI接口。确保正确连接RFID-RC522模块STM32开发板,并通过SPI接口进行通信。 6. 在主程序中,初始化SPI接口并使用RFID-RC522库提供的函数来初始化RFID模块。这些函数通常包括初始化SPI、设置IO口方向和模式、复位模块等。 7. 通过调用RFID-RC522库中的函数,实现读取和写入RFID卡的功能。例如,您可以使用函数来检测卡片是否存在、读取卡片UID、读取或写入卡片数据等。 8. 编译和烧录程序到STM32F103RCT6开发板上。 请注意,以上步骤仅提供了一个大致的指导。具体的实现过程可能因您所选择的库和硬件连接方式而有所不同。确保阅读并遵循RFID-RC522库的文档和示例程序以获取更详细的指导。 祝您成功使用STM32F103RCT6RFID-RC522!如果您有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值