本帖最后由 李浔玖 于 2023-8-30 17:35 编辑  
 
基于STM32F103RCT6(HAL库)+RC522RFID模块开发读写模块  
 
首先准备好需要使用的硬件设备: 正点原子MiniSTM32开发板一块, MiniRFID-RC522模块一个, 杜邦线七条, miniUSB线一条, ST_Link一个(ST_Link是需要一根miniUSB线与20pin接口线的,也可采用4条杜邦线连接;也可换为J_Link),M1白卡一张,  
 STM32 Cobe MX配置: 配置外部时钟72M 配置引脚: PA3->input PA4->output PD2->output PA8->outpu 配置SPI1默认引脚,打开中断,Parameter Settings界面下Prescaile(for Baud Rate)配置为16 配置USART1默认引脚,打开中断 然后就正常生成代码.  
 
 
 
 
代码部分: 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); 
    } 
    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 = 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; 
            snr_check ^= CmdFrameBuf; 
        } 
        if(snr_check != CmdFrameBuf) 
        { 
            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 = *(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; 
        } 
    } 
    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 = *(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逻辑处理 
  *作者        i 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 ->需要更改大小写的数组 
  *补充           :将数组内的元素大写 
  *作者        i Xunjiu 
*********************************************************************************/ 
void convertToUpper(uint8_t *str)  
{ 
    int i = 0; 
    while (str)  
        { 
        str = toupper(str); 
        i++; 
    } 
} 
/******************************************************************************* 
  * 函数名 :SIM_Card 选择卡 
  *函数参数 :cardID ->卡号ID 
  *作者        i 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的卡号 
  *作者        i 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位) 
  *作者        i 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 ->需要写入的数据 
  *作者        i 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 ->卡内读出的数据 
  *作者        i 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内的输出函数,在这只是重定向其输出方向 
  *作者     i 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库内的函数,只是在这重写了 
  *作者     i 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 
  *功能描述:串口数据处理 
  *函数参数:无 
  * 返回值 :无 
  *补充说明:该函数只做接收的的函数处理,所有串口数据皆在该函数内进行,外部只需调用即可 
  *作者     i 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=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 */ 
} 
​最终实验现象  
 
 |