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