⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fm1702.c

📁 FM1702SL.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
	}

	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 + -