// 通过RC522和ISO14443卡通讯
int8_t RC522_CardCom(uint8_t Command, uint8_t *InData, uint8_t InLength, uint8_t *OutData, uint32_t *OutLength)
{
uint8_t waitFor = 0x00;
switch(Command)
{
case PCD_AUTHENT: // 验证密钥
waitFor = 0x10; // 认证寻卡等待时间 查询空闲中断标志位
break;
case PCD_TRANSCEIVE: // 接收发送 发送接收
waitFor = 0x30;
break;
default:
break;
}
RC522_ClearReg(ComIrqReg, 0x80); // 清楚中断标志
RC522_WriteData(CommandReg, PCD_IDLE); // 关闭接收机的模拟部分,进入软关机模式,进入IDLE模式
RC522_SetReg(FIFOLevelReg, 0x80); // 清楚Fifo缓冲区及状态位
// 写数据进FIFOdata
for(uint32_t i=0; i<InLength; i++)
{
RC522_WriteData(FIFODataReg, InData[i]);
}
// 写入命令(PCD_TRANSCEIVE:开始传输并且传输完成后自动接收数据 PCD_AUTHENT:作为读取器执行MIFARE®标准身份验证)
RC522_WriteData(CommandReg, Command);
if(Command == PCD_TRANSCEIVE)
{
// 开始传输数据
RC522_SetReg(BitFramingReg, 0x80);
}
// 读取中断状态。PCD_TRANSCEIVE:等待接收完成或空闲模式 PCD_AUTHENT:等待系统进入空闲模式。
uint8_t state;
uint16_t i;
for(i=1200; i>0; i--)
{
state = RC522_ReadData(ComIrqReg);
if(state&waitFor || state&0x01)
{
break;
}
}
// 停止传输数据
RC522_ClearReg(BitFramingReg, 0x80);
int8_t status = MI_ERR;
if(i!=0) // 如果进入空闲模式
{
if(!(RC522_ReadData(ErrorReg)&0x1B)) // 判断是否存在错误。FIFO溢出、位冲突、奇偶校验错误、协议错误
{
status = MI_OK;
if(Command == PCD_TRANSCEIVE)
{
// 计算输出数据长度(位)
uint8_t number = RC522_ReadData(FIFOLevelReg); // 读FIFO中保存的字节数
uint8_t rxLastBits = RC522_ReadData(ControlReg) & 0x07; // 最后接收到的字节的有效位数
if(rxLastBits)
{
*OutLength = (number-1) * 8 + rxLastBits; // 读取到的数据总位数
}
else
{
*OutLength = number * 8; // 最后接收到的字节整个字节有效
}
// 计算输出数据长度(位)
if(number == 0)
{
number = 1;
}
if(number > MAXRLEN)
{
number = MAXRLEN;
}
for(i=0; i<number; i++)
{
OutData[i] = RC522_ReadData(FIFODataReg);
}
}
}
else
{
status = MI_ERR;
}
}
RC522_SetReg(ControlReg, 0x80);
RC522_WriteData(CommandReg, PCD_IDLE);
return status;
}
|