arduino+RC522 操作FM1208 失败

asdf asdfa 2019-02-16 03:10:52
求助!
使用arduino +RC522 SPI方式操作FM1208时无法使用APDU命令
代码如下,操作中【选卡】成功,【RATS】成功,【选择MF】失败,【获取随机数】失败


#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN 9
#define SS_PIN 10
#define ET_CS 8

//通讯缓存最大长度
#define MAXRLEN 64

//MF522命令字
#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 //休眠

#define MI_ERR 1
#define MI_OK 0
MFRC522 mfrc522(SS_PIN, RST_PIN);

int NewCard;
unsigned char DataBuf[MAXRLEN];

void setup()
{
Serial.begin(115200);
SPI.begin();
Serial.println("Test begin.");
mfrc522.PCD_Init();
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);

digitalWrite(3, HIGH);
digitalWrite(5, HIGH);
delay(100);
digitalWrite(3, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
}

void PrintUid()
{
Serial.print("UID of the card: ");
for (int i = 0; i < mfrc522.uid.size; i++)
{
Serial.print(mfrc522.uid.uidByte[i], HEX);
Serial.print(" ");
}
Serial.print(" SAK: ");
Serial.println(mfrc522.uid.sak, HEX);
}

//send data to PICC with CRC
byte NfcSendData(byte *tData, byte tLen, byte *rData, byte *rLen, bool Crc = true, bool ifPrint = true)
{
MFRC522::StatusCode status = MI_ERR;
unsigned char ucComMF522Buf[MAXRLEN];
memset(ucComMF522Buf, 0x00, MAXRLEN);
strcpy(ucComMF522Buf, tData);
memset(rData, 0x00, *rLen);
if (Crc == true)
{
status = mfrc522.PCD_CalculateCRC(ucComMF522Buf, tLen, &ucComMF522Buf[tLen]); // 生成发送内容的CRC校验,保存到最后两个字节
if (status != MI_OK)
{
Serial.println("CRC error");
return MI_ERR;
}
tLen += 2;
}
status = mfrc522.PCD_TransceiveData(ucComMF522Buf, tLen, rData, rLen); //发送数据

//打印数据
if (ifPrint == true)
{
//print transmit data
Serial.print("Trans data:");
for (byte j = 0; j < tLen; j++)
{
Serial.print(" 0x");
if (tData[j] < 0x10)
{
Serial.print("0");
}
Serial.print(tData[j], HEX);

}
Serial.print(" len:");
Serial.println(tLen);

//print receive data
Serial.print("Receive data:");
for (int j = 0; j < *rLen; j++)
{
Serial.print(" 0x");
if (rData[j] < 0x10)
{
Serial.print("0");
}
Serial.print(rData[j], HEX);

}
Serial.print(" status:");
Serial.print(status);
Serial.print(" len:");
Serial.println(*rLen);

}
return status;
}

//*************************************************************************
// 函数名 :pro_reset
// 描述 :转入APDU命令格式CPU卡复位操作
// 入口 : 无
// 出口 : DataOut 输出的数据, rlen 输出数据的长度
// 返回 :成功返回MI_OK
//*************************************************************************
#define CID 1
byte Pcb = 0x0a;
byte temp1, temp2;
//各种命令,数组长度+命令
byte nfcComReset[] = {0x02, 0xE0, 0x50 | CID}; //5.1 RATS bit[0:3]=CID, bit[4:7]=FSDI define max size of a frame the PCD is able to receive 5=64byte.
byte nfcCmdSelectMf[] = {9, 0x0A, CID, 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00}; //len+pcb+CID+CMD
byte nfcCmdRequestRand[] = {0x07, 0x0A, CID, 0x00, 0x84, 0x00, 0x00, 0x08};

//刷新PCB
void PcbRefresh()
{
switch (Pcb)
{
case 0:
Pcb = 0x0A;
break;
case 0x0A:
Pcb = 0x0B;
break;
case 0x0B:
Pcb = 0x0A;
}
}


char pro_reset(byte *DataOut, unsigned char *rlen)
{
byte unLen = MAXRLEN;
MFRC522::StatusCode status = MI_ERR;

status = NfcSendData(&nfcComReset[1], nfcComReset[0], DataOut, &unLen);

if (status == MFRC522::STATUS_OK)
{
rlen[1] = unLen / 8 - 2;
status = MI_OK;
}
else
status = MI_ERR;
return status; //返回结果
}

//选择主文件
char SelectMf(byte *DataOut, unsigned char *rlen)
{

MFRC522::StatusCode status = MI_ERR;
byte unLen = MAXRLEN;


nfcCmdSelectMf[1] = Pcb;
PcbRefresh();
status = NfcSendData(&nfcCmdSelectMf[1], nfcCmdSelectMf[0], DataOut, &unLen);

if (status == MFRC522::STATUS_OK)
{
rlen[1] = unLen / 8 - 2;
status = MI_OK;
}
else
status = MI_ERR;
return status; //返回结果
}

//获取随机数
char CatchRandNum(byte *DataOut, unsigned char *rlen)
{
MFRC522::StatusCode status = MI_ERR;
byte unLen = MAXRLEN;


nfcCmdRequestRand[1] = Pcb;
PcbRefresh();
status = NfcSendData(&nfcCmdRequestRand[1], nfcCmdRequestRand[0], DataOut, &unLen);

if (status == MFRC522::STATUS_OK)
{
rlen[1] = unLen / 8 - 2;
status = MI_OK;
}
else
status = MI_ERR;
return status; //返回结果
}

//选择ST的NDEF模式
char SelectNdef(byte *DataOut, unsigned char *rlen)
{
MFRC522::StatusCode status = MI_ERR;
byte unLen = MAXRLEN;


nfcCmdRequestRand[1] = Pcb;
PcbRefresh();
status = NfcSendData(&nfcCmdSelectNdef[1], nfcCmdSelectNdef[0], DataOut, &unLen);

if (status == MFRC522::STATUS_OK)
{
rlen[1] = unLen / 8 - 2;
status = MI_OK;
}
else
status = MI_ERR;
return status; //返回结果
}
//进入PPSS模式
char Ppss(byte *DataOut, unsigned char *rlen)
{
MFRC522::StatusCode status = MI_ERR;
byte unLen = MAXRLEN;

status = NfcSendData(&nfcCmdPpss[1], nfcCmdPpss[0], DataOut, &unLen);

if (status == MFRC522::STATUS_OK)
{
rlen[1] = unLen / 8 - 2;
status = MI_OK;
}
else
status = MI_ERR;
return status; //返回结果
}
byte tt[2];
byte lenATQA = 2;
MFRC522::StatusCode statusRe;

void loop() {

NewCard = 0;

//通过ATQA获取卡片类型
statusRe = mfrc522.PICC_RequestA(tt, &lenATQA);
if (statusRe != MFRC522::STATUS_OK)
{
NewCard = 0;
delay(200);
return;
}
else
{
memset(DataBuf, 0x00, MAXRLEN);
Serial.println("#######################################################################");
Serial.println("Find a new card.");
Serial.print("Card type: 0x"); Serial.print(tt[0], HEX); Serial.print(" "); Serial.println(tt[1], HEX);

//选择卡
Serial.println("Select the card.");
mfrc522.PICC_Select(&mfrc522.uid);
PrintUid();
Serial.println();

//复位CPU卡 RATS
Serial.println("Reset the card (RATS).");
if (MI_OK == pro_reset(DataBuf, tt))
{
Serial.println("CPU card reset succeed.");
Serial.println();
}
else
{
Serial.println("CPU card reset failed.");
return;
}
delay(500);


//选择MF
Serial.println("Select MF.");
memset(DataBuf, 0x00, MAXRLEN);
if (MI_OK == SelectMf(DataBuf, tt))
{
Serial.println("Select MF succeed.");
Serial.println();
}
else
{
Serial.println("Select MF failed.");
return;
}

//获取随机数
Serial.println("Catch rand number.");
if (MI_OK == CatchRandNum(DataBuf, tt))
{
Serial.println("Catch rand number succeed.");
}
else
{
Serial.println("Catch rand number failed.");
return;
}
digitalWrite(3, HIGH);
digitalWrite(5, HIGH);
NewCard = 1;
delay(50);
}

digitalWrite(6, HIGH);
delay(50);
digitalWrite(3, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(100);
}


串口log:
...全文
371 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
asdf asdfa 2019-02-18
  • 打赏
  • 举报
回复
引用 4 楼 xqhrs232的回复:
[quote=引用 3 楼 312494845 的回复:] [quote=引用 2 楼 xqhrs232的回复:]你这个LOG不是都显示成功吗?
返回6D 00意思是不能识别该命令[/quote] 我只看见了3格succeed[/quote] 代码只检测是否受到正确的数据长度
xqhrs232 2019-02-17
  • 打赏
  • 举报
回复
引用 3 楼 312494845 的回复:
[quote=引用 2 楼 xqhrs232的回复:]你这个LOG不是都显示成功吗?
返回6D 00意思是不能识别该命令[/quote] 我只看见了3格succeed
asdf asdfa 2019-02-16
  • 打赏
  • 举报
回复
引用 2 楼 xqhrs232的回复:
你这个LOG不是都显示成功吗?
返回6D 00意思是不能识别该命令
xqhrs232 2019-02-16
  • 打赏
  • 举报
回复
你这个LOG不是都显示成功吗?
xqhrs232 2019-02-16
  • 打赏
  • 举报
回复
做个记号!!!

21,595

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧