📄 m500auc.c
字号:
{
lastBits = ReadIO(RegSecondaryStatus) & 0x07; /* 取出最后三位 */
if (lastBits) /* 最后三位为1-7,不全有效 */
info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
else /* 最后三位为0,全有效 */
info->nBitsReceived += info->nBytesReceived * 8;
}
}
else
{
info->collPos = 0x00; /* 无碰撞 */
}
}
MpIsrInfo = 0;
MpIsrOut = 0;
return status;
}
///////////////////////////////////////////////////////////////////////
// 置RC500寄存器bit
///////////////////////////////////////////////////////////////////////
char SetBitMask(unsigned char reg,unsigned char mask)
{ /* 相应的寄存器(REG),相应的屏蔽位(MASK) */
char idata tmp = 0x00;
tmp = ReadIO(reg);
WriteIO(reg,tmp | mask); /* 写入 */
return 0x00;
}
///////////////////////////////////////////////////////////////////////
// 清RC500寄存器bit
///////////////////////////////////////////////////////////////////////
char ClearBitMask(unsigned char reg,unsigned char mask)
{ /* 相应的寄存器(REG),相应的屏蔽位(MASK) */
char idata tmp = 0x00;
tmp = ReadIO(reg);
WriteIO(reg,tmp & ~mask); /* 写入 */
return 0x00;
}
///////////////////////////////////////////////////////////////////////
/* 清缓冲区标志,这样RC500的FIFO取就可供单片机或RC500状态机使用 */
///////////////////////////////////////////////////////////////////////
void FlushFIFO(void)
{
SetBitMask(RegControl,0x01); /* 控制寄存器地址:09H------置1(FIFOFLUSH=1) */
}
///////////////////////////////////////////////////////////////////////
// Value format operations for Mifare Standard card ICs
/* 改变MIFARE1卡内部EEROM的内容(单调增加,单调减少,数据检验操作) */
///////////////////////////////////////////////////////////////////////
char M500PiccValue(unsigned char dd_mode,
unsigned char addr,
unsigned char *value,
unsigned char trans_addr)
{ /* VALUE:连续写入的四字节指针,TRANS_ADDR:指向的改变后的数据要存入的地址 */
char status = MI_OK; /* SATUS:置初值 */
/* DD_MODE:三种命令模式,ADDR:指向的要改变数据单元的地址 */
M500PcdSetTmo(1); /* 初始化计时器--方式1 */
ResetInfo(MInfo); /* Minfo=INFO */
SerBuffer[0] = dd_mode; /* 93h,95h,97h三种命令模式 */
SerBuffer[1] = addr; /* ADDR:指向的要改变数据单元的地址 */
MInfo.nBytesToSend = 2; /* 要发送的字节数 */
status = M500PcdCmd(PCD_TRANSCEIVE,
SerBuffer,
&MInfo);
/* 执行先送后接指令后返回STATUS */
if (status != MI_NOTAGERR) /* MI_NOTAGERR=没有卡在此场里 */
{ /* 有卡在此场里 */
if (MInfo.nBitsReceived != 4) /* 收到的数据不是4比特 */
{
status = MI_BITCOUNTERR; /* 置收到错误的比特数目标志位 */
}
else /* 收到的数据是4比特 */
{
SerBuffer[0] &= 0x0f; /* 取出低四位 */
switch(SerBuffer[0])
{
case 0x00:
status = MI_NOTAUTHERR; /* 0000=置收到错误的比特数目标志位 */
break;
case 0x0a: /* 1010=置命令正确执行位 */
status = MI_OK;
break;
case 0x01: /* 0001=置数据结构错误位 */
status = MI_VALERR;
break;
default:
status = MI_CODEERR; /* 收到NACK,发送的数据出错(CRC,PARITY) */
break;
}
}
}
if ( status == MI_OK)
{ /* TRANSCEIVE命令执行成功 */
M500PcdSetTmo(3); /* 初始化计时器--方式3 */
ResetInfo(MInfo); /* Minfo=INFO */
memcpy(SerBuffer,value,4); /* 将缓冲区里放入要改变的数据 */
MInfo.nBytesToSend = 4; /* 要发送的字节数4 */
status = M500PcdCmd(PCD_TRANSCEIVE, /* 执行先送后接指令后返回STATUS */
SerBuffer,
&MInfo);
if (status == MI_OK) /* 上条TRANSCEIVE命令执行成功 */
{
if (MInfo.nBitsReceived != 4) /* 收到的数据不是4比特 */
{
status = MI_BITCOUNTERR; /* MI_NOTAGERR=没有卡在此场里 */
}
else /* 收到的数据是4比特 */
{
SerBuffer[0] &= 0x0f; /* 取出低四位 */
switch(SerBuffer[0])
{
case 0x00: /* 0000=置收到错误的比特数目标志位 */
status = MI_NOTAUTHERR;
break;
case 0x01: /* 0001=置数据结构错误位 */
status = MI_VALERR;
break;
default: /* 收到NACK,发送的数据出错(CRC,PARITY) */
status = MI_CODEERR;
break;
}
}
}
else /* 上条TRANSCEIVE命令执行不成功 */
{
if (status == MI_NOTAGERR ) /* MI_NOTAGERR=没有卡在此场里 */
status = MI_OK; /* 恢复初始值 */
}
}
if (status == MI_OK) /* */
{
ResetInfo(MInfo); /* Minfo=INFO */
SerBuffer[0] = PICC_TRANSFER; /* 这才是真正的改变卡内存的指令(下载) */
SerBuffer[1] = trans_addr;
MInfo.nBytesToSend = 2;
status = M500PcdCmd(PCD_TRANSCEIVE, /* 执行传送指令,下载到卡的EEROM */
SerBuffer,
&MInfo); /* TRANSCEIVE指令的出口参数,一部分状态信息 */
if (status != MI_NOTAGERR)
{ /* 有卡在此场里 */
if (MInfo.nBitsReceived != 4)
{
status = MI_BITCOUNTERR; /* 收到的数据不是4比特 */
}
else /* 收到的数据是4比特 */
{
SerBuffer[0] &= 0x0f; /* 取出低四位 */
switch(SerBuffer[0])
{
case 0x00: /* 0000=置收到错误的比特数目标志位 */
status = MI_NOTAUTHERR;
break;
case 0x0a:
status = MI_OK; /* 1010=置命令正确执行位 */
break;
case 0x01: /* 0001=置数据结构错误位 */
status = MI_VALERR;
break;
default: /* 收到NACK,发送的数据出错(CRC,PARITY) */
status = MI_CODEERR;
break;
}
}
}
}
return status; /* 这个SWITCH作为整个函数的反馈值 */
}
///////////////////////////////////////////////////////////////////////
// Set card in HALT-state
/* 终止卡的操作 */
///////////////////////////////////////////////////////////////////////
char M500PiccHalt(void)
{
char idata status = MI_CODEERR; /* 将STATUS初值定为数据错 */
// ************* Cmd Sequence **********************************
ResetInfo(MInfo); /* Minfo=INFO */
SerBuffer[0] = PICC_HALT ; /* 执行IDLE指令,关闭卡 */
SerBuffer[1] = 0x00; /* 同上 */
MInfo.nBytesToSend = 2; /* 同上 */
status = M500PcdCmd(PCD_TRANSCEIVE, /* 调用命令执行程序 */
SerBuffer,
&MInfo);
if (status)
{
// timeout error ==> no NAK received ==> OK
if (status == MI_NOTAGERR || status == MI_ACCESSTIMEOUT)
{ /* 无卡响应,命令执行成功 */
status = MI_OK;
}
}
//reset command register - no response from tagit
WriteIO(RegCommand,PCD_IDLE); /* 有卡响应,命令执行不成功 */
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Reset the MF RC500
/* 重启RC500,开始新一轮寻卡 */
///////////////////////////////////////////////////////////////////////
char M500PcdReset(void)
{
char idata status = MI_OK; /* 状态初值 */
unsigned int idata timecnt=0; /* 局部计数器置初值 */
RC500RST = 0; /* 重启时序 */
delay_1ms(25);
RC500RST = 1;
delay_50us(200);
RC500RST = 0;
delay_50us(50);
timecnt=1000;
while ((ReadIO(RegCommand) & 0x3F) && timecnt--); /* 循环查询? */
if(!timecnt)
{
status = MI_RESETERR; /* timecnt=0,则置status为重起失败标志 */
}
if (status == MI_OK) /* 如果在timecnt没变成0时status就被置命令执行成功 */
{
//WriteIO(RegPage,0x80);
if (ReadIO(RegCommand) != 0x00) /* 如果此时regcommand不为0 */
{
status = MI_INTERFACEERR; /* 则置status为接口出错(实质上是rc500没有响应单片机或是上位机) */
}
}
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Configures the MF RC500
/* 新一轮认卡后的寄存器配置过程 */
///////////////////////////////////////////////////////////////////////
char M500PcdConfig(void)
{
char idata status;
if ((status = M500PcdReset()) == MI_OK) /* 如果返回的状态值是重启成功 */
{
WriteIO(RegClockQControl,0x00); /* q通道时钟控制寄存器置0,自动校准时钟偏差 */
WriteIO(RegClockQControl,0x40); /* q通道时钟控制寄存器置40,不校准时钟偏差 ? */
delay_50us(2); /* 延时100us */
ClearBitMask(RegClockQControl,0x40); /* q通道时钟控制寄存器又置0,自动校准时钟偏差(1BH) */
WriteIO(RegBitPhase,0xAD); /* 选择发送与接收之间的时钟相位差,默认值:oxad -----important(1FH) */
WriteIO(RegRxThreshold,0xFF); /* 选择RX脚输入信号的门限电压值0XFF(1CH) */
WriteIO(RegRxControl2,0x01); /* 接收控制--使用内部解码器,用Q时钟,接收器时常处于激活态(1EH) */
WriteIO(RegFIFOLevel,0x1A); /* FIFO饱和度水平=1A(29H) */
WriteIO(RegTimerControl,0x02); /* 发送一完成自动开始计数(2BH) */
WriteIO(RegIRqPinConfig,0x03); /* IRQ脚配置:输出电平与IRQ标志相反,工作于标准CMOS输出模式(2DH) */
M500PcdRfReset(1); /* 调用射频重启函数 */
}
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////
// Key loading into the MF RC500's EEPROM
/* 将主密钥送入RC500的EEROM */
///////////////////////////////////////////////////////////////
char M500PcdLoadKeyE2(unsigned char key_type,
unsigned char sector, /* 存放密钥的EEROM块地址 */
unsigned char *uncoded_keys)
{
signed char status = MI_OK;
unsigned int e2addr = 0x80 + sector * 0x18; /* EEROM地址为两个字节 */
unsigned char coded_keys[12];
if (key_type == PICC_AUTHENT1B) /* 如果是B类卡 */
{
e2addr += 12; /* 取12字节以后的作为密钥地址 */
}
if ((status = M500HostCodeKey(uncoded_keys,coded_keys)) == MI_OK) /* 如果密钥编码成功 */
{
status = PcdWriteE2(e2addr,12,coded_keys); /* 将主密钥(12字节)送入RC500的EEROM */
}
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Write the MF RC500's EEPROM
/* 写RC500's EEPROM */
///////////////////////////////////////////////////////////////////////
char PcdWriteE2(unsigned int startaddr, /* EEROM地址为两个字节 */
unsigned char length, /* 长度 */
unsigned char* _data) /* 密钥在单片机里的初始地址 */
{
char status = MI_OK;
ResetInfo(MInfo);
SerBuffer[0] = startaddr & 0xFF; /* 存放密钥的EEROM块地址 */
SerBuffer[1] = (startaddr >> 8) & 0xFF; /* STARTADDR为整型变量,16BIT */
memcpy(SerBuffer + 2,_data,length); /* 将密钥拷贝到发送缓冲区 */
MInfo.nBytesToSend = length + 2; /* 发送14字节 */
status = M500PcdCmd(PCD_WRITEE2, /* 执行写RC500's EEPROM命令 */
SerBuffer,
&MInfo);
return status; /* 返回状态值 */
}
///////////////////////////////////////////////////////////////////////
// Select Command defined in ISO14443(MIFARE)
/* 配置MFOUT/MFIN两脚输出内容 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -