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

📄 main.c

📁 射频卡读写程序和读写器原理图,常用的射频卡读写器源程序,源程序和原理图均是最终应用的程序,该读卡器已经批量生产,性能稳定.
💻 C
📖 第 1 页 / 共 5 页
字号:
	user_key_buf[7]=keycal_rl;
//计算卡号前2字节
	keycal_rh=rfcard_sn_buf[0];
	keycal_rl=rfcard_sn_buf[1];
	ls3=keycal_r;
	keycal_r=0;
	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[8]=keycal_rh;
	user_key_buf[9]=keycal_rl;
//计算卡号2~3字节
	keycal_rh=rfcard_sn_buf[2];
	keycal_rl=rfcard_sn_buf[3];
	ls3=keycal_r;
	keycal_r=0;
	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[10]=keycal_rh;
	user_key_buf[11]=keycal_rl;
//对密钥进行格式转换,转换为12字节密钥
	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;
	}
}






//----------------------------------------------------------------
//名称: save_uid                                                //
//功能: 该函数实现保存卡片收到的序列号                          //
//输入:  row: 产生冲突的行					//
//       col: 产生冲突的列					//
//       length: 接収到的UID数据长度                            //
//输出:  无                                                     //
//----------------------------------------------------------------
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++)
		{
			rfcard_sn_buf[i]=card_wrrd_buf[i];	//UID转到UID存储区
		}
	}
	else
	{	
		temp = card_wrrd_buf[0];
		temp1 = rfcard_sn_buf[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;
		}
		card_wrrd_buf[0] = temp;
		rfcard_sn_buf[row - 1] = temp1 | temp;
		for(i = 1; i < length; i++)
		{
			rfcard_sn_buf[row - 1 + i] = card_wrrd_buf[i];
		}
	}
}


//----------------------------------------------------------------
//名称: set_bitframing                                          //
//功能: 该函数设置待发送数据的字节数                         	//
//输入:  row: 产生冲突的行                                      //
//col: 产生冲突的列						//
//输出:  None							//
//----------------------------------------------------------------
void set_bitframing(uchar row,uchar col)
{	
	switch (row)
	{
		case 0: 
			card_wrrd_buf[1] = 0x20;
			break;
		case 1:
			card_wrrd_buf[1] = 0x30;
			break;
		case 2:
			card_wrrd_buf[1] = 0x40;
			break;
		case 3:
			card_wrrd_buf[1] = 0x50;
			break;
		case 4:
			card_wrrd_buf[1] = 0x60;
			break;
		default:
			break;
	}	
	
	switch(col)
	{
		case 0:
			wr_1byte_rfm(Bit_Frame,0x00);
			break;
		case 1:
			wr_1byte_rfm(Bit_Frame,0x11);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x01);
			break;
		case 2:
			wr_1byte_rfm(Bit_Frame,0x22);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x02);
			break;
		case 3:
			wr_1byte_rfm(Bit_Frame,0x33);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x03);
			break;
		case 4:
			wr_1byte_rfm(Bit_Frame,0x44);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x04);
			break;
		case 5:
			wr_1byte_rfm(Bit_Frame,0x55);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x05);
			break;
		case 6:
			wr_1byte_rfm(Bit_Frame,0x66);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x06);
			break;
		case 7:
			wr_1byte_rfm(Bit_Frame,0x77);
			card_wrrd_buf[1] = (card_wrrd_buf[1] | 0x07);
			break;
		default:
			break;
	}
}






//----------------------------------------------------------------
//由于布线的问题,数据口顺序错误, 所以笨函数转换这个数据
//----------------------------------------------------------------
uchar conv_datao(uchar data)
{
	datac=data;
	datap_b0 = datac_b6;
	datap_b1 = datac_b0;
	datap_b2 = datac_b1;
	datap_b3 = datac_b3;
	datap_b4 = datac_b2;
	datap_b5 = datac_b7;
	datap_b6 = datac_b5;
	datap_b7 = datac_b4;
	return (datap);
}



//----------------------------------------------------------------
//对读卡器芯片操作函数
//包括:写入一字节数据到读卡器芯片/从读卡器芯片读出一字节数据
//读数据: 输入地址,不关心页面情况,页面由前面的操作确定, 返回读取的数据
//写数据: 输入地址,和要写入的数据, 不关心页面情况,页面由前面的操作确定, 无返回
//----------------------------------------------------------------
void wr_1byte_rfm(uchar add,uchar data)
{
	uchar ls1;
	ls1=add&0x38;
	ls1>>=3;
	ls1|=0x80;
	ls1=conv_datao(ls1);
	rfm_cs_kx=1;
	rfm_wr_kx=1;
	rfm_add_A0=0;
	rfm_add_A1=0;
	rfm_add_A2=0;
	rfm_data_k=ls1;		//发出地址高3位
	rfm_cs_kx=0;		//CS
	rfm_wr_kx=0;		//WR
	Nop();
	rfm_wr_kx=1;		//WR
	rfm_cs_kx=1;		//CS

	data=conv_datao(data);
	if (add&0x01) rfm_add_A0=1;
	else rfm_add_A0=0;
	if (add&0x02) rfm_add_A1=1;
	else rfm_add_A1=0;
	if (add&0x04) rfm_add_A2=1;
	else rfm_add_A2=0;
	rfm_data_k=data;			//发出数据
	rfm_cs_kx=0;		//CS
	rfm_wr_kx=0;		//WR
	Nop();
	rfm_wr_kx=1;		//WR
	rfm_cs_kx=1;		//CS
}




//----------------------------------------------------------------
//由于布线的问题,数据口顺序错误, 所以笨函数转换这个数据
//----------------------------------------------------------------
uchar conv_datai(uchar data)
{
	datac=data;
	datap_b6 = datac_b0;
	datap_b0 = datac_b1;
	datap_b1 = datac_b2;
	datap_b3 = datac_b3;
	datap_b2 = datac_b4;
	datap_b7 = datac_b5;
	datap_b5 = datac_b6;
	datap_b4 = datac_b7;
	return (datap);
}


//----------------------------------------------------------------
uchar rd_1byte_rfm(uchar add)
{
	uchar data;
	data=add&0x38;
	data>>=3;
	data|=0x80;
	data=conv_datao(data);
	rfm_cs_kx=1;
	rfm_wr_kx=1;
	rfm_add_A0=0;
	rfm_add_A1=0;
	rfm_add_A2=0;
	rfm_data_k=data;		//发出地址高3位
	rfm_cs_kx=0;		//CS
	rfm_wr_kx=0;		//WR
	Nop();
	rfm_wr_kx=1;		//WR
	rfm_cs_kx=1;		//CS

	DDRB=0x00;
//	rfm_cs_kx=1;
	rfm_rd_kx=1;
	if (add&0x01) rfm_add_A0=1;
	else rfm_add_A0=0;
	if (add&0x02) rfm_add_A1=1;
	else rfm_add_A1=0;
	if (add&0x04) rfm_add_A2=1;
	else rfm_add_A2=0;
	rfm_cs_kx=0;		//CS
	rfm_rd_kx=0;		//RD
	Nop();
	data=rfm_data_k;	//收数据
	rfm_rd_kx=1;		//RD
	rfm_cs_kx=1;		//CS
	DDRB=0xff;
	data=conv_datai(data);
	return(data);
}



//----------------------------------------------------------------
//处理接收指令---SPI UART用同一个程序,也是同一个缓冲区
//指令处理完,直接设置返回数据,然后设置标志,返回应答和结果给上位机
//根据指令要求,向FIFO中写入需要向卡发送的指令,读卡器芯片自动发出这些指令完成需要的操作
//向卡发送的指令见<8K位非接触式集成电路卡专用芯片FM11RF08.doc>中的"指令格式"表格P3
//写入和读取"射频卡读写模块"数据用void wr_1byte_rfm(uchar add,uchar data);uchar rd_1byte_rfm(uchar add);
//进行卡的EEPROM读写必须认证后加密进行.

//前面只是对卡进行了询卡 防冲突 选卡操作, 尚未进行认证, 这里接收到的指令如果需要对卡进行操作, 则先对卡进行认证
// 认证后再进行相应的操作, 至于对卡某区的操作, 完全由上位机确定, 密钥在开机时已经传输到本读卡器中, 经过运算的
//密钥可以用于认证, 如果采用不同的分区操作, 则需要上位机重新发送固定密钥.

//读卡指令:根据指令读出指定的块, 需要先进行认证
//写卡指令:根据指令把数据写入指定的块, 需要先进行认证
//加  指令:根据指令对指定的块进行加操作, 需要先进行认证
//减  指令:根据指令对指定的块进行减操作, 需要先进行认证
//格式化为电子钱包: format_card_money() 根据指令对指定的块进行电子钱包格式化操作(写入按照格式要求的初始值), 需要先进行认证

//帧开始 参数个数 指令 参数 校验和
//返回上位机 ack_to_main_par  00:卡片操作正确  0f:接收上位机数据错误  1x:无卡   2x:未经认证  3x:从卡片接收信息错误   4x:校验错误
//  5x:数据溢出错误  6x:操作失败
//----------------------------------------------------------------
void rf_ins_proc_p(void)
{
	uchar ls1,ls2,i;
//	com_up_err_flg=0;
//	if ((!ins_spi_flg)&&(!ins_uart_flg))  return;
	ls2=ls1=re_buf[0];
	ls2+=2;			//校验和计算数据个数
	for (i=1;i<ls2;i++)
	{
		ls1+=re_buf[i];
	}
	if (ls1!=re_buf[ls2])
	{
		ack_to_main_par=0x0f;
		goto rf_ins_proc_p1;
	}
	//校验完成,正确,开始处理指令
	card_opr_er_ct=0;
	ls1=re_buf[1];
	if (ls1==0x11)		//握手指令
	{
		rfcard_type=re_buf[2];
	}
	else if (ls1==0x22)	//设置卡某区为电子钱包模式
	{
		sector_rh=re_buf[2];
		sector_rl=re_buf[3];
		card_block=re_buf[4];
		card_key_mode=re_buf[5];
		ack_to_main_par=format_card_money(sector_rl,card_block,card_key_mode);
	}
	else if ((ls1==0x33)||(ls1==0x55))	//电子钱包减值	//电子钱包加值
	{
		if (ls1==0x33) card_inc_or_dec_flg=1;
		sector_rh=re_buf[2];
		sector_rl=re_buf[3];
		card_block=re_buf[4];
		card_key_mode=re_buf[8];
		i=ls2=ls1=re_buf[7];
		ls1>>=4;
		ls1&=0x0f;
		ls2=~ls2;
		ls2&=0xf0;
		ls1|=ls2;
		card_inc_dec_buf[0]=ls1;
		ls2=ls1=i;
		ls1&=0x0f;
		ls2=~ls2;
		ls2<<=4;
		ls2&=0xf0;
		ls1|=ls2;
		card_inc_dec_buf[1]=ls1;
		i=ls2=ls1=re_buf[6];
		ls1>>=4;
		ls1&=0x0f;
		ls2=~ls2;
		ls2&=0xf0;
		ls1|=ls2;
		card_inc_dec_buf[2]=ls1;
		ls2=ls1=i;
		ls1&=0x0f;
		ls2=~ls2;
		ls2<<=4;
		ls2&=0xf0;
		ls1|=ls2;
		card_inc_dec_buf[3]=ls1;
		ack_to_main_par=authentication_p(sector_rl,card_key_mode);		//认证
		if (ack_to_main_par!=0) goto rf_ins_proc_p1;
		delay_ms(15);
		if (card_inc_or_dec_flg) ack_to_main_par=card_dec_p(card_block);	//减数
		else ack_to_main_par=card_inc_p(card_block);				//加数
		ack_to_main_par=card_transfer_p(card_block);				//传输
		if (ack_to_main_par!=0) goto rf_ins_proc_p1;	
		delay_ms(15);
		ack_to_main_par=read_card(card_block);					//读出现值返回上位机
		tr_buf[0]=0xff;

⌨️ 快捷键说明

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