📄 mfrc522.c
字号:
** MF3 IC D40 的类型号:0344H
****************************************************************************************/
char PiccRequest(unsigned char req_code, unsigned char idata *atq)
{
char status = STATUS_SUCCESS;
unsigned char idata SerBuffer[2];
/************* initialize *****************/
RcModifyReg(JREG_STATUS2, 0, JBIT_CRYPTO1ON); /* disable Crypto if activated before */
RcSetReg(JREG_COLL, JBIT_VALUESAFTERCOLL); //active values after coll
RcModifyReg(JREG_TXMODE, 0, JBIT_CRCEN); //disable TxCRC and RxCRC
RcModifyReg(JREG_RXMODE, 0, JBIT_CRCEN);
RcSetReg(JREG_BITFRAMING, REQUEST_BITS);
/* set necessary parameters for transmission */
ResetInfo();
SerBuffer[0] = req_code;
MInfo.nBytesToSend = 1;
/* Set timeout for REQA, ANTICOLL, SELECT*/
SetTimeOut(4);
status = M522PcdCmd(JCMD_TRANSCEIVE,
SerBuffer);
if(status == STATUS_SUCCESS || status == STATUS_COLLISION_ERROR)
{
if(MInfo.nBytesReceived != ATQA_LENGTH || MInfo.nBitsReceived != 0x00)
{
status = STATUS_PROTOCOL_ERROR;
}
else
{
memcopy(atq,SerBuffer,2);
}
}
else
{ /* reset atqa parameter */
atq[0] = 0x00;
atq[1] = 0x00;
}
//RcSetReg(JREG_BITFRAMING, 0);
return status;
}
/****************************************************************************************
** 函数原型: char PiccCascAnticoll(unsigned char sel_code,unsigned char bitcount,
** unsigned char idata *snr);
** 函数功能: 防碰撞
** 入口参数: unsigned char sel_code ; 防碰撞的等级
** unsigned char bitcount ; 已知UID的位数
** unsigned char idata *snr ; 已知的UID
** 出口参数: unsigned char idata *snr ; UID
** 返 回 值: 执行结果
** 描 述:
****************************************************************************************/
char PiccCascAnticoll(unsigned char sel_code,
unsigned char bitcount,
unsigned char idata *snr)
{
char status = STATUS_SUCCESS;
unsigned char idata SerBuffer[7];
unsigned char i;
unsigned char complete = 0; /* signs end of anticollission loop */
unsigned char rbits = 0; /* number of total received bits */
unsigned char nbits = 0; /* */
unsigned char nbytes = 0; /* */
unsigned char byteOffset; /* stores offset for ID copy if uncomplete last byte was sent */
/* initialise relvant bytes in internal buffer */
for(i=2;i<7;i++)
SerBuffer[i] = 0x00;
/* disable TxCRC and RxCRC */
RcModifyReg(JREG_TXMODE, 0, JBIT_CRCEN);
RcModifyReg(JREG_RXMODE, 0, JBIT_CRCEN);
/* activate deletion of bits after coll */
RcSetReg(JREG_COLL, 0);
/* init parameters for anticollision */
while(!complete && (status == STATUS_SUCCESS))
{
/* if there is a communication problem on the RF interface, bcnt
could be larger than 32 - folowing loops will be defective. */
if(bitcount > SINGLE_UID_LENGTH)
{
status = STATUS_INVALID_PARAMETER;
continue;
}
/* prepare data length */
nbits = (unsigned char)(bitcount % BITS_PER_BYTE);
nbytes = (unsigned char)(bitcount / BITS_PER_BYTE);
if(nbits)
nbytes++;
/* prepare data buffer */
SerBuffer[0] = sel_code;
SerBuffer[1] = (unsigned char)(NVB_MIN_PARAMETER + ((bitcount / BITS_PER_BYTE) << UPPER_NIBBLE_SHIFT) + nbits);
for(i=0;i<nbytes;i++)
SerBuffer[2+i] = snr[i]; /* copy serial number to tranmit buffer */
/* set TxLastBits and RxAlign to number of bits sent */
RcSetReg(JREG_BITFRAMING, (unsigned char)((nbits << UPPER_NIBBLE_SHIFT) | nbits));
/* prepare data for common transceive */
ResetInfo();
MInfo.nBytesToSend = (unsigned char)(nbytes + 2);
SetTimeOut(100);
status = M522PcdCmd(JCMD_TRANSCEIVE, SerBuffer);
if(status == STATUS_COLLISION_ERROR || status == STATUS_SUCCESS)
{
/* store number of received data bits and bytes internaly */
rbits = (unsigned char)(MInfo.nBitsReceived + (MInfo.nBytesReceived << 3) - nbits);
if((rbits + bitcount) > COMPLETE_UID_BITS)
{
status = STATUS_BITCOUNT_ERROR;
continue;
}
/* increment number of bytes received if also some bits received */
if(MInfo.nBitsReceived)
MInfo.nBytesReceived++;
/* reset offset for data copying */
byteOffset = 0;
/* if number of bits sent are not 0, write first received byte in last of sent */
if(nbits)
{ /* last byte transmitted and first byte received are the same */
snr[nbytes - 1] |= SerBuffer[0];
byteOffset++;
}
for(i=0;i<(4-nbytes);i++)
snr[nbytes + i] = SerBuffer[i + byteOffset];
if(status == STATUS_COLLISION_ERROR)
{
/* calculate new bitcount value */
bitcount = (unsigned char)(bitcount + rbits);
status = STATUS_SUCCESS;
} else
{
if((snr[0] ^ snr[1] ^ snr[2] ^ snr[3]) != SerBuffer[i + byteOffset])
{
status = STATUS_WRONG_UID_CHECKBYTE;
continue;
}
complete=1;
}
}
}
/* clear RxAlign and TxLastbits */
RcSetReg(JREG_BITFRAMING, 0);
/* activate values after coll */
RcSetReg(JREG_COLL, JBIT_VALUESAFTERCOLL);
return status;
}
/****************************************************************************************
** 函数原型: char PiccCascSelect(unsigned char sel_code,unsigned char idata *snr,
** unsigned char idata *sak);
** 函数功能: 防碰撞
** 入口参数: unsigned char sel_code ; 防碰撞的等级
** unsigned char idata *snr ; UID
** 出口参数: unsigned char idata *sak ; SAK
** 返 回 值: 执行结果
** 描 述:
****************************************************************************************/
char PiccCascSelect(unsigned char sel_code,
unsigned char idata *snr,
unsigned char idata *sak)
{
char status = STATUS_SUCCESS;
/* define local variables */
unsigned char i;
unsigned char idata SerBuffer[7];
/* activate CRC */
RcModifyReg(JREG_TXMODE, 1, JBIT_CRCEN);
RcModifyReg(JREG_RXMODE, 1, JBIT_CRCEN);
/* prepare data stream */
SerBuffer[0] = sel_code; /* command code */
SerBuffer[1] = NVB_MAX_PARAMETER; /* parameter */
for(i=0;i<4;i++)
SerBuffer[2+i] = snr[i]; /* serial numbner bytes 1 to 4 */
SerBuffer[6] = (unsigned char)(snr[0] ^ snr[1] ^ snr[2] ^ snr[3]); /* serial number check byte */
/* prepare data for common transceive */
ResetInfo();
MInfo.nBytesToSend = 0x07;
SetTimeOut(20);
status = M522PcdCmd(JCMD_TRANSCEIVE, SerBuffer);
if(status == STATUS_SUCCESS)
{
if(MInfo.nBytesReceived == SAK_LENGTH && MInfo.nBitsReceived == 0)
*sak = SerBuffer[0];
else
status = STATUS_BITCOUNT_ERROR;
}
return status;
}
/*************************************************
Function: AnticollSelect
Description:
Anticollision loop and selecte a card to operate
Parameter:
bcnt bit counter of known UID
snr buffer to store the card UID
Return:
char status of implement
**************************************************/
/*char AnticollSelect(unsigned char bcnt, unsigned char *snr)
{
unsigned char i;
char status=STATUS_SUCCESS;
unsigned char length, casc_code, length_in,sak,tmpSnr[12];
length_in = bcnt;
//* do loop for max. cascade level
for(i=0;i<MAX_CASCADE_LEVELS;i++)
{
if(length_in)
{
if(length_in > SINGLE_UID_LENGTH)
{
length = SINGLE_UID_LENGTH;
length_in -= SINGLE_UID_LENGTH;
}
else
{
length = length_in;
length_in = 0;
}
}
else
{
length = 0;
}
switch(i)
{
case 1: casc_code = SELECT_CASCADE_LEVEL_2;
memcopy(snr, tmpSnr+1,3);
break;
case 2: casc_code = SELECT_CASCADE_LEVEL_3;
break;
default: casc_code = SELECT_CASCADE_LEVEL_1;
break;
}
if(length != SINGLE_UID_LENGTH && status == STATUS_SUCCESS)
// do anticollission with selected level
status = CascAnticoll(casc_code,
length,
tmpSnr + i * 4);
if(status == STATUS_SUCCESS)
{
// select 1st cascade level uid
status = Select(casc_code, tmpSnr + i * 4, &sak);
// check if further cascade level is used
if(status == STATUS_SUCCESS)
{
// increase number of received bits in parameter
bcnt = (unsigned char)(SINGLE_UID_LENGTH * (i + 1)); //the actually length of the UID, you can return it.
// check if cascade bit is set
if(!(sak & CASCADE_BIT))
{
break;
}
}
}
else
{
break;
}
}
switch(i)
{
case 1: memcopy(snr+3, tmpSnr+4,4); //copy UID to snr buffer without CT(0x88)
break;
case 2: memcopy(snr+6, tmpSnr+4,4);
break;
default: memcopy(snr, tmpSnr,4);
break;
}
return status;
}
*/
/****************************************************************************************
** 函数原型: char PiccHalt(void)
** 函数功能: 将选择的卡挂起(ISO/IEC14443A-3)
** 入口参数: -
** 出口参数: -
** 返 回 值: 执行结果
** 描 述: 该函数是ISO/IEC14443A-3层协议
****************************************************************************************/
char PiccHalt(void)
{
char status = STATUS_SUCCESS;
unsigned char idata SerBuffer[2];
/* initialise data buffer */
SerBuffer[0] = HALTA_CMD;
SerBuffer[1] = HALTA_PARAM;
ResetInfo();
MInfo.nBytesToSend = HALTA_CMD_LENGTH;
SetTimeOut(10);
status = M522PcdCmd(JCMD_TRANSCEIVE, SerBuffer);
if(status == STATUS_IO_TIMEOUT)
status = STATUS_SUCCESS;
return status;
}
/****************************************************************************************
** 函数原型: char PiccAuthKey(unsigned char auth_mode,unsigned char idata *snr,
** unsigned char idata *key,unsigned char addr)
** 函数功能: 验证Mifare卡选择的扇区
** 入口参数: unsigned char auth_mode ; 验证模式阿:A密钥/B密钥
** unsigned char idata *snr ; 4字节UID
** unsigned char idata *key ; 6字节密钥
** unsigned char addr ; 验证的扇区号
** 出口参数: -
** 返 回 值: 执行结果
** 描 述:
****************************************************************************************/
char PiccAuthKey(unsigned char auth_mode,unsigned char idata *snr,
unsigned char idata *key,unsigned char addr)
{
char status;
unsigned char RegVal;
unsigned char idata SerBuffer[12];
ResetInfo();
SerBuffer[0] = auth_mode; // key A or key B
SerBuffer[1] = addr; // address to authentication
memcopy(SerBuffer+2,key,6); // 6bytes key
memcopy(SerBuffer+8,snr,4); // 4 bytes UID
MInfo.nBytesToSend = 12; // length
SetTimeOut(20);
status = M522PcdCmd(JCMD_AUTHENT, SerBuffer);
if(status == STATUS_SUCCESS)
{
RegVal = RcGetReg(JREG_STATUS2);
if((RegVal & 0x0f) != 0x08)
status = STATUS_AUTHENT_ERROR;
}
return status;
}
/****************************************************************************************
** 函数原型: char PiccRead(unsigned char addr, unsigned char idata *_data)
** 函数功能: 从指定的块号读出一块数据
** 入口参数: unsigned char addr ; 块号
** 出口参数: unsigned char idata *_data ; 读出的数据(16字节)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -