#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_
#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;
}
#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_
#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