CC2640R2F学习笔记(23)——RFID RC522使用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36347513/article/details/100094162

一、硬件连接

功能口 引脚
MISO DIO_8
MOSI DIO_9
CLK DIO_10
CSN DIO_11
RST DIO_1

二、添加SPI驱动

查看 CC2640R2F学习笔记(22)——SPI接口使用

三、移植文件

链接:https://pan.baidu.com/s/1ztR1SZrRsv7Bxhj1Vnpbaw 提取码:lasq
rc522.crc522.h 两个文件拖拽至CCS工程的Application文件夹下

添加文件过程中,选项选择如下

3.1 rc522.c

/*********************************************************************
 * INCLUDES
 */
#include <string.h>
#include <stdio.h>

#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>
#include <ti/devices/cc26x0r2/driverlib/cpu.h>
#include <ti/sysbios/knl/Clock.h>
#include "board.h"
#include "util.h"

#include "board_spi.h"
#include "board_uart.h"
#include "rc522.h"

static void rstPinInit(void);
static void rstPinSet(PIN_Id pinId, bool pinState);
static void irqCallback(PIN_Handle pinHandle, PIN_Id pinId);
static void irqChangeHandler(UArg arg);
static char pcdRequest(uint8_t reqCode, uint8_t *pTagType);
static char pcdAnticoll(uint8_t *pSnr);
static char pcdSelect(uint8_t *pSnr);
static char pcdAuthState(uint8_t authMode, uint8_t addr, uint8_t *pKey, uint8_t *pSnr);
static char pcdRead(uint8_t addr, uint8_t *pData);
static char pcdWrite(uint8_t addr, uint8_t *pData);
static void pcdReset(void);
static void calulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData);
static char pcdComMF522(uint8_t command, uint8_t *pInData, uint8_t inLenByte, uint8_t *pOutData, uint32_t *pOutLenBit);
static void pcdAntennaOn(void);
static void pcdAntennaOff(void);
static void setBitMask(uint8_t reg, uint8_t mask);
static void clearBitMask(uint8_t reg, uint8_t mask);
static uint8_t readRawRc(uint8_t addr);
static void writeRawRc(uint8_t addr, uint8_t writeData);
static void delayMs(uint8_t time);

/*********************************************************************
 * LOCAL VARIABLES
 */
// RST引脚配置
static PIN_State s_rc522RstState;
static PIN_Handle s_rc522RstHandle;
static PIN_Config s_rc522RstPinsCfg[] =
{
    RC522_RST_IO | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,
    PIN_TERMINATE
};

// IRQ引脚配置
static PIN_State s_rc522IrqState;
static PIN_Handle s_rc522IrqHandle;
static PIN_Config s_rc522IrqPinsCfg[] =
{
    RC522_IRQ_IO | PIN_GPIO_OUTPUT_DIS | PIN_INPUT_EN | PIN_PULLDOWN,
    PIN_TERMINATE
};
static uint8_t s_irqValue;                                                      // 中断值
static Clock_Struct s_irqChangeClock;                                           // 中断消抖时钟
static IrqCallback_t s_appIrqChangeHandler = NULL;                              // 对应应用层回调函数的函数指针

static uint8_t s_cardType[2];                                                   // 卡类型
static uint8_t s_cardSerialNo[4];                                               // 卡序列号

static uint8_t s_defaultKeyA[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};         // 默认密码A

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/**
 @brief RC522的初始化函数
 @param 无
 @return 无
*/
void RC522_Init(void)
{
    SPI_Init();                                                                 // SPI初始化
    rstPinInit();                                                               // 复位引脚初始化
    pcdReset();                                                                 // 复位

    delayMs(5);
    pcdAntennaOn();                                                             // 开启天线发射
}

/**
 @brief RC522中断初始化函数
 @param appIrqCB -[in] 中断回调函数
 @return 无
*/
void RC522_irqInit(IrqCallback_t appIrqCB)
{
    s_rc522IrqHandle = PIN_open(&s_rc522IrqState, s_rc522IrqPinsCfg);           // 初始化中断的IO

    PIN_registerIntCb(s_rc522IrqHandle, irqCallback);                           // 注册回调函数

    // 修改成双沿中断触发,以避免睡眠之后中断不灵
    PIN_setConfig(s_rc522IrqHandle, PIN_BM_IRQ, RC522_IRQ_IO | PIN_IRQ_BOTHEDGES);  // PIN_IRQ_NEGEDGE

#ifdef POWER_SAVING                                                             // 低功耗下的配置
    PIN_setConfig(s_rc522IrqHandle, PINCC26XX_BM_WAKEUP, RC522_IRQ_IO | PINCC26XX_WAKEUP_NEGEDGE);
#endif // POWER_SAVING
                                                                                // 初始化按键定时事件
    Util_constructClock(&s_irqChangeClock, irqChangeHandler, IRQ_DEBOUNCE_TIMEOUT, 0, false, 0);

    s_appIrqChangeHandler = appIrqCB;                                           // 保存应用层的函数指针
}

/**
 @brief RC522读取卡片块数据
 @param addr -[in] 块地址
 @return 状态值,0 - 成功;2 - 无卡;3 - 防冲撞失败;4 - 选卡失败;5 - 密码错误
*/
uint8_t RC522_ReadCardDataBlock(uint8_t addr)
{
    memset(s_cardSerialNo, 0, 4);

    if(pcdRequest(PICC_REQALL, s_cardType) == MI_OK)
    {
    }
    else
    {
        return 2;                                                               // 无卡
    }

    if(pcdAnticoll(s_cardSerialNo) == MI_OK)
    {
    }
    else
    {
        return 3;                                                               // 防冲撞失败
    }

    if(pcdSelect(s_cardSerialNo) == MI_OK)
    {
    }
    else
    {
        return 4;                                                               // 选卡失败
    }

    if(pcdAuthState(0x60, addr, s_defaultKeyA, s_cardSerialNo) == MI_OK)
    {
        return 0;
    }
    else
    {
        return 5;                                                               // 密码错误
    }
}

/*********************************************************************
 * LOCAL FUNCTIONS
 */

/**
 @brief RC522的RST引脚初始化
 @param 无
 @return 无
*/
static void rstPinInit(void)
{
    s_rc522RstHandle = PIN_open(&s_rc522RstState, s_rc522RstPinsCfg);
}

/**
 @brief RC522的RST引脚设置
 @param pinId -[in] 引脚号
 @param pinState -[in] 引脚状态
 @return 无
*/
static void rstPinSet(PIN_Id pinId, bool pinState)
{
    if(pinState == RC522_RST_OFF)
    {
        PIN_setOutputValue(s_rc522RstHandle, pinId, 1);
    }
    else if(pinState == RC522_RST_ON)
    {
        PIN_setOutputValue(s_rc522RstHandle, pinId, 0);
    }
}

/**
 @brief IRQ中断回调函数
 @param pinHandle -[in] 引脚句柄
 @param pinId -[in] 引脚号
 @return 无
*/
static void irqCallback(PIN_Handle pinHandle, PIN_Id pinId)
{
    s_irqValue = 0;                                                             // 清除中断值

    if(PIN_getInputValue(RC522_IRQ_IO) == RC522_IRQ_ON)                         // 判断卡片是否接近
    {
        s_irqValue |= 0x0001;                                                   // 保存键值
    }

    Util_startClock(&s_irqChangeClock);                                         // 启动定时器进行消抖
}

/**
 @brief IRQ中断的消抖处理函数
 @param 无
 @return 无
*/
static void irqChangeHandler(UArg arg)
{
    if(s_appIrqChangeHandler != NULL)                                           // 判断是否有注册
    {
        if(PIN_getInputValue(RC522_IRQ_IO) == RC522_IRQ_ON)                     // 消抖
        {
            s_irqValue |= 0x0001;
        }

        (*s_appIrqChangeHandler)(s_irqValue);                                   // 调用中断应用层处理函数
    }
}

/**
 @brief 寻卡
 @param reqCode -[in] 寻卡方式,0x52 寻感应区内所有符合1443A标准的卡,0x26 寻未进入休眠状态的卡
 @param pTagType -[out] 卡片类型代码
                        0x4400 = Mifare_UltraLight
                        0x0400 = Mifare_One(S50)
                        0x0200 = Mifare_One(S70)
                        0x0800 = Mifare_Pro(X)
                        0x4403 = Mifare_DESFire
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdRequest(uint8_t reqCode, uint8_t *pTagType)
{
    char status;
    uint32_t len;
    uint8_t comMF522Buf[MAXRLEN];

    clearBitMask(Status2Reg, 0x08);
    writeRawRc(BitFramingReg, 0x07);
    setBitMask(TxControlReg, 0x03);

    comMF522Buf[0] = reqCode;

    status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 1, comMF522Buf, &len);    // 发送并接收数据
    if((status == MI_OK) && (len == 0x10))
    {
        *pTagType = comMF522Buf[0];
        *(pTagType+1) = comMF522Buf[1];
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}

/**
 @brief 防冲撞
 @param pSnr -[out] 卡片序列号,4字节
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdAnticoll(uint8_t *pSnr)
{
    char status;
    uint8_t i, snrCheck = 0;
    uint32_t len;
    uint8_t comMF522Buf[MAXRLEN];

    clearBitMask(Status2Reg, 0x08);             // 寄存器包含接收器和发送器和数据模式检测器的状态标志
    writeRawRc(BitFramingReg, 0x00);            // 不启动数据发送,接收的LSB位存放在位0,接收到的第二位放在位1,定义发送的最后一个字节位数为8
    clearBitMask(CollReg, 0x80);                // 所有接收的位在冲突后将被清除

    comMF522Buf[0] = PICC_ANTICOLL1;
    comMF522Buf[1] = 0x20;

    status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 2, comMF522Buf, &len);

    if(status == MI_OK)
    {
        for(i = 0; i < 4; i++)
        {
            *(pSnr + i) = comMF522Buf[i];
            snrCheck ^= comMF522Buf[i];
        }
        if(snrCheck != comMF522Buf[i])          // 返回四个字节,最后一个字节为校验位
        {
            status = MI_ERR;
        }
    }

    setBitMask(CollReg, 0x80);

    return status;
}

/**
 @brief 选定卡片
 @param pSnr -[in] 卡片序列号,4字节
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdSelect(uint8_t *pSnr)
{
    char status;
    uint8_t i;
    uint8_t comMF522Buf[MAXRLEN];
    uint32_t len;

    comMF522Buf[0] = PICC_ANTICOLL1;
    comMF522Buf[1] = 0x70;
    comMF522Buf[6] = 0;

    for(i = 0; i < 4; i++)
    {
        comMF522Buf[i + 2] = *(pSnr + i);
        comMF522Buf[6] ^= *(pSnr + i);
    }

    calulateCRC(comMF522Buf, 7, &comMF522Buf[7]);

    clearBitMask(Status2Reg, 0x08);

    status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 9, comMF522Buf, &len);

    if((status == MI_OK ) && (len == 0x18))
    {
        status = MI_OK;
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}

/**
 @brief 验证卡片密码
 @param authMode -[in] 密码验证模式,0x60 验证A密钥,0x61 验证B密钥
 @param addr -[in] 块地址
 @param pKey -[in] 密码
 @param pSnr -[in] 卡片序列号,4字节
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdAuthState(uint8_t authMode, uint8_t addr, uint8_t *pKey, uint8_t *pSnr)
{
    char status;
    uint8_t i, comMF522Buf[MAXRLEN];
    uint32_t len;

    comMF522Buf[0] = authMode;
    comMF522Buf[1] = addr;

    for(i = 0; i < 6; i++)
    {
        comMF522Buf[i + 2] = *(pKey + i);
    }

    for(i = 0; i < 6; i++)
    {
        comMF522Buf[i + 8] = *(pSnr + i);
    }

    status = pcdComMF522(PCD_AUTHENT, comMF522Buf, 12, comMF522Buf, &len);

    if((status != MI_OK ) || ( ! (readRawRc(Status2Reg) & 0x08)))
    {
        status = MI_ERR;
    }

    return status;
}

/**
 @brief 读取M1卡一块数据
 @param addr -[in] 块地址
 @param pData -[out] 读出的数据,16字节
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdRead(uint8_t addr, uint8_t *pData)
{
    char status;
    uint8_t i, comMF522Buf[MAXRLEN];
    uint32_t len;

    comMF522Buf[0] = PICC_READ;
    comMF522Buf[1] = addr;

    calulateCRC(comMF522Buf, 2, &comMF522Buf[2]);

    status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 4, comMF522Buf, &len);

    if((status == MI_OK) && (len == 0x90))
    {
        for(i = 0; i < 16; i++)
        {
            *(pData + i) = comMF522Buf[i];
        }
    }
    else
    {
        status = MI_ERR;
    }

    return status;
}

/**
 @brief 写入M1卡一块数据
 @param addr -[in] 块地址
 @param pData -[out] 写入的数据,16字节
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdWrite(uint8_t addr, uint8_t *pData)
{
    char status;
    uint8_t i, comMF522Buf[MAXRLEN];
    uint32_t len;

    comMF522Buf[0] = PICC_WRITE;
    comMF522Buf[1] = addr;

    calulateCRC(comMF522Buf, 2, &comMF522Buf[2]);

    status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 4, comMF522Buf, &len);
    if((status != MI_OK) || (len != 4) || ((comMF522Buf[0] & 0x0F) != 0x0A))
    {
        status = MI_ERR;
    }

    if(status == MI_OK)
    {
        for(i = 0; i < 16; i++)
        {
            comMF522Buf[i] = *(pData + i);
        }
        calulateCRC(comMF522Buf, 16, &comMF522Buf[16]);

        status = pcdComMF522(PCD_TRANSCEIVE, comMF522Buf, 18, comMF522Buf, &len);
        if((status != MI_OK) || (len != 4) || ((comMF522Buf[0] & 0x0F) != 0x0A))
        {
            status = MI_ERR;
        }
    }

    return status;
}

/**
 @brief 复位RC522
 @return 无
*/
static void pcdReset(void)
{
    // 需先保持高电平,后给个下降沿
    RC522_RST_LOW;
    delayMs(5);
    RC522_RST_HIGH;
    delayMs(10);

    writeRawRc(CommandReg, PCD_RESETPHASE);                                     // 和MI卡通讯,CRC初始值0x6363
    delayMs(1);
    writeRawRc(ModeReg, 0x3D);
    writeRawRc(TReloadRegL, 30);
    writeRawRc(TReloadRegH, 0);
    writeRawRc(TModeReg, 0x8D);
    writeRawRc(TPrescalerReg, 0x3E);

    writeRawRc(TxASKReg, 0x40);
}

/**
 @brief 用MF522计算CRC16
 @param pInData -[in] 计算CRC16的数组
 @param len -[in] 计算CRC16的数组字节长度
 @param pOutData -[out] 存放计算结果存放的首地址
 @return 无
*/
static void calulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData)
{
    uint8_t i, n;

    clearBitMask(DivIrqReg, 0x04);
    writeRawRc(CommandReg, PCD_IDLE);
    setBitMask(FIFOLevelReg, 0x80);

    for(i = 0; i < len; i++)
    {
        writeRawRc(FIFODataReg, *(pInData + i));
    }

    writeRawRc(CommandReg, PCD_CALCCRC);

    i = 0xFF;

    do
    {
        n = readRawRc(DivIrqReg);
        i--;
    }
    while((i != 0) && ! (n & 0x04));

    pOutData[0] = readRawRc(CRCResultRegL);
    pOutData[1] = readRawRc(CRCResultRegM);
}

/**
 @brief 通过RC522和ISO14443卡通讯
 @param command -[in] RC522命令字
 @param pInData -[in] 通过RC522发送到卡片的数据
 @param inLenByte -[in] 发送数据的字节长度
 @param pOutData -[out] 接收到的卡片返回数据
 @param pOutLenBit -[out] 返回数据的位长度
 @return 状态值,MI OK - 成功;MI_ERR - 失败
*/
static char pcdComMF522(uint8_t command, uint8_t *pInData, uint8_t inLenByte, uint8_t *pOutData, uint32_t *pOutLenBit)
{
    char status = MI_ERR;
    uint8_t irqEn = 0x00;
    uint8_t waitFor = 0x00;
    uint8_t lastBits;
    uint8_t n;
    uint32_t i;
    uint8_t j;

    switch(command)
    {
    case PCD_AUTHENT:
        irqEn = 0x12;
        waitFor = 0x10;
        break;
    case PCD_TRANSCEIVE:
        irqEn = 0x77;
        waitFor = 0x30;
        break;
    default:
        break;
    }

    writeRawRc(ComIEnReg, irqEn | 0x80);
    clearBitMask(ComIrqReg, 0x80);
    writeRawRc(CommandReg, PCD_IDLE);
    setBitMask(FIFOLevelReg, 0x80);                                             // 清空FIFO

    for(i = 0; i < inLenByte; i++)
    {
        writeRawRc(FIFODataReg, pInData[i]);                                    // 数据写入FIFO
    }
    writeRawRc(CommandReg, command);                                            // 命令写入命令寄存器

    if(command == PCD_TRANSCEIVE)
    {
        setBitMask(BitFramingReg, 0x80);                                        // 开始发送
    }

    i = 6000;                                                                   // 根据时钟频率调整,操作M1卡最大等待时间25ms
    do
    {
        n = readRawRc(ComIrqReg);
        i--;
    }
    while((i != 0) && !(n & 0x01) && !(n & waitFor));
    clearBitMask(BitFramingReg, 0x80);

    if(i != 0)
    {
        j = readRawRc(ErrorReg);
        if(!(j & 0x1B))
        {
            status = MI_OK;
            if(n & irqEn & 0x01)
            {
                status = MI_NOTAGERR;
            }
            if(command == PCD_TRANSCEIVE)
            {
                n = readRawRc(FIFOLevelReg);
                lastBits = readRawRc(ControlReg) & 0x07;
                if(lastBits)
                {
                    *pOutLenBit = (n - 1) * 8 + lastBits;
                }
                else
                {
                    *pOutLenBit = n * 8;
                }
                if(n == 0)
                {
                    n = 1;
                }
                if(n > MAXRLEN)
                {
                    n = MAXRLEN;
                }
                for(i = 0; i < n; i++)
                {
                    pOutData[i] = readRawRc(FIFODataReg);
                }
            }
        }
        else
        {
          status = MI_ERR;
        }
    }

    setBitMask(ControlReg, 0x80);                                               // stop timer now
    writeRawRc(CommandReg, PCD_IDLE);

    return status;
}

/**
 @brief 开启天线【每次启动或关闭天线发射之间至少有1ms的间隔】
 @return 无
*/
static void pcdAntennaOn(void)
{
    uint8_t temp;
    temp = readRawRc(TxControlReg);
    if(!(temp & 0x03))
    {
        setBitMask(TxControlReg, 0x03);
    }
}

/**
 @brief 关闭天线
 @return 无
*/
static void pcdAntennaOff(void)
{
    clearBitMask(TxControlReg, 0x03);
}

/**
 @brief 置RC522寄存器位
 @param reg -[in] 寄存器地址
 @param mask -[in] 置位值
 @return 无
*/
static void setBitMask(uint8_t reg, uint8_t mask)
{
    char temp = 0x00;
    temp = readRawRc(reg) | mask;
    writeRawRc(reg, temp | mask);                                               // set bit mask
}

/**
 @brief 清RC522寄存器位
 @param reg -[in] 寄存器地址
 @param mask -[in] 清位值
 @return 无
*/
static void clearBitMask(uint8_t reg, uint8_t mask)
{
    char temp = 0x00;
    temp = readRawRc(reg) & (~mask);
    writeRawRc(reg, temp);                                                      // clear bit mask
}

/**
 @brief 写RC522寄存器
 @param addr -[in] 寄存器地址
 @param writeData -[in] 写入数据
 @return 无
*/
static void writeRawRc(uint8_t addr, uint8_t writeData)
{
    SPI_CS_LOW;

    addr <<= 1;
    addr &= 0x7e;

    SPI_ReadWriteData(&addr, NULL, sizeof(uint8_t));
    SPI_ReadWriteData(&writeData, NULL, sizeof(uint8_t));

    SPI_CS_HIGH;
}

/**
 @brief 读RC522寄存器
 @param addr -[in] 寄存器地址
 @return 读出一字节数据
*/
static uint8_t readRawRc(uint8_t addr)
{
    uint8_t writeData = 0xff;
    uint8_t readData;

    SPI_CS_LOW;

    addr <<= 1;
    addr |= 0x80;

    SPI_ReadWriteData(&addr, NULL, sizeof(uint8_t));
    SPI_ReadWriteData(&writeData, &readData, sizeof(uint8_t));

    SPI_CS_HIGH;

    return readData;
}

/**
 @brief 毫秒级延时函数
 @param time -[in] 延时时间(毫秒)
 @return 无
*/
static void delayMs(uint8_t time)
{
    CPUdelay(12000 * time);
}

/*************************************END OF FILE*************************************/

3.2 rc522.h

#ifndef _RC522_H_
#define _RC522_H_

/*********************************************************************
 * INCLUDES
 */

/*********************************************************************
 * DEFINITIONS
 */
#define RC522_RST_ON            0
#define RC522_RST_OFF           1

#define RC522_IRQ_ON            1
#define RC522_IRQ_OFF           0

#define RC522_RST_IO            IOID_1
#define RC522_IRQ_IO            IOID_5

#define IRQ_DEBOUNCE_TIMEOUT    20               // 超时时间

#define RC522_RST_HIGH          rstPinSet(RC522_RST_IO, RC522_RST_OFF)
#define RC522_RST_LOW           rstPinSet(RC522_RST_IO, RC522_RST_ON)

#define MAXRLEN                 18
#define MIN_STRENGTH            228
#define DEF_FIFO_LENGTH         64               // FIFO size = 64byte;

//******************************************************************/
//                       RC522命令字                                                                                   /
//******************************************************************/
#define PCD_IDLE                  0x00           // 取消当前命令
#define PCD_AUTHENT               0x0E           // 验证密钥
#define PCD_RECEIVE               0x08           // 接收数据
#define PCD_TRANSMIT              0x04           // 发送数据
#define PCD_TRANSCEIVE            0x0C           // 发送并接收数据
#define PCD_RESETPHASE            0x0F           // 复位
#define PCD_CALCCRC               0x03           // CRC计算

//******************************************************************/
//                   Mifare_One卡片命令字                                                                       */
//******************************************************************/
#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_RESTORE              0xC2           // 调块数据到缓冲区
#define PICC_TRANSFER             0xB0           // 保存缓冲区中数据
#define PICC_HALT                 0x50           // 休眠

//******************************************************************/
//                        MF522寄存器定义                                                                          /
//******************************************************************/
// PAGE 0
#define     RFU00                 0x00
#define     CommandReg            0x01
#define     ComIEnReg             0x02
#define     DivlEnReg             0x03
#define     ComIrqReg             0x04
#define     DivIrqReg             0x05
#define     ErrorReg              0x06
#define     Status1Reg            0x07
#define     Status2Reg            0x08
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxASKReg              0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2
#define     RFU20                 0x20
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
// PAGE 3
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39
#define     TestDAC2Reg           0x3A
#define     TestADCReg            0x3B
#define     RFU3C                 0x3C
#define     RFU3D                 0x3D
#define     RFU3E                 0x3E
#define     RFU3F         0x3F

//******************************************************************/
//                    RC522通讯返回错误代码                                                                         /
//******************************************************************/
#define MI_ERR                      0xFE
//#define MI_ERR                         //(-2)

// Mifare Error Codes
// Each function returns a status value, which corresponds to the
// mifare error codes.

#define MI_OK                          0
#define MI_CHK_OK                      0
#define MI_CRC_ZERO                    0

#define MI_CRC_NOTZERO                 1

#define MI_NOTAGERR                 0xFF
#define MI_CHK_FAILED               0xFF
#define MI_CRCERR                   0xFE
#define MI_CHK_COMPERR              0xFE
#define MI_EMPTY                    0xFD
#define MI_AUTHERR                  0xFC
#define MI_PARITYERR                0xFB
#define MI_CODEERR                  0xFA

#define MI_SERNRERR                 0xF8
#define MI_KEYERR                   0xF7
#define MI_NOTAUTHERR               0xF6
#define MI_BITCOUNTERR              0xF5
#define MI_BYTECOUNTERR             0xF4
#define MI_IDLE                     0xF3
#define MI_TRANSERR                 0xF2
#define MI_WRITEERR                 0xF1
#define MI_INCRERR                  0xF0
#define MI_DECRERR                  0xEF
#define MI_READERR                  0xEE
#define MI_OVFLERR                  0xED
#define MI_POLLING                  0xEC
#define MI_FRAMINGERR               0xEB
#define MI_ACCESSERR                0xEA
#define MI_UNKNOWN_COMMAND          0xE9
#define MI_COLLERR                  0xE8
#define MI_RESETERR                 0xE7
#define MI_INITERR                  0xE7
#define MI_INTERFACEERR             0xE7
#define MI_ACCESSTIMEOUT            0xE5
#define MI_NOBITWISEANTICOLL        0xE4
#define MI_QUIT                     0xE2

#define MI_RECBUF_OVERFLOW          0xCF
#define MI_SENDBYTENR               0xCE

#define MI_SENDBUF_OVERFLOW         0xCC
#define MI_BAUDRATE_NOT_SUPPORTED   0xCB
#define MI_SAME_BAUDRATE_REQUIRED   0xCA

#define MI_WRONG_PARAMETER_VALUE    0xC5

#define MI_BREAK                    0x9E
#define MI_NY_IMPLEMENTED           0x9D
#define MI_NO_MFRC                  0x9C
#define MI_MFRC_NOTAUTH             0x9B
#define MI_WRONG_DES_MODE           0x9A
#define MI_HOST_AUTH_FAILED         0x99

#define MI_WRONG_LOAD_MODE          0x97
#define MI_WRONG_DESKEY             0x96
#define MI_MKLOAD_FAILED            0x95
#define MI_FIFOERR                  0x94
#define MI_WRONG_ADDR               0x93
#define MI_DESKEYLOAD_FAILED        0x92

#define MI_WRONG_SEL_CNT            0x8F
#define MI_RC531_WRONG_READVALUE    0x8E // LI ADDED 09-4-24
#define MI_WRONG_TEST_MODE          0x8C
#define MI_TEST_FAILED              0x8B
#define MI_TOC_ERROR                0x8A
#define MI_COMM_ABORT               0x89
#define MI_INVALID_BASE             0x88
#define MI_MFRC_RESET               0x87
#define MI_WRONG_VALUE              0x86
#define MI_VALERR                   0x85

/*********************************************************************
 * TYPEDEFS
 */
typedef void (*IrqCallback_t)(uint8_t irqValue);

/*********************************************************************
 * API FUNCTIONS
 */
void RC522_Init(void);
void RC522_irqInit(IrqCallback_t appIrqCB);
uint8_t RC522_ReadCardDataBlock(uint8_t addr);

#endif /* _RC522_H_ */

四、API调用

需包含头文件 rc522.h

RC522_Init

功能 RC522的初始化函数
函数定义 void RC522_Init(void)
参数
返回

RC522_irqInit

功能 RC522中断初始化函数
函数定义 void RC522_irqInit(IrqCallback_t appIrqCB)
参数 appIrqCB:中断回调函数
返回

RC522_ReadCardDataBlock

功能 RC522读取卡片块数据
函数定义 uint8_t RC522_ReadCardDataBlock(uint8_t addr)
参数 addr:块地址
返回 状态值,0 - 成功;2 - 无卡;3 - 防冲撞失败;4 - 选卡失败;5 - 密码错误

五、使用例子

1)添加头文件(例multi_role.c中)

#include "rc522.h"

2)添加初始化代码(multi_role.c的multi_role_init函数末尾中)

// RC522初始化
RC522_Init(); 

3)读取数据块4

RC522_ReadCardDataBlock(4);

• 由 Leung 写于 2019 年 8 月 27 日

猜你喜欢

转载自blog.csdn.net/qq_36347513/article/details/100094162