MFRC522读卡封装(附源代码)

Mfrc.h

#ifndef _MFRC_H_
#define _MFRC_H_


#include "libreagent.h"


// 应答
#define SW_OK                   (0x9000)
#define SW_PCD                  (0x9870)

// 密钥长度
#define KEY_LEN                 (8)
// 命令长度
#define LENGTH_OF_COMMAND       (64)


class REAGENT_EXPORT Mfrc
{
public:
    Mfrc();
    virtual ~Mfrc();

    // 寻试剂卡
    virtual quint16 request() = 0;

    // 认证(8位密钥)
    quint16 authenticate(quint8 keyId, const quint8* key);

    // 读写文件
    quint16 readBinaryFile(quint8* content, int len, quint8 offset);
    quint16 writeBinaryFile(const quint8* content, int len, quint8 offset);

public:
    // 取随机数(8字节)
    quint16 getChallenge(quint8* challenge);
    // 外部认证(8字节随机数)
    quint16 externalAuthenticate(quint8 keyId, const quint8* challenge);
    // 卡片擦除
    quint16 erase();
    // 建立目录
    quint16 createDfFile(quint16 fileId, quint16 size, quint8 appId);
    // 创建密钥文件
    quint16 createKeyFile(quint16 fileId, quint16 size);
    // 创建二进制文件
    quint16 createBinaryFile(quint16 fileId, quint16 size);
    // 添加线路保护密钥
    quint16 createLineProtectKey(quint8 keyId, const quint8* key);
    // 添加外部认证密钥
    quint16 createExternalAuthenticateKey(quint8 keyId, const quint8* key);
    // 选中文件
    quint16 selectMfFile();
    quint16 selectFile(quint16 fileId);

protected:
    // 格式化
    QString toString(const quint8* datas, quint8 len);

    // 接收发送
    virtual quint16 piccTransceive(quint8* trans, quint8 tlen, quint8* recv, quint8& rlen) = 0;
};


#endif // _MFRC_H_

 

Mfrc.cpp

#include

#include "des.h"
#include "mfrc.h"
#include "fmcos.h"
#include "utility.h"


Mfrc::Mfrc()
{

}

Mfrc::~Mfrc()
{

}

// 认证(8位密钥)
quint16 Mfrc::authenticate(quint8 keyId, const quint8* key)
{
    qDebug() << "Mfrc authenticate" << QString::number(keyId, 16);

    // 获取随机数
    quint8 challenge[KEY_LEN] = { 0 };

    quint16 ret = this->getChallenge(challenge);
    if (SW_OK == ret)
    {
        // 对随机数进行DES加密
        quint8 encrypted[KEY_LEN] = { 0 };
        Des::encrypt(challenge, key, encrypted, KEY_LEN);

        // 外部认证(8字节随机数)
        ret = this->externalAuthenticate(keyId, encrypted);
        if (SW_OK == ret)
        {

        }
        else
        {
            qWarning() << "Mfrc authenticate externalAuthenticate fail";
        }
    }
    else
    {
        qWarning() << "Mfrc authenticate getChallenge fail";
    }

    return ret;
}

// 读写文件
quint16 Mfrc::readBinaryFile(quint8* content, int len, quint8 offset)
{
    qDebug() << "Mfrc readBinaryFile" << QString::number(offset, 16) << QString::number(len, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::readBinrayCommand(buf, offset, len);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    quint16 ret = this->piccTransceive(buf, tlen, buf, rlen);

    if (SW_OK == ret)
    {
        // 返回随机数(0A 01 84 8A 51 10 9E 2B A7 A2 90 00,跳过0A 01)
        memcpy(content, buf + 2, len);
    }

    return ret;
}

quint16 Mfrc::writeBinaryFile(const quint8* content, int len, quint8 offset)
{
    qDebug() << "Mfrc writeBinaryFile" << QString::number(offset, 16) << QString::number(len, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::writeBinaryCommand(buf, offset, content, len);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 取随机数(8字节)
quint16 Mfrc::getChallenge(quint8* challenge)
{
    qDebug() << "Mfrc getChallenge";

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::getChallengeCommand(buf, KEY_LEN);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    quint16 ret = this->piccTransceive(buf, tlen, buf, rlen);

    if (SW_OK == ret)
    {
        // 返回随机数(0A 01 84 8A 51 10 9E 2B A7 A2 90 00,跳过0A 01)
        memcpy(challenge, buf + 2, KEY_LEN);
    }

    return ret;
}

// 外部认证(8字节随机数)
quint16 Mfrc::externalAuthenticate(quint8 keyId, const quint8* challenge)
{
    qDebug() << "Mfrc externalAuthenticate" << QString::number(keyId, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::externalAuthenticateCommand(buf, keyId, challenge);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 卡片擦除
quint16 Mfrc::erase()
{
    qDebug() << "Mfrc erase";

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::eraseCommand(buf);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 建立目录
quint16 Mfrc::createDfFile(quint16 fileId, quint16 size, quint8 appId)
{
    qDebug() << "Mfrc createDfFile" << QString::number(fileId, 16) << QString::number(size, 16) << QString::number(appId, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::createDfFileCommand(buf, fileId, size, appId);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 创建密钥文件
quint16 Mfrc::createKeyFile(quint16 fileId, quint16 size)
{
    qDebug() << "Mfrc createKeyFile" << QString::number(fileId, 16) << QString::number(size, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::createKeyFileCommand(buf, fileId, size);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 创建二进制文件
quint16 Mfrc::createBinaryFile(quint16 fileId, quint16 size)
{
    qDebug() << "Mfrc createBinaryFile" << QString::number(fileId, 16) << QString::number(size, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::createBinaryFileCommand(buf, fileId, size);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 添加线路保护密钥
quint16 Mfrc::createLineProtectKey(quint8 keyId, const quint8* key)
{
    qDebug() << "Mfrc createLineProtectKey" << QString::number(keyId, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::writeLineKeyCommand(buf, keyId, key);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 添加外部认证密钥
quint16 Mfrc::createExternalAuthenticateKey(quint8 keyId, const quint8* key)
{
    qDebug() << "Mfrc createExternalAuthenticateKey" << QString::number(keyId, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::writeExternalKeyCommand(buf, keyId, key);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 选中文件
quint16 Mfrc::selectMfFile()
{
    return this->selectFile(0x3F00);
}

quint16 Mfrc::selectFile(quint16 fileId)
{
    qDebug() << "Mfrc selectFile" << QString::number(fileId, 16);

    // 指令
    quint8 buf[LENGTH_OF_COMMAND] = { 0 };
    quint8 tlen = FMCos::selectFileCommand(buf, fileId);

    // 发送指令,接收返回值
    quint8 rlen = 0;
    return this->piccTransceive(buf, tlen, buf, rlen);
}

// 格式化
QString Mfrc::toString(const quint8* datas, quint8 len)
{
    QString text;

    for (int i = 0; i < len; i++)
    {
        text += QString("%1").arg(*(datas + i), 2, 16, QChar('0'));
    }

    return text;
}

 

Mfrc522.h

#ifndef _MFRC_522_H_
#define _MFRC_522_H_


#include "mfrc.h"

class Mfrc522Private;


class REAGENT_EXPORT Mfrc522 : public Mfrc
{
public:
    Mfrc522();
    virtual ~Mfrc522();

    // 寻试剂卡
    virtual quint16 request();

    // 通信设备
    void setSpi(const QString& dev);

protected:
    // 接收发送
    virtual quint16 piccTransceive(quint8* trans, quint8 tlen, quint8* recv, quint8& rlen);

private:
    // 芯片复位
    virtual quint16 reset();
    // 寻卡
    virtual quint16 request(quint16& type);
    // 防卡冲突
    virtual quint16 antiCollision(quint32& rfid);
    // 选卡
    virtual quint16 select(quint32 rfid);
    // 复位激活卡
    virtual quint16 rats();

private:
    Mfrc522Private* d;
};


#endif // _MFRC_522_H_

 

Mfrc522.cpp

#include

#include "spi.h"
#include "fmcos.h"
#include "mfrc522.h"
#include "utility.h"


// Command
#define Command_Idle            (0x00) // 取消当前命令
#define Command_CalcCrc         (0x03) // CRC计算
#define Command_Transceive      (0x0C) // 发送并接收数据
#define Command_ResetPhase      (0x0F) // 复位

// Reg
#define Reg_Command             (0x01) // 启动和停止命令的执行
#define Reg_ComIEn              (0x02) // 中断请求传递的使能和禁能控制位
#define Reg_DivIEn              (0x03)
#define Reg_ComIrq              (0x04) // 包含中断请求标志
#define Reg_DivIrq              (0x05)
#define Reg_Error               (0x06) // 错误标志,指示执行的上个命令的错误状态
#define Reg_Status1             (0x07) // 包含通信的状态标志
#define Reg_Status2             (0x08) // 包含接收器和发射器的状态标志
#define Reg_FifoData            (0x09) // 64字节FIFO缓冲区的输入和输出
#define Reg_FifoLevel           (0x0A) // 指示FIFO中存储的字节数
#define Reg_Control             (0x0C) // 不同的控制寄存器
#define Reg_BitFraming          (0x0D) // 面向位的帧的调节
#define Reg_Coll                (0x0E)

#define Reg_Mode                (0x11) // 定义发送和接收的常用模式
#define Reg_TxMode              (0x12) // 定义发送过程的数据传输速率
#define Reg_RxMode              (0x13) // 定义接收过程中的数据传输速率
#define Reg_TxControl           (0x14) // 控制天线驱动器的设置
#define Reg_TxAuto              (0x15)
#define Reg_RxSel               (0x17) // 选择内部的接收器设置

#define Reg_CRCResultH          (0x21) // 显示CRC计算的实际值
#define Reg_CRCResultL             (0x22)
#define Reg_RFCfg               (0x26) // 配置接收器增益
#define Reg_TMode               (0x2A) // 定义内部定时器的设置
#define Reg_TPrescaler          (0x2B)
#define Reg_TReloadH            (0x2C) // 描述16位长的定时器重装值
#define Reg_TReloadL            (0x2D)

#define Reg_Version             (0x37) // 显示版本


class Mfrc522Private
{
public:
    Mfrc522Private();
    ~Mfrc522Private();

    // 等待IRQ
    bool waitComIrq();

    // Cmd
    bool writeCmd(quint8 data);

    // 是否出错
    bool isError(quint8 mask);

    // 开关天线
    bool switchAntenna(bool on);

    // Fifo
    bool readFifo(quint8* data, int len);
    bool writeFifo(const quint8* data, int len);

    // Reg
    bool setMask(quint8 reg, quint8 mask);
    bool clearMask(quint8 reg, quint8 mask);
    bool waitMask(quint8 reg, quint8 mask, quint16 timeout);

    bool readReg(quint8 reg, quint8& data);
    bool writeReg(quint8 reg, quint8 data);

    bool readReg(quint8 lreg, quint8 hreg, quint16& data);
    bool writeReg(quint8 lreg, quint8 hreg, quint16 data);

    // 应答判定
    quint16 sw(const quint8* data, int len);

    // 计算CRC
    bool calcCrc1(quint8* data, int len);
    bool calcCrc2(quint8* data, int len);

    // 接收发送
    bool receive(quint8* recv, quint8& rlen);
    bool trans(const quint8* trans, quint8 tlen);
    quint16 pcdTransceive(quint8* trans, quint8 tlen, quint8* recv, quint8& rlen);

public:
    // 通信设备
    QString dev;
};

Mfrc522Private::Mfrc522Private()
    : dev()
{

}

Mfrc522Private::~Mfrc522Private()
{

}

// 等待IRQ
bool Mfrc522Private::waitComIrq()
{
    // 注意:30ms超时不能随便更改,更改后可能导致读卡外部认证时出错
    return this->waitMask(Reg_ComIrq, 0x30, 30);
}

// Cmd
bool Mfrc522Private::writeCmd(quint8 data)
{
    return this->writeReg(Reg_Command, data);
}

// 是否出错
bool Mfrc522Private::isError(quint8 mask)
{
    bool ret = true;

    // ErrorReg : Error bit register showing the error status of the last command executed.
    quint8 err = 0xFF;
    if (this->readReg(Reg_Error, err))
    {
        ret = (err & mask);
    }

    return ret;
}

// 开关天线
bool Mfrc522Private::switchAntenna(bool on)
{
    quint8 addr = Reg_TxControl;
    if (on)
    {
        return this->setMask(addr, 3);
    }
    else
    {
        return this->clearMask(addr, 3);
    }
}

// Fifo
bool Mfrc522Private::readFifo(quint8* data, int len)
{
    for (int i = 0; i < len; i++)
    {
        if (!this->readReg(Reg_FifoData, *(data + i)))
        {
            return false;
        }
    }
    return true;
}

bool Mfrc522Private::writeFifo(const quint8* data, int len)
{
    for (int i = 0; i < len; i++)
    {
        if (!this->writeReg(Reg_FifoData, *(data + i)))
        {
            return false;
        }
    }
    return true;
}

// Reg
bool Mfrc522Private::setMask(quint8 reg, quint8 mask)
{
    quint8 data = 0;
    if (this->readReg(reg, data))
    {
        data |= mask;
        if (this->writeReg(reg, data))
        {
            return true;
        }
    }
    return false;
}

bool Mfrc522Private::clearMask(quint8 reg, quint8 mask)
{
    quint8 data = 0;
    if (this->readReg(reg, data))
    {
        data &= ~mask;
        if (this->writeReg(reg, data))
        {
            return true;
        }
    }
    return false;
}

bool Mfrc522Private::waitMask(quint8 reg, quint8 mask, quint16 timeout)
{
    bool ret = false;

    // 延时
    Utility::msleep(timeout);

    // 读值
    quint8 data = 0;
    if (this->readReg(reg, data))
    {
        if (data & mask)
        {
            ret = true;
        }
    }

    return ret;
}

bool Mfrc522Private::readReg(quint8 reg, quint8& data)
{
    // 参见手册:10.2.4章节
    quint8 rreg = (0x80 | ((reg << 1) & 0x7E));
    return Spi::read1(this->dev, rreg, data);
}

bool Mfrc522Private::writeReg(quint8 reg, quint8 data)
{
    // 参见手册:10.2.4章节
    quint8 wreg = ((reg << 1) & 0x7E);
    return Spi::write1(this->dev, wreg, data);
}

bool Mfrc522Private::readReg(quint8 lreg, quint8 hreg, quint16& data)
{
    bool ret = false;

    quint8 d[2] = { 0 };
    if (this->readReg(lreg, d[0]) && this->readReg(hreg, d[1]))
    {
        data = ((d[1] << 8) | d[0]);
        ret = true;
    }

    return ret;
}

bool Mfrc522Private::writeReg(quint8 lreg, quint8 hreg, quint16 data)
{
    return (this->writeReg(lreg, (data & 0xFF)) && this->writeReg(hreg, ((data >> 8) & 0xFF)));
}

// 应答判定
quint16 Mfrc522Private::sw(const quint8* data, int len)
{
    // 0a 01 d7 1d b9 8f c8 29 3d f6 90 00 3b e6
    const quint8* p = data + len - 4;
    return ((*p << 8) | *(p + 1));
}

// 计算CRC
bool Mfrc522Private::calcCrc1(quint8* data, int len)
{
    bool ret = false;

    do
    {
        // DivIRqReg : Contains Interrupt Request bits
        if (!this->clearMask(Reg_DivIrq, 0x04))
        {
            break;
        }

        // Idle : No action; cancels current command execution.
        if (!this->writeCmd(Command_Idle))
        {
            break;
        }

        // FIFOLevelReg : Indicates the number of bytes stored in the FIFO.
        if (!this->setMask(Reg_FifoLevel, 0x80))
        {
            break;
        }

        // FIFODataReg : Input and output of 64 byte FIFO buffer.
        if (!this->writeFifo(data, len))
        {
            break;
        }

        // CalcCRC : Activates the CRC co - processor or performs a selftest.
        if (!this->writeCmd(Command_CalcCrc))
        {
            break;
        }

        // DivIrqReg : Contains Interrupt Request bits
        // bit2 : Set to logic 1, when the CRC command is active and all data are processed.
        if (!this->waitMask(Reg_DivIrq, 0x04, 10))
        {
            break;
        }

        // CRCResultReg : Shows the actual MSB and LSB values of the CRC calculation.
        quint16 crc = 0;
        if (!this->readReg(Reg_CRCResultL, Reg_CRCResultH, crc))
        {
            break;
        }

        data[len] = (crc & 0xFF);
        data[len + 1] = ((crc >> 8) & 0xFF);

        ret = true;
    } while (0);

    return ret;
}

bool Mfrc522Private::calcCrc2(quint8* data, int len)
{
    quint8 crc = 0;

    for (int i = 0; i < len; i++)
    {
        crc ^= *(data + i);
    }

    *(data + len) = crc;

    return true;
}

// 接收发送
bool Mfrc522Private::receive(quint8* recv, quint8& rlen)
{
    bool ret = false;

    do
    {
        // BitFramingReg : Adjustments for bit oriented frames.
        if (!this->clearMask(Reg_BitFraming, 0x80))
        {
            break;
        }

        // ErrorReg : Error bit register showing the error status of the last command executed.
        // WrErr TempErr * BufferOvfl CollErr CRCErr ParityErr ProtocolErr
        if (this->isError(0x1B))
        {
            break;
        }

        // FIFOLevelReg : Indicates the number of bytes stored in the FIFO.
        quint8 bytes = 0;
        if (!this->readReg(Reg_FifoLevel, bytes))
        {
            break;
        }

        // ControlReg : Miscellaneous control bits.
        // bit2 - bit0 : RxLastBits Shows the number of valid bits in the last received byte. If 0, the whole byte is valid.
        quint8 control = 0;
        if (!this->readReg(Reg_Control, control))
        {
            break;
        }

        // 读FIFO数据
        if (!this->readFifo(recv, bytes))
        {
            break;
        }

        ret = true;
        rlen = bytes;
    } while (0);

    return ret;
}

bool Mfrc522Private::trans(const quint8* trans, quint8 tlen)
{
    bool ret = false;

    do
    {
        // ComlEnReg : Controls bits to enable and disable the passing of Interrupt Requests
        // bit7 - bit0 : IRqInv TxIEn RxIEn IdleIEn HiAlertIEn LoAlertIEn ErrIEn TimerIEn
        if (!this->writeReg(Reg_ComIEn, 0xF7))
        {
            break;
        }

        // CommIRqReg : Contains Interrupt Request bits.
        // bit7 - bit0 : Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
        if (!this->clearMask(Reg_ComIrq, 0x80))
        {
            break;
        }

        // FIFOLevelReg : Indicates the number of bytes stored in the FIFO.
        // bit7 : this bit clears the internal FIFO-buffer's read and write pointer and the bit BufferOvfl in the register ErrReg immediately.
        // bit6 - bit0 : Indicates the number of bytes stored in the FIFO buffer.
        if (!this->setMask(Reg_FifoLevel, 0x80))
        {
            break;
        }

        // Idle : No action; cancels current command execution.
        if (!this->writeCmd(Command_Idle))
        {
            break;
        }

        // FIFODataReg : Input and output of 64 byte FIFO buffer.
        if (!this->writeFifo(trans, tlen))
        {
            break;
        }

        // Transceive : Transmits data from FIFO buffer to the antenna and activates automatically the receiver after transmission.
        if (!this->writeCmd(Command_Transceive))
        {
            break;
        }

        // BitFramingReg : Adjustments for bit oriented frames.
        if (!this->setMask(Reg_BitFraming, 0x80))
        {
            break;
        }

        ret = true;
    } while (0);

    return ret;
}

quint16 Mfrc522Private::pcdTransceive(quint8* trans, quint8 tlen, quint8* recv, quint8& rlen)
{
    quint16 ret = SW_PCD;

    do
    {
        // trans
        if (!this->trans(trans, tlen))
        {
            break;
        }

        // wait irq
        if (!this->waitComIrq())
        {
            break;
        }

        // receive
        if (!this->receive(recv, rlen))
        {
            break;
        }

        ret = SW_OK;
    } while (0);

    return ret;
}


Mfrc522::Mfrc522()
    : Mfrc(), d(new Mfrc522Private())
{

}

Mfrc522::~Mfrc522()
{
    delete d;
}

// 通信设备
void Mfrc522::setSpi(const QString& dev)
{
    d->dev = dev;
}

// 寻试剂卡
quint16 Mfrc522::request()
{
    quint16 ret = SW_PCD;

    do
    {
        // 复位
        ret = this->reset();
        if (SW_OK != ret)
        {
            qWarning() << "Mfrc522 request reset fail";
            break;
        }

        // 寻卡
        quint16 type = 0;
        ret = this->request(type);
        if (SW_OK != ret)
        {
            qWarning() << "Mfrc522 request request fail";
            break;
        }

        // 防冲突
        quint32 rfid = 0;
        ret = this->antiCollision(rfid);
        if (SW_OK != ret)
        {
            qWarning() << "Mfrc522 request antiCollision fail";
            break;
        }

        // 选卡
        ret = this->select(rfid);
        if (SW_OK != ret)
        {
            qWarning() << "Mfrc522 request select fail";
            break;
        }

        // 复位激活CPU卡
        ret = this->rats();
        if (SW_OK != ret)
        {
            qWarning() << "Mfrc522 request select fail";
            break;
        }

        ret = SW_OK;
    } while (0);

    return ret;
}

// 芯片复位
quint16 Mfrc522::reset()
{
    quint16 ret = SW_PCD;

    qDebug() << "Mfrc522 reset";

    do
    {
        // SoftReset : Resets the MFRC522
        if (!d->writeCmd(Command_ResetPhase))
        {
            break;
        }

        Utility::msleep(100);

        // VersionReg : Shows the version
        quint8 version;
        if (!d->readReg(Reg_Version, version))
        {
            break;
        }

        // TModeReg : Defines settings for the internal timer
        // TPrescalerReg : Defines settings for the internal timer
        if (!d->writeReg(Reg_TMode, 141) || !d->writeReg(Reg_TPrescaler, 62))
        {
            break;
        }

        // TReloadReg : Describes the 16 bit timer reload value
        if (!d->writeReg(Reg_TReloadL, Reg_TReloadH, 30))
        {
            break;
        }

        // ModeReg : Defines general mode settings for transmitting and receiving.
        // TxASKReg : Controls the setting of the TX modulation
        if (!d->writeReg(Reg_TxAuto, 64) || !d->writeReg(Reg_Mode, 61))
        {
            qWarning() << "Mfrc522 reset writeReg 64 61 fail";
            break;
        }

        Utility::msleep(10);

        // switch antenna on
        if (!d->switchAntenna(false))
        {
            break;
        }

        Utility::msleep(10);

        // switch antenna on
        if (!d->switchAntenna(true))
        {
            break;
        }

        ret = SW_OK;
    } while (0);

    return ret;
}

// 寻卡(成功返回卡片类型)
quint16 Mfrc522::request(quint16& type)
{
    quint16 ret = SW_PCD;

    qDebug() << "Mfrc522 request";

    do
    {
        // BitFramingReg : Adjustments for bit oriented frames
        if (!d->writeReg(Reg_BitFraming, 0x07))
        {
            break;
        }

        // PCD初始化
        FMCos::pcbInit();

        // 发送接收数据
        quint8 rlen;
        quint8 buf[LENGTH_OF_COMMAND] = { 0x26 }; // 寻未进入休眠状态的卡

        ret = d->pcdTransceive(buf, 1, buf, rlen);
        if (SW_OK == ret)
        {
            // 返回卡类型
            type = (buf[0] | (buf[1] << 8));
        }

        qDebug() << "Mfrc522 request" << QString::number(type, 16);
    } while (0);

    return ret;
}

// 防卡冲突(成功返回卡片标识号)
quint16 Mfrc522::antiCollision(quint32& rfid)
{
    quint16 ret = SW_PCD;

    qDebug() << "Mfrc522 antiCollision";

    do
    {
        // BitFramingReg : Adjustments for bit oriented frames
        if (!d->writeReg(Reg_BitFraming, 0x00))
        {
            break;
        }

        // 发送接收数据
        quint8 rlen;
        quint8 buf[LENGTH_OF_COMMAND] = { 0x93, 0x20 };

        ret = d->pcdTransceive(buf, 2, buf, rlen);
        if (SW_OK == ret)
        {
            // 返回卡号
            rfid = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
        }
    } while (0);

    return ret;
}

// 选卡
quint16 Mfrc522::select(quint32 rfid)
{
    quint16 ret = SW_PCD;

    qDebug() << "Mfrc522 select" << QString::number(rfid, 16);

    do 
    {
        quint8 buf[LENGTH_OF_COMMAND] = { 0x93, 0x70, (quint8)(rfid >> 24), (quint8)(rfid >> 16), (quint8)(rfid >> 8), (quint8)rfid, 0x00 };

        // CRC校验
        if (!d->calcCrc2(&buf[2], 4))
        {
            break;
        }
        if (!d->calcCrc1(buf, 7))
        {
            break;
        }

        // 发送接收
        quint8 rlen;
        ret = d->pcdTransceive(buf, 9, buf, rlen);
    } while (0);

    return ret;
}

// 复位激活卡
quint16 Mfrc522::rats()
{
    quint16 ret = SW_PCD;

    qDebug() << "Mfrc522 rats";

    do
    {
        quint8 buf[LENGTH_OF_COMMAND] = { 0xE0, 0x51 };
        
        // CRC校验
        if (!d->calcCrc1(buf, 2))
        {
            break;
        }

        // 发送接收
        quint8 rlen;
        ret = d->pcdTransceive(buf, 4, buf, rlen);
    } while (0);

    return ret;
}

// 接收发送
quint16 Mfrc522::piccTransceive(quint8* trans, quint8 tlen, quint8* recv, quint8& rlen)
{
    quint16 ret = SW_PCD;

    do
    {
        // CRC校验
        if (!d->calcCrc1(trans, tlen))
        {
            break;
        }

        // trans
        if (!d->trans(trans, tlen + 2))
        {
            break;
        }

        // output
        QString text = this->toString(trans, tlen + 2);
        qDebug() << "Mfrc522 piccTransceive trans" << text;

        // 取消次
        // Utility::msleep(30);

        // wait irq
        if (!d->waitComIrq())
        {
            break;
        }

        // receive
        if (!d->receive(recv, rlen))
        {
            break;
        }

        // output
        text = this->toString(recv, rlen);
        qDebug() << "Mfrc522 piccTransceive recv" << text;

        // check
        ret = d->sw(recv, rlen);
    } while (0);

    return ret;
}

 

FmCos相关接口参见

https://blog.csdn.net/calm_agan/article/details/86660179

你可能感兴趣的:(随笔)