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

📄 fm1702.c

📁 复旦RF1702读写卡应用
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <string.h>
#include <stdio.h>
#include <absacc.h>
#include <intrins.h>

#include "FM1702.h"
#include "reg52.h"

#define NO_TIMER2           1
bit CmdValid;
unsigned char cardtype;

//uchar idata	readdata[16];	    /* 读写数据缓冲区 */
//uchar idata	value[4];	        /* 增减的数值 */
//uchar idata	KeySet;		        /* 密码类型 */
uchar idata	tagtype[2];	            /* 卡片标识字符 */

/* FM1715变量定义 */
//uchar idata	PRO_SendBuf[16];	/* 发送处理缓冲区16 BYTE */
//uchar idata	PRO_RecvBuf[16];	/* 接收处理缓冲区16 BYTE */
uchar idata	buffer[30];             /* FM1715命令发送接收缓冲区 */
uchar idata	UID[5];                 /* 序列号 */
uchar idata Secnr;			        /* 扇区号 */

/****************************************************************/
/*名称: Clear_FIFO */
/*功能: 该函数实现清空FM1715中FIFO的数据*/
/*输入: N/A */
/*输出: TRUE, FIFO被清空*/
/* FALSE, FIFO未被清空*/
/****************************************************************/
uchar Clear_FIFO(void)
{
	/*~~~~~~~~~*/
	uchar	temp;
	uint	i;
	/*~~~~~~~~~*/

	temp = Control;			/* 清空FIFO */
	temp = (temp | 0x01);
	Control = temp;
	for(i = 0; i < RF_TimeOut; i++) /* 检查FIFO是否被清空 */
	{
		temp = FIFO_Length;
		if(temp == 0)
		{
			return TRUE;
		}
	}

	return FALSE;
}

/****************************************************************/
/*名称: Write_FIFO */
/*功能: 该函数实现向FM1715的FIFO中写入x bytes数据*/
/*输入: count, 待写入字节的长度*/
/* buff, 指向待写入数据的指针*/
/*输出: N/A */
/****************************************************************/
void Write_FIFO(uchar count, uchar idata *buff)
{
	/*~~~~~~*/
	uchar	i;
	/*~~~~~~*/

	for(i = 0; i < count; i++)
	{
		FIFO = *(buff + i);
	}
}

/****************************************************************/
/*名称: Read_FIFO */
/*功能: 该函数实现从FM1715的FIFO中读出x bytes数据*/
/*输入: buff, 指向读出数据的指针*/
/*输出: N/A */
/****************************************************************/
uchar Read_FIFO(uchar idata *buff)
{
	/*~~~~~~~~~*/
	uchar	temp;
	uchar	i;
	/*~~~~~~~~~*/

	temp = FIFO_Length;
	if(temp == 0)
	{
		return 0;
	}

	if(temp >= 24)		/* temp=255时,会进入死循环 */
	{
		/* 因此增加FIFO_Length越限判断 */
		temp = 24;	/* yanshouli,2003-12-2 */
	}

	for(i = 0; i < temp; i++)
	{
		*(buff + i) = FIFO;
	}

	return temp;
}

/****************************************************************/
/*名称: Judge_Req */
/*功能: 该函数实现对卡片复位应答信号的判断*/
/*输入: *buff, 指向应答数据的指针*/
/*输出: TRUE, 卡片应答信号正确*/
/* FALSE, 卡片应答信号错误*/
/****************************************************************/
uchar Judge_Req(uchar idata *buff)
{
	/*~~~~~~~~~~~~~~~~~*/
	uchar	temp1, temp2;
	/*~~~~~~~~~~~~~~~~~*/

	temp1 = *buff;
	temp2 = *(buff + 1);
	if(((temp1 == 0x03) || (temp1 == 0x04) || (temp1 == 0x05) || (temp1 == 0x53)) && (temp2 == 0x00))
	{
		return TRUE;
	}

	return FALSE;
}

/****************************************************************/
/*名称: Check_UID */
/*功能: 该函数实现对收到的卡片的序列号的判断*/
/*输入: N/A */
/*输出: TRUE: 序列号正确*/
/* FALSE: 序列号错误*/
/****************************************************************/
uchar Check_UID(void)
{
	/*~~~~~~~~~*/
	uchar	temp;
	uchar	i;
	/*~~~~~~~~~*/

	temp = 0x00;
	for(i = 0; i < 5; i++)
	{
		temp = temp ^ UID[i];
	}

	if(temp == 0)
	{
		return TRUE;
	}

	return FALSE;
}

/****************************************************************/
/*名称: Save_UID */
/*功能: 该函数实现保存卡片收到的序列号*/
/*输入: row: 产生冲突的行*/
/* col: 产生冲突的列*/
/* length: 接収到的UID数据长度*/
/*输出: N/A */
/****************************************************************/
void Save_UID(uchar row, uchar col, uchar length)
{
	/*~~~~~~~~~~*/
	uchar	i;
	uchar	temp;
	uchar	temp1;
	/*~~~~~~~~~~*/

	if((row == 0x00) && (col == 0x00))
	{
		for(i = 0; i < length; i++)
		{
			UID[i] = buffer[i];
		}
	}
	else
	{
		temp = buffer[0];
		temp1 = UID[row - 1];
		switch(col)
		{
		case 0:		temp1 = 0x00; row = row + 1; break;
		case 1:		temp = temp & 0xFE; temp1 = temp1 & 0x01; break;
		case 2:		temp = temp & 0xFC; temp1 = temp1 & 0x03; break;
		case 3:		temp = temp & 0xF8; temp1 = temp1 & 0x07; break;
		case 4:		temp = temp & 0xF0; temp1 = temp1 & 0x0F; break;
		case 5:		temp = temp & 0xE0; temp1 = temp1 & 0x1F; break;
		case 6:		temp = temp & 0xC0; temp1 = temp1 & 0x3F; break;
		case 7:		temp = temp & 0x80; temp1 = temp1 & 0x7F; break;
		default:	break;
		}

		buffer[0] = temp;
		UID[row - 1] = temp1 | temp;
		for(i = 1; i < length; i++)
		{
			UID[row - 1 + i] = buffer[i];
		}
	}
}

/****************************************************************/
/*名称: Set_BitFraming */
/*功能: 该函数设置待发送数据的字节数*/
/*输入: row: 产生冲突的行*/
/* col: 产生冲突的列*/
/*输出: N/A */
/****************************************************************/
void Set_BitFraming(uchar row, uchar col)
{
	switch(row)
	{
	case 0:		buffer[1] = 0x20; break;
	case 1:		buffer[1] = 0x30; break;
	case 2:		buffer[1] = 0x40; break;
	case 3:		buffer[1] = 0x50; break;
	case 4:		buffer[1] = 0x60; break;
	default:	break;
	}

	switch(col)
	{
	case 0:		Bit_Frame = 0x00; break;
	case 1:		Bit_Frame = 0x11; buffer[1] = (buffer[1] | 0x01); break;
	case 2:		Bit_Frame = 0x22; buffer[1] = (buffer[1] | 0x02); break;
	case 3:		Bit_Frame = 0x33; buffer[1] = (buffer[1] | 0x03); break;
	case 4:		Bit_Frame = 0x44; buffer[1] = (buffer[1] | 0x04); break;
	case 5:		Bit_Frame = 0x55; buffer[1] = (buffer[1] | 0x05); break;
	case 6:		Bit_Frame = 0x66; buffer[1] = (buffer[1] | 0x06); break;
	case 7:		Bit_Frame = 0x77; buffer[1] = (buffer[1] | 0x07); break;
	default:	break;
	}
}

/****************************************************************/
/*名称: FM1715_Bus_Sel */
/*功能: 该函数实现对FM1715操作的总线方式(并行总线,SPI)选择*/
/*输入: N/A */
/*输出: TRUE, 总线选择成功*/
/* FALSE, 总线选择失败*/
/****************************************************************/
uchar FM1715_Bus_Sel(void)
{
	/*~~~~~~*/
	uchar	i;
	/*~~~~~~*/

	Page_Sel = 0x80;		/* 表示PageSelect的值做为寄存器地址A5A4 和A3低 */

	/* 三位寄存器地址A2A0 由//外部地址线A2A0 决定 */
	for(i = 0; i < RF_TimeOut; i++) /* 延时 */
	{
		if(Command == 0x00)	/* 读命令执行结果, bit7为0表示接口检测结束 */
		{
			Page_Sel = 0x00;
			return TRUE;
		}
	}

	return FALSE;
}

/****************************************************************/
/*名称: Init_FM1715 */
/*功能: 该函数实现对FM1715初始化操作*/
/*输入: mode:工作模式, 0:TYPEA模式*/
/* 1:TYPEB模式*/
/* 2:上海模式*/
/*输出: N/A */
/****************************************************************/
void Init_FM1715(uchar mode)
{
	/*~~~~~~~~~~~~~~~~~*/
	uchar idata	temp;
	uint		i;
	/*~~~~~~~~~~~~~~~~~*/

	MFRST = 1;			            /* FM1715复位 */
	for(i = 0; i < 0x1fff; i++)
	{
		_nop_();
	}

	MFRST = 0;
	for(i = 0; i < 0x1fff; i++)
	{
		_nop_();
	}

	while(Command != 0)		        /* 等待Command = 0,FM1715复位成功 */
	{
		_nop_();
	}
	
	temp = FM1715_Bus_Sel();		        /* FM1715总线选择 */
	
	TimerClock = 0x0b;		        /* 151us/per */
	TimerControl = 0x02;		    /* 发送结束开定时器接收开始关定时器 */
	TimerReload = 0x42;		        /* 10ms定时 */
	InterruptEn = 0x7f;		        /* 关所有中断 */
	temp = InterruptEn;
	Int_Req = 0x7f;
	MFOUTSelect = 0x02;		        /* 调试用 */
	TxControl = 0x5b;		        /* 开启TX1TX2 */
	if(mode == SHANGHAI_MODE)	    /* 上海模式 */
	{
		TypeSH = 0x01;
	}
	else
	{
		TypeSH = 0x00;
	}

	if(mode == TYPEB_MODE)		/* TYPEB模式 */
	{
		CoderControl = 0x20;
		TypeBFraming = 0x05;
		DecoderControl = 0x19;
		ChannelRedundancy = 0x24;
		TxControl = 0x4b;
		CWConductance = 0x3f;
		ModConductance = 0xaf;
	}
}

/****************************************************************/
/*名称: Command_Send */
/*功能: 该函数实现向FM1715发送命令集的功能*/
/*输入: count, 待发送命令集的长度*/
/* buff, 指向待发送数据的指针*/
/* Comm_Set, 命令码*/
/*输出: TRUE, 命令被正确执行*/
/* FALSE, 命令执行错误*/
/****************************************************************/
uchar Command_Send(uchar count, uchar idata *buff, uchar Comm_Set)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~*/
	uint		j;
	uchar idata	temp, temp1;
	/*~~~~~~~~~~~~~~~~~~~~~~~~*/

	Command = 0x00;
	Clear_FIFO();
	Write_FIFO(count, buff);

	temp = MFOUTSelect;
	Command = Comm_Set;		/* 命令执行 */
	for(j = 0; j < RF_TimeOut; j++) /* 检查命令执行否 */
	{
		temp = MFOUTSelect;
		temp = Command;
		temp1 = Int_Req & 0x80;
		if((temp == 0x00) || (temp1 == 0x80))
		{
			return TRUE;
		}
	}

	return FALSE;
}

/****************************************************************/
/*名称: Read_E2 */
/*功能: 该函数实现从FM1715的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 */
/*功能: 该函数实现向FM1715的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 = SecondaryStatus;
	temp = temp & 0x40;
	if(temp == 0x40)
	{
		return TRUE;
	}

	return FALSE;
}

/****************************************************************/
/*名称: MIF_Halt */
/*功能: 该函数实现暂停MIFARE卡*/
/*输入: N/A */
/*输出: FM1715_OK: 应答正确*/
/* FM1715_PARITYERR: 奇偶校验错*/
/* FM1715_CRCERR: CRC校验错*/
/* FM1715_NOTAGERR: 无卡*/
/****************************************************************/
uchar MIF_Halt(void)
{
	/*~~~~~~~~~*/
	uchar	temp;
	uint	i;
	/*~~~~~~~~~*/

	CRCPresetLSB = 0x63;
	CWConductance = 0x3f;
	ChannelRedundancy = 0x03;
	*buffer = RF_CMD_HALT;
	*(buffer + 1) = 0x00;
	temp = Command_Send(2, buffer, Transmit);
	if(temp == TRUE)
	{
		for(i = 0; i < 0x50; i++)
		{
			_nop_();
		}

		return FM1715_OK;
	}
	else
	{
		temp = ErrorFlag;
		if((temp & 0x02) == 0x02)
		{
			return(FM1715_PARITYERR);
		}

		if((temp & 0x04) == 0x04)
		{
			return(FM1715_FRAMINGERR);
		}

		return(FM1715_NOTAGERR);
	}
}

///////////////////////////////////////////////////////////////////////
// 转换密钥格式
///////////////////////////////////////////////////////////////////////
char M500HostCodeKey(unsigned char *uncoded, unsigned char *coded)   
{
    char idata status = FM1715_OK;
    unsigned char idata cnt = 0;
    unsigned char idata ln  = 0;     
    unsigned char 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 FM1715_OK;
}

/****************************************************************/
/*名称: Load_keyE2 */
/*功能: 该函数实现把E2中密码存入FM1715的keybuffer中*/
/*输入: Secnr: EE起始地址*/
/*输出: True: 密钥装载成功*/
/* False: 密钥装载失败*/
/****************************************************************/
uchar Load_keyE2_CPY(uchar *uncoded_keys)
{
    uchar temp;
    unsigned char coded_keys[13];
    
    M500HostCodeKey(uncoded_keys, coded_keys);
	temp = Command_Send(12, coded_keys, LoadKey);
	temp = ErrorFlag & 0x40;
	if (temp == 0x40)
	{
		return FALSE;
	}
	return TRUE;
}

/****************************************************************/
/*名称: Request */
/*功能: 该函数实现对放入FM1715操作范围之内的卡片的Request操作*/
/*输入: mode: ALL(监测所以FM1715操作范围之内的卡片) */
/* STD(监测在FM1715操作范围之内处于HALT状态的卡片) */
/*输出: FM1715_NOTAGERR: 无卡*/
/* FM1715_OK: 应答正确*/
/* FM1715_REQERR: 应答错误*/
/****************************************************************/
uchar Request(uchar mode)
{
	/*~~~~~~~~~~~~~~~~~*/
	uchar idata	temp;
	/*~~~~~~~~~~~~~~~~~*/

	CRCPresetLSB = 0x63;
	CWConductance = 0x3f;
	buffer[0] = mode;		/* Request模式选择 */
	Bit_Frame = 0x07;		/* 发送7bit */
	ChannelRedundancy = 0x03;	/* 关闭CRC */
	temp = Control;
	temp = temp & (0xf7);
	Control = temp;			/* 屏蔽CRYPTO1位 */
	temp = Command_Send(1, buffer, Transceive);
	if(temp == FALSE)
	{
		return FM1715_NOTAGERR;
	}

	Read_FIFO(buffer);		/* 从FIFO中读取应答信息 */
	temp = Judge_Req(buffer);	/* 判断应答信号是否正确 */
	if(temp == TRUE)
	{
		tagtype[0] = buffer[0];
		tagtype[1] = buffer[1];
		return FM1715_OK;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -