📄 main.c
字号:
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 + -