📄 fm1702.c
字号:
}
switch(col)
{
case 0: SPIWrite(Bit_Frame,0x00); break;
case 1: SPIWrite(Bit_Frame,0x11); RevBuffer[1] = (RevBuffer[1] | 0x01); break;
case 2: SPIWrite(Bit_Frame,0x22); RevBuffer[1] = (RevBuffer[1] | 0x02); break;
case 3: SPIWrite(Bit_Frame,0x33); RevBuffer[1] = (RevBuffer[1] | 0x03); break;
case 4: SPIWrite(Bit_Frame,0x44); RevBuffer[1] = (RevBuffer[1] | 0x04); break;
case 5: SPIWrite(Bit_Frame,0x55); RevBuffer[1] = (RevBuffer[1] | 0x05); break;
case 6: SPIWrite(Bit_Frame,0x66); RevBuffer[1] = (RevBuffer[1] | 0x06); break;
case 7: SPIWrite(Bit_Frame,0x77); RevBuffer[1] = (RevBuffer[1] | 0x07); break;
default: break;
}
}
/****************************************************************/
/*名称: Init_FM1702 */
/*功能: 该函数实现对FM1702初始化操作*/
/*输入: mode:工作模式, 0:TYPEA模式*/
/* 1:TYPEB模式*/
/* 2:上海模式*/
/*输出: N/A */
/****************************************************************/
void Init_FM1702(uchar mode)
{
uchar temp;
uint i;
// unsigned int idata timecnt=0;
RF_SCK = 1;
RF_MISO = 1;
RF_MOSI = 1;
RF_RST = 1; /* FM1702复位 */
for(i = 0; i < 0x1fff; i++)
{
_nop_(); /*等待约140ms, 11.0592*/
}
RF_RST = 0;
for(i = 0; i < 0x1fff; i++)
{
_nop_();
}
////////////////////////////////////////////////////////////////////////////
while(temp = SPIRead(Command) != 0) /* 等待Command = 0,FM1702复位成功 */
{
_nop_();
}
////////////////////////////////////////////////////////////////////////////
// delay_10ms(1);
SPIWrite(Page_Sel,0x80);
for(i = 0; i < 0x1fff; i++) /* 延时 */
{
if(temp=SPIRead(Command) == 0x00)
{
SPIWrite(Page_Sel,0x00);
}
}
// P2 = SPIRead(TimerClock); //for debug
SPIWrite(TimerClock,0x0b); //address 2AH /* 定时器周期设置寄存器 */
SPIWrite(TimerControl,0x02); //address 2BH /* 定时器控制寄存器 */
SPIWrite(TimerReload,0x42); //address 2CH /* 定时器初值寄存器 */
SPIWrite(InterruptEn,0x7f); //address 06H /* 中断使能/禁止寄存器 */
// temp = SPIRead(InterruptEn);
SPIWrite(Int_Req,0x7f); //address 07H /* 中断请求标识寄存器 */
SPIWrite(MFOUTSelect,0x02); //address 26H /* mf OUT 选择配置寄存器 */
//设置调制器的输入源为内部编码器, 并且设置TX1和TX2
SPIWrite(TxControl,0x5b); //address 11H /* 发送控制寄存器 */
SPIWrite(RxControl2,0x01);
// SPIWrite(RxControl1,0x73);
SPIWrite(RxWait,0x05);
if(mode ==2)
{
SPIWrite(TypeSH,0x01);
}
else
{
SPIWrite(TypeSH,0x00);
}
}
/****************************************************************/
/*名称: Command_Send */
/*功能: 该函数实现向FM1702发送命令集的功能*/
/*输入: count, 待发送命令集的长度*/
/* buff, 指向待发送数据的指针*/
/* Comm_Set, 命令码*/
/*输出: TRUE, 命令被正确执行*/
/* FALSE, 命令执行错误*/
/****************************************************************/
uchar Command_Send(uchar count, uchar idata *buff, uchar Comm_Set)
{
uint j;
uchar idata temp, temp1;
SPIWrite(Command,0x00);
temp = Clear_FIFO();
Write_FIFO(count, buff);
// temp = SPIRead(MFOUTSelect);
SPIWrite(Command,Comm_Set); /* 命令执行 */
for(j = 0; j < RF_TimeOut; j++) /* 检查命令执行否 */
{
// temp = SPIRead(MFOUTSelect); //??
temp = SPIRead(Command);
temp1 = SPIRead(Int_Req) & 0x80;
if((temp == 0x00) || (temp1 == 0x80))
{
return TRUE;
}
}
return FALSE;
}
/****************************************************************/
/*名称: Read_E2 */
/*功能: 该函数实现从FM1702的EE中读出数据*/
/*输入: lsb, EE地址(低字节) */
/* msb, EE地址(高字节) */
/* count, 待读出数据EE的字节个数*/
/* buff, 指向待读出数据的指针*/
/*输出: TRUE, EE数据正确读出*/
/* FALSE, EE数据读出有误*/
/****************************************************************/
uchar Read_E2(uchar lsb, uchar msb, uchar count, uchar idata *buff)
{
uchar temp;
*buff = lsb;
*(buff + 1) = msb;
*(buff + 2) = count;
temp = Command_Send(3, buff, ReadE2);
Read_FIFO(buff);
if(temp == FALSE) return(TRUE);
return(FALSE);
}
/****************************************************************/
/*名称: Write_E2 */
/*功能: 该函数实现向FM1702的EE中写入数据*/
/*输入: lsb, EE地址(低字节) */
/* msb, EE地址(高字节) */
/* count, 待写入数据EE的字节个数*/
/* buff, 指向待写入数据的指针*/
/*输出: TRUE, EE数据正确写入*/
/* FALSE, EE数据写入有误*/
/****************************************************************/
uchar Write_E2(uchar lsb, uchar msb, uchar count, uchar idata *buff)
{
uchar idata temp, i;
for(i = 0; i < count; i++)
{
*(buff + count - i + 2) = *(buff - i + count);
}
*buff = lsb;
*(buff + 1) = msb;
temp = Command_Send(count + 2, buff, WriteE2);
temp = SPIRead(SecondaryStatus);
temp = temp & 0x40;
if(temp == 0x40)
{
SPIWrite(Command,0x00); //added 2006/03/15
return TRUE;
}
return FALSE;
}
/****************************************************************/
/*名称: MIF_Halt */
/*功能: 该函数实现暂停MIFARE卡*/
/*输入: N/A */
/*输出: FM1702_OK: 应答正确*/
/* FM1702_PARITYERR: 奇偶校验错*/
/* FM1702_CRCERR: CRC校验错*/
/* FM1702_NOTAGERR: 无卡*/
/****************************************************************/
uchar MIF_Halt(void)
{
uchar temp;
uint i;
SPIWrite(CRCPresetLSB,0x63);
SPIWrite(CWConductance,0x3f);
SPIWrite(ChannelRedundancy,0x03);
*RevBuffer = RF_CMD_HALT;
*(RevBuffer + 1) = 0x00;
temp = Command_Send(2, RevBuffer, Transmit);
if(temp == TRUE)
{
for(i = 0; i < 0x50; i++)
{
_nop_();
}
return FM1702_OK;
}
else
{
temp = SPIRead(ErrorFlag);
if((temp & 0x02) == 0x02)
{
return(FM1702_PARITYERR);
}
if((temp & 0x04) == 0x04)
{
return(FM1702_FRAMINGERR);
}
return(FM1702_NOTAGERR);
}
}
///////////////////////////////////////////////////////////////////////
// 转换密钥格式
///////////////////////////////////////////////////////////////////////
char M500HostCodeKey( uchar *uncoded, uchar *coded)
{
char idata status = FM1702_OK;
uchar idata cnt = 0;
uchar idata ln = 0;
uchar idata hn = 0;
for (cnt = 0; cnt < 6; cnt++)
{
ln = uncoded[cnt] & 0x0F;
hn = uncoded[cnt] >> 4;
coded[cnt * 2 + 1] = (~ln << 4) | ln;
coded[cnt * 2 ] = (~hn << 4) | hn;
}
return FM1702_OK;
}
/****************************************************************/
/*名称: Load_keyE2 */
/*功能: 该函数实现把E2中密码存入FM1702的keyRevBuffer中*/
/*输入: Secnr: EE起始地址*/
/*输出: True: 密钥装载成功*/
/* False: 密钥装载失败*/
/****************************************************************/
uchar Load_keyE2_CPY(uchar Secnr, uchar Mode)
{
char idata status;
uchar temp;
uchar msb = 0;
uchar lsb = 0;
uchar coded_keys[12];
uchar temp1;
if(Secnr >= 0x20)
{
temp1 = Secnr - 0x20;
Secnr = 0x20 + temp1 * 4;
}
temp = Secnr * 12;
if(Mode == RF_CMD_AUTH_LA)
{
if(temp >= 0x80)
{
lsb = temp - 0x80;
msb = 0x01;
}
else
{
lsb = temp + 0x80;
msb = 0x00;
}
}
else
{
msb = 0x01;
lsb = temp + 0x40;
}
status = M500HostCodeKey(&RevBuffer[3],coded_keys);////////////////
/* status = Write_E2(lsb, msb, 12, coded_keys); ////////////////
RevBuffer[0] = lsb;
RevBuffer[1] = msb;
temp = Command_Send(2, RevBuffer, LoadKeyE2);*/ //注释掉,是因为该处是从EEPROM加载密钥
Command_Send(12,coded_keys,LoadKey); //从FIFO加载密钥 ,修改耿学涛 09。6。2。
temp = SPIRead(ErrorFlag) & 0x40;
if(temp == 0x40)
{
return FALSE;
}
return TRUE;
}
/****************************************************************/
/*名称: Request */
/*功能: 该函数实现对放入FM1702操作范围之内的卡片的Request操作*/
/*输入: mode: ALL(监测所以FM1702操作范围之内的卡片) */
/* STD(监测在FM1702操作范围之内处于HALT状态的卡片) */
/*输出: FM1702_NOTAGERR: 无卡*/
/* FM1702_OK: 应答正确*/
/* FM1702_REQERR: 应答错误*/
/****************************************************************/
uchar Request(uchar mode)
{
uchar idata temp;
SPIWrite(CRCPresetLSB,0x63); //CRCPresetLSB address is 0x23
SPIWrite(CWConductance,0x3f);
RevBuffer[0] = mode; /* Request模式选择 */
SPIWrite(Bit_Frame,0x07);
SPIWrite(ChannelRedundancy,0x03);
temp = SPIRead(Control);
temp = temp & (0xf7);
SPIWrite(Control,temp); //Control reset value is 00
temp = Command_Send(1, RevBuffer, Transceive); //Transceive=0x1E /* 发送接收命令 */
if(temp == FALSE)
{
return FM1702_NOTAGERR;
}
Read_FIFO(RevBuffer); /* 从FIFO中读取应答信息到RevBuffer[]中 */
temp = Judge_Req(RevBuffer); /* 判断应答信号是否正确 */
if(temp == TRUE)
{
tagtype[0] = RevBuffer[0];
tagtype[1] = RevBuffer[1];
return FM1702_OK;
}
return FM1702_REQERR;
}
/****************************************************************/
/*名称: AntiColl */
/*功能: 该函数实现对放入FM1702操作范围之内的卡片的防冲突检测*/
/*输入: N/A */
/*输出: FM1702_NOTAGERR: 无卡*/
/* FM1702_BYTECOUNTERR: 接收字节错误*/
/* FM1702_SERNRERR: 卡片序列号应答错误*/
/* FM1702_OK: 卡片应答正确*/
/****************************************************************/
uchar AntiColl(void)
{
uchar temp;
uchar i;
uchar row, col;
uchar pre_row;
row = 0;
col = 0;
pre_row = 0;
SPIWrite(CRCPresetLSB,0x63);
SPIWrite(CWConductance,0x3f);
// SPIWrite(ModConductance,0x3f);
RevBuffer[0] = RF_CMD_ANTICOL;
RevBuffer[1] = 0x20;
SPIWrite(ChannelRedundancy,0x03);
temp = Command_Send(2, RevBuffer, Transceive);
while(1)
{
if(temp == FALSE)
{
return(FM1702_NOTAGERR);
}
//temp = ErrorFlag;
temp = SPIRead(FIFO_Length);
if(temp == 0)
{
return FM1702_BYTECOUNTERR;
}
Read_FIFO(RevBuffer);
Save_UID(row, col, temp); /* 将收到的UID放入UID数组中 */
temp = SPIRead(ErrorFlag); /* 判断接収数据是否出错 */
temp = temp & 0x01;
if(temp == 0x00)
{
temp = Check_UID(); /* 校验收到的UID */
if(temp == FALSE)
{
return(FM1702_SERNRERR);
}
return(FM1702_OK);
}
else
{
temp = SPIRead(CollPos); /* 读取冲突检测寄存器 */
row = temp / 8;
col = temp % 8;
RevBuffer[0] = RF_CMD_ANTICOL;
Set_BitFraming(row + pre_row, col); /* 设置待发送数据的字节数 */
pre_row = pre_row + row;
for(i = 0; i < pre_row + 1; i++)
{
RevBuffer[i + 2] = UID[i];
}
if(col != 0x00)
{
row = pre_row + 1;
}
else
{
row = pre_row;
}
temp = Command_Send(row + 2, RevBuffer, Transceive);
}
}
}
/****************************************************************/
/*名称: Select_Card */
/*功能: 该函数实现对放入FM1702操作范围之内的某张卡片进行选择*/
/*输入: N/A */
/*输出: FM1702_NOTAGERR: 无卡*/
/* FM1702_PARITYERR: 奇偶校验错*/
/* FM1702_CRCERR: CRC校验错*/
/* FM1702_BYTECOUNTERR: 接收字节错误*/
/* FM1702_OK: 应答正确*/
/* FM1702_SELERR: 选卡出错*/
/****************************************************************/
uchar Select_Card(void)
{
uchar temp, i;
SPIWrite(CRCPresetLSB,0x63);
SPIWrite(CWConductance,0x3f);
RevBuffer[0] = RF_CMD_SELECT;
RevBuffer[1] = 0x70;
for(i = 0; i < 5; i++)
{
RevBuffer[i + 2] = UID[i];
}
SPIWrite(ChannelRedundancy,0x0f);
temp = Command_Send(7, RevBuffer, Transceive);
if(temp == FALSE)
{
return(FM1702_NOTAGERR);
}
else
{
temp = SPIRead(ErrorFlag);
if((temp & 0x02) == 0x02) return(FM1702_PARITYERR);
if((temp & 0x04) == 0x04) return(FM1702_FRAMINGERR);
if((temp & 0x08) == 0x08) return(FM1702_CRCERR);
temp = SPIRead(FIFO_Length);
if(temp != 1) return(FM1702_BYTECOUNTERR);
Read_FIFO(RevBuffer); /* 从FIFO中读取应答信息 */
temp = *RevBuffer;
if((temp == 0x18) || (temp == 0x08) || (temp == 0x88) || (temp == 0x53)) /* 判断应答信号是否正确 */
return(FM1702_OK);
else
return(FM1702_SELERR);
}
}
/****************************************************************/
/*名称: Authentication */
/*功能: 该函数实现密码认证的过程*/
/*输入: UID: 卡片序列号地址*/
/* SecNR: 扇区号*/
/* mode: 模式*/
/*输出: FM1702_NOTAGERR: 无卡*/
/* FM1702_PARITYERR: 奇偶校验错*/
/* FM1702_CRCERR: CRC校验错*/
/* FM1702_OK: 应答正确*/
/* FM1702_AUTHERR: 权威认证有错*/
/****************************************************************/
uchar Authentication(uchar idata *UID, uchar SecNR, uchar mode)
{
uchar idata i;
uchar idata temp, temp1;
uchar temp0;
if(SecNR >= 0x20)
{
temp0 = SecNR -0x20;
SecNR = 0x20 + temp0 * 4;
}
SPIWrite(CRCPresetLSB,0x63);
SPIWrite(CWConductance,0x3f);
// SPIWrite(ModConductance,0X3f);
// temp1 = SPIRead(Control);
// temp1 = temp1 & 0xf7;
// SPIWrite(Control,temp1);
if(mode == RF_CMD_AUTH_LB)
RevBuffer[0] = RF_CMD_AUTH_LB;
else
RevBuffer[0] = RF_CMD_AUTH_LA;
RevBuffer[1] = SecNR * 4 + 3;
for(i = 0; i < 4; i++)
{
RevBuffer[2 + i] = UID[i];
}
SPIWrite(ChannelRedundancy,0x0f);
temp = Command_Send(6, RevBuffer, Authent1);
if(temp == FALSE)
{
return 0x99;
}
temp = SPIRead(ErrorFlag); //ErrorFlag address is 0x0A.
if((temp & 0x02) == 0x02) return FM1702_PARITYERR;
if((temp & 0x04) == 0x04) return FM1702_FRAMINGERR;
if((temp & 0x08) == 0x08) return FM1702_CRCERR;
temp = Command_Send(0, RevBuffer, Authent2);
if(temp == FALSE)
{
return 0x88;
}
temp = SPIRead(ErrorFlag);
if((temp & 0x02) == 0x02) return FM1702_PARITYERR;
if((temp & 0x04) == 0x04) return FM1702_FRAMINGERR;
if((temp & 0x08) == 0x08) return FM1702_CRCERR;
temp1 = SPIRead(Control);
temp1 = temp1 & 0x08;
if(temp1 == 0x08)
{
return FM1702_OK;
}
return FM1702_AUTHERR;
}
/****************************************************************/
/*名称: MIF_Read */
/*功能: 该函数实现读MIFARE卡块的数值*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -