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

📄 main.c

📁 射频卡读写程序和读写器原理图,常用的射频卡读写器源程序,源程序和原理图均是最终应用的程序,该读卡器已经批量生产,性能稳定.
💻 C
📖 第 1 页 / 共 5 页
字号:
		return 0x60;
	}
}



//----------------------------------------------------------------
//减操作---只能对已经认证的扇区进行操作
//实现卡的自动减值, 值存放在 card_inc_dec_buf[]中   块地址直接带进
//返回值表示处理结果  00:卡片操作正确  1x:无卡   2x:未经认证  3x:从卡片接收信息错误   4x:校验错误  5x:数据溢出错误  6x:操作失败
//----------------------------------------------------------------
uchar card_dec_p(uchar block_nm)
{
	uchar ls1,i;
	wr_1byte_rfm(CRCPresetLSB,0x63);
	wr_1byte_rfm(CWConductance,0x3f);
//	wr_1byte_rfm(ModConductance,0x3f);

	card_wrrd_buf[0]=RF_DEC;
	card_wrrd_buf[1]=block_nm;

	wr_1byte_rfm(ChannelRedundancy,0x0f);	//开启校验

	ls1=command_send(2,MU_TransCeive);
	if (ls1!=0) return 0x10;
	ls1=rd_1byte_rfm(FIFO_Length);		//FIFO LENGTH
	if (ls1==0)
	{
		return 0x30;
	}
	ls1=read_fifo();
	ls1=card_wrrd_buf[0];
	switch (ls1)
	{
		case 0x00:
			return 0x20;
		case 0x04:
			return 0x50;
		case 0x0a:
			break;
		case 0x01:
			return 0x40;
		case 0x05:
			return 0x40;
		default:
			return 0x60;
	}
	for (i=0;i<4;i++)		card_wrrd_buf[i]=card_inc_dec_buf[i];
	ls1=command_send(4,MU_TransCeive);
	if (ls1==0) 
	{
		return 0;
	}
	else
	{
		return 0x60;
	}
}


//----------------------------------------------------------------
//格式化为电子钱包: 根据指令对指定的块进行电子钱包格式化操作(写入按照格式要求的初始值)
//方法:对指定的扇区进行认证,认证后按照资料(6.4)要求格式写入相应的初始数据(0)即完成
//输入: 扇区号
//返回值表示处理结果  00:卡片操作正确  1x:无卡   2x:未经认证  3x:从卡片接收信息错误   4x:校验错误  5x:数据溢出错误  6x:操作失败
//----------------------------------------------------------------
uchar format_card_money(uchar sector_nm,uchar block_nm,uchar mode)
{
	uchar ls1;
	ls1=authentication_p(sector_nm,mode);
	if (ls1!=0) return ls1;
	//下面组织要写入的数据--按照个数写入
	delay_ms(15);
	for (ls1=0;ls1<4;ls1++)
	{
		card_wrrd_buf[ls1]=0;
	}
	for (ls1=0;ls1<4;ls1++)
	{
		card_wrrd_buf[ls1+4]=0xff;
	}
	for (ls1=0;ls1<4;ls1++)
	{
		card_wrrd_buf[ls1+8]=0;
	}
	ls1=sector_nm*4+block_nm;
	card_wrrd_buf[12]=ls1;
	card_wrrd_buf[13]=~ls1;
	card_wrrd_buf[14]=ls1;
	card_wrrd_buf[15]=~ls1;

	//数据写入
	ls1=write_card(sector_nm*4+block_nm);
	return ls1;
}


//----------------------------------------------------------------
//传输操作---只能对已经认证的扇区进行操作   将卡内数据寄存器内容写入到卡中
//在卡自动加减值后,发出本指令使数据写入卡内EEPROM, 
//返回值表示处理结果  00:卡片操作正确  1x:无卡   2x:未经认证  3x:从卡片接收信息错误   4x:校验错误  5x:数据溢出错误  6x:操作失败
//----------------------------------------------------------------
uchar card_transfer_p(uchar block_nm)
{
	uchar ls1;
	wr_1byte_rfm(CRCPresetLSB,0x63);
	wr_1byte_rfm(CWConductance,0x3f);
//	wr_1byte_rfm(ModConductance,0x3f);

	card_wrrd_buf[0]=RF_Tranfer;
	card_wrrd_buf[1]=block_nm;

	wr_1byte_rfm(ChannelRedundancy,0x0f);	//开启校验

	ls1=command_send(2,MU_TransCeive);
	if (ls1!=0) return 0x10;
	ls1=rd_1byte_rfm(FIFO_Length);		//FIFO LENGTH
	if (ls1==0)
	{
		return 0x30;
	}
	ls1=read_fifo();
	ls1=card_wrrd_buf[0];
	switch (ls1)
	{
		case 0x00:
			return 0x20;
		case 0x04:
			return 0x50;
		case 0x0a:
			return 0x00;
		case 0x01:
			return 0x40;
		case 0x05:
			return 0x40;
		default:
			return 0x60;
	}
}



//----------------------------------------------------------------
//Card Restore 操作  将块中的数据读到卡内的数据存储器
//输入块号 (0~63)
//输出操作结果
//----------------------------------------------------------------
uchar card_restore_p(uchar block_nm)
{
	uchar ls1;
	wr_1byte_rfm(CRCPresetLSB,0x63);
	wr_1byte_rfm(CWConductance,0x3f);
//	wr_1byte_rfm(ModConductance,0x3f);

	card_wrrd_buf[0]=RF_Restore;
	card_wrrd_buf[1]=block_nm;

	wr_1byte_rfm(ChannelRedundancy,0x0f);	//开启校验

	ls1=command_send(2,MU_TransCeive);
	if (ls1!=0) return 0x10;
	ls1=rd_1byte_rfm(FIFO_Length);		//FIFO LENGTH
	if (ls1==0)
	{
		return 0x30;
	}
	ls1=read_fifo();
	ls1=card_wrrd_buf[0];
	switch (ls1)
	{
		case 0x00:
			return 0x20;
		case 0x04:
			return 0x50;
		case 0x0a:
			break;
		case 0x01:
			return 0x40;
		case 0x05:
			return 0x40;
		default:
			return 0x60;
	}
	for (ls1=0;ls1<4;ls1++)
	{
		card_wrrd_buf[ls1]=0;
	}
	ls1=command_send(4,MU_Trans);
	if (ls1!=0) return 0x10;
	else return 0;	
}


//----------------------------------------------------------------
//指令传输-----向RF卡传输指令
//输入:卡指令类型--表示FM1702对卡的操作comm   参数个数num  对卡发送的信息放在card_wrrd_buf[]中.
//	卡返回的信息存放在FM1702的FIFO中,用Read_fifo()函数读取
//返回的信息表示  00:命令执行正确  非0:命令执行错误
//对receive 或transceive指令, 接收情况需要在调用本函数的程序中通过查询Primary Status寄存器检测接收情况
//----------------------------------------------------------------
uchar command_send(uchar num,uchar comm)
{
	uint i;
	uchar ls1,ls2;
	wr_1byte_rfm(Command,0x00);	//command=0;
	ls1=clear_fifo();
	if (ls1!=0) ls1=clear_fifo();
	write_fifo(num);
	ls1=rd_1byte_rfm(MFOUTSelect);
	wr_1byte_rfm(Command,comm);	//command=comm;

	for (i=0;i<5000;i++)			//???
	{//查询执行结果,含超时处理
//		ls1=rd_1byte_rfm(MFOUTSelect);
		ls1=rd_1byte_rfm(Command);	//command
		t_data=ls1;
		ls2=rd_1byte_rfm(Int_Req);	//INTreq
		t_data=ls2;
		ls2&=0x08;
		if ((ls1==0)||(ls2==0x08)) return 0;
//		if (ls1==0) return 0;
	}

	return 0xff;
}



//----------------------------------------------------------------
//读出FM1702 EEPROM中数据
//输入: addl:EEPROM 低地址  addh:EEPROM 高地址  count:读出字节数(最多24字节)
//输出: 0:读取正确 9x:读取个数超限  其他:读取错误
//----------------------------------------------------------------
uchar read_ee(uchar addl,uchar addh,uchar count)
{
	uchar ls1;
	if (count>24) return 0x90;
	card_wrrd_buf[0]=addl;
	card_wrrd_buf[1]=addh;
	card_wrrd_buf[2]=count;
	ls1=command_send(3,MU_ReadE2);
	ls1=read_fifo();
	if (ls1==0) return 0xff;
	else return 0x00;
}



//----------------------------------------------------------------
//读出FM1702 EEPROM中数据
//输入: addl:EEPROM 低地址  addh:EEPROM 高地址  count:写入字节数(最多20字节)
//要写入的数据放在card_wrrd_buf[], 从card_wrrd_buf[0]开始存放
//输出: 0:写入正确 9x:写入个数超限  其他:写入错误
//----------------------------------------------------------------
uchar write_ee(uchar addl,uchar addh,uchar count)
{
	uchar ls1;
	if (count>20) return 0x90;
	for (ls1=0;ls1<count;ls1++)
	{
		card_wrrd_buf[count+2-ls1]=card_wrrd_buf[count-ls1];
	}
	card_wrrd_buf[0]=addl;
	card_wrrd_buf[1]=addh;
	ls1=command_send(count+2,MU_WritE2);
	ls1=rd_1byte_rfm(SecondaryStatus);
	ls1&=0x40;
	if (ls1!=0x40) return 0xff;
	else return 0x00;
}




//----------------------------------------------------------------
//从FIFO中读出X字节数据------在执行了收发指令或接收指令后,RF卡返回信息放在FIFO中,这个函数读取
//输入:无    读取的数据放在card_wrrd_buf[]中.
//返回信息:  0:读取的数据个数
//----------------------------------------------------------------
uchar read_fifo(void)
{
	uchar i,ls1;
	ls1=rd_1byte_rfm(FIFO_Length);		//读出FIFO字节数
	if (ls1==0) return 0;
	if (ls1>24) ls1=24;
	for (i=0;i<ls1;i++)
	{
		card_wrrd_buf[i]=rd_1byte_rfm(FIFO);
	}
	return (ls1);
}


//----------------------------------------------------------------
//向FIFO中写入X字节数据
//输入:写入取数据个数num    返回信息-无   写入的数据放在card_wrrd_buf[]中.
//----------------------------------------------------------------
void write_fifo(uchar num)
{
	uchar i;
	for (i=0;i<num;i++)
	{
		wr_1byte_rfm(FIFO,card_wrrd_buf[i]);
	}
}


//----------------------------------------------------------------
//清除FIFO中数据
//输入:无  返回信息-00:命令正确执行    非0:命令每被正确执行.
//----------------------------------------------------------------
uchar clear_fifo(void)
{
	uchar ls1,i;
	ls1=rd_1byte_rfm(Control);
	ls1|=0x01;
	wr_1byte_rfm(Control,ls1);
	for (i=0;i<100;i++)
	{
		ls1=rd_1byte_rfm(FIFO_Length);
		if (ls1==0) return 0;
	}
	return 1;
}


//----------------------------------------------------------------
//把密钥写入FM1702密钥缓冲区
//输入:无  密钥存放在user_key_buf[]
//输出: 00:操作正确   0x80:操作失败,密钥格式错误
//----------------------------------------------------------------
uchar load_key(void)
{
	uchar i;
	uchar ls1;
	for (i=0;i<12;i++)
	{
		card_wrrd_buf[i]=user_key_buf[i];		//密钥输入
	}
	ls1=command_send(12,MU_Loadkey);
	ls1=rd_1byte_rfm(ErrorFlag);
	ls1&=0x40;
	if (ls1!=0)
	{//密钥格式错误
		return 0x80;
	}
	return 0;
}



//----------------------------------------------------------------
//把EEPROM密钥写入FM1702密钥缓冲区
//输入: 扇区 ,不同扇区按照顺序存放把密钥存放在内部EEPROM中, 密钥为12字节
//输出: 00:操作正确   0x80:操作失败,密钥格式错误
//----------------------------------------------------------------
uchar load_e2key(uchar sector)
{
	uchar ls1;
	uchar lsb,msb;
	ls1=sector*12;
	if (ls1>=0x80)
	{
		lsb=ls1-0x80;
		msb=0x01;
	}
	else
	{
		lsb=ls1+0x80;
		msb=0x00;
	}
	card_wrrd_buf[0]=lsb;
	card_wrrd_buf[1]=msb;
	ls1=command_send(2,MU_LoadkeyE2);
	if (ls1!=0) return 0x10;
	ls1=rd_1byte_rfm(ErrorFlag);
	ls1&=0x40;
	if (ls1!=0)
	{//密钥格式错误
		return 0x80;
	}
	return 0;
}



//----------------------------------------------------------------
//密钥计算函数
//根据卡号UID(低4字节) 扇区号(2字节) 置换盒 计算认证密钥
//输入: 保存在RAM中的UID 发来的扇区号 保存在RAM中的置换盒数据
//输出:计算好的密钥,存放在user_key_buf[];
//----------------------------------------------------------------
void key_calcu_p(void)
{
	uchar i,j,k,ls1;
	uint ls2,ls3;

//调试vvvvvv
	for (i=6;i<12;i++)	user_key_buf[i]=0xff;

	for (i=0;i<6;i++)
	{
		k=j=ls1=user_key_buf[i+6];
		ls1>>=4;
		ls1&=0x0f;
		j=~j;
		j&=0xf0;
		ls1|=j;
		user_key_buf[2*i]=ls1;
		ls1=k;
		ls1<<=4;
		ls1=~ls1;
		ls1&=0xf0;
		j=k&0x0f;
		ls1|=j;
		user_key_buf[2*i+1]=ls1;
	}
	return;
//调试^^^^



	keycal_r=0;
//计算扇区号
	ls3=sector_r;
	for (i=0;i<8;i++)
	{
	ls2=ls3;
	ls2&=0x8000;
	ls1=static_key_1[i];
	ls1&=0xf0;
	ls1>>=4;
	ls1=15-ls1;
	ls2>>=ls1;
	keycal_r|=ls2;	
	ls3<<=1;

	ls2=ls3;
	ls2&=0x8000;
	ls1=static_key_1[i];
	ls1&=0x0f;
	ls1=15-ls1;
	ls2>>=ls1;
	keycal_r|=ls2;	
	ls3<<=1;
	}
	user_key_buf[6]=keycal_rh;

⌨️ 快捷键说明

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