美文网首页物联网loT从业者物联网相关技术研究arduino
CC2640R2F学习笔记(23)——RFID RC522使用

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

作者: Leung_ManWah | 来源:发表于2019-08-27 10:05 被阅读0次

    一、硬件连接

    功能口 引脚
    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 日

    相关文章

      网友评论

        本文标题:CC2640R2F学习笔记(23)——RFID RC522使用

        本文链接:https://www.haomeiwen.com/subject/vussectx.html