标题:
单片机+RC522读FM1208 CPU卡程序 定额消费带PSAM卡操作12864显示
[打印本页]
作者:
84660310
时间:
2018-12-6 18:01
标题:
单片机+RC522读FM1208 CPU卡程序 定额消费带PSAM卡操作12864显示
52单片机驱动rc522读cpu卡资料包:
0.png
(11.68 KB, 下载次数: 59)
下载附件
2018-12-7 04:00 上传
单片机源程序如下:
#include "reg52.h"
#include <string.h>
#include <intrins.h>
#include "main.h"
#include "RC522.H"
#include "12864.h"
#include "uart.h"
#include "FM1208.H"
#include "psam.h"
unsigned char Serial_Num[8]; //用户卡序列号
unsigned char code S_KEY_1[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88}; //分散因子1(为自定义城市标识)
unsigned char code S_KEY_2[8]={0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11}; //分散因子2(为自定义各成员银行标识)
//////////////////文件标识的定义/////////////////////////////////////////////////////////////////////////////////
//
//为统一方便管理阅读代码,我们在所有的文件名后面加个_Flag,表示就是该对应文件的标识//
//
unsigned char code CZKey_Flag={0x01}; //圈存密钥标识为01
unsigned char code DPKey_Flag={0x00}; //消费密钥标识为00
unsigned char code DF_ExKey_Flag = {0x00}; //DF下的外部密钥标识00
unsigned char code DF_Inital_Key_Flag = {0x00}; //DF下的内部密钥标识00
unsigned char code FM1208_DF_0015_Flag[]={0x00,0x15}; //公共应用基本数据文件标识0015
unsigned char code FM1208_DF_0016_Flag[]={0x00,0x16}; //持卡人基本信息数据的文件标识0016
////////////////////////////////////////////////////////////////////////
//文件标识
unsigned char code File_3F00[] ={0x3f,0x00}; //MF下的文件标识3F00
unsigned char code File_3F01[] ={0x3f,0x01}; //DF下的文件标识3F01
unsigned char code File_0016={0x16}; //终端机短文件标识
unsigned char Temporary_Key[8];
unsigned char xdata Challenge_Num[8]; //随机数
unsigned char code DateTime[]={0x20,0x16,0x10,0x26,0x11,0x32,0x45}; //交易时间,如果板子带有时钟芯片,可以把实时时间写入卡中。
unsigned char xdata NameBuf[20]; //临时存放姓名
unsigned char xdata NameLen; //姓名长度
unsigned char code Purchase_Pay[4]={0x00,0x00,0x00,0x01}; //操作的金额 高位在前,16进制计算的,定额消费1元
unsigned int xdata PAY;
unsigned int xdata Pay_1 ;
unsigned char xdata POSNum[6]; //终端机编号 从SAM卡中读取
unsigned char xdata g_cSNR[4];
unsigned char xdata DataBuf[MAXRLEN];
unsigned char xdata g_cReceBuf[MAXRLEN];
void NameToStr(char *s) //计算姓名的长度,及临时保存姓名
{
char i;
NameLen=strlen(s);
for(i=0;i<NameLen;i++)
NameBuf[i]=s[i];
}
void CLRBuff()
{
memset(g_cReceBuf, 0x00, MAXRLEN); //清0
memset(DataBuf, 0x00, MAXRLEN);
}
void Request_loop()
{
s8 status,atq[2] ;
while(1)
{
status = PcdRequest(PICC_REQALL, atq);
if(status != MI_OK)
{
status = PcdRequest(PICC_REQALL, atq);
if(status != MI_OK)
break;
}
}
}
void main( )
{
unsigned int xdata st;
unsigned char xdata tt[2];
unsigned char xdata i;
unsigned char status;
InitializeSystem( );
DelayMs(200); //等待上电稳定
UART_Init(); //串口初始化
RC522_Init(); //RC522初始化 ,
initial_LCD(); //显示屏初始化
if(PSAMInit(g_cReceBuf)) //PSAM卡初始化
{
UART_Send_Str("无PSAM卡,请插入PSAM卡!");
UART_Send_Enter();
while(1);
}
UART_Send_Str("PSAM卡复位成功!");
UART_Send_Enter();
Dis_Deduct_Charge(0); //12864显示
PcdAntennaOff();
DelayMs(3);
PcdAntennaOn();
CLRBuff();
while ( 1 )
{
st =PcdRequest(PICC_REQALL, tt); //寻卡
if(st){continue;}
st =PcdAnticoll(g_cSNR);//防冲撞,
if(st){continue;}
st =PcdSelect(g_cSNR); //选择卡片
if(st){continue;}
if (pro_reset(g_cReceBuf,tt)!=MI_OK) //用户卡(CPU卡)复位,成功后才能往下操作//
{
CLRBuff();
continue;
}
UART_Send_Enter();
UART_Send_Enter();
UART_Send_Str("用户卡复位成功!");
UART_Send_Enter();
UART_Send_Enter();
////////////////////////////////////////////////////////////////
CLRBuff();
st=Sam_Select_File(File_3F00, 2, 0,g_cReceBuf, 0x28 ); //选择SAM卡中PBOC的3F00文件// 0x2E
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡3F00文件打开错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
CLRBuff();
st=Sam_ReadBinary( File_0016,g_cReceBuf, 6 ); //读取SAM卡里面的终端机编号//
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡的终端机编号读取错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("终端机编号为:");
memcpy(POSNum, g_cReceBuf, 6);
UART_Put_Num(POSNum,6);
UART_Send_Enter();
CLRBuff();
st=Sam_Select_File(File_3F01, 2, 0,g_cReceBuf, 0x27 ); //选择SAM卡中PBOC的3F01文件
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡PBOC文件打开错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("SAM卡PBOC文件打开成功!");
UART_Send_Enter();
UART_Send_Enter();
CLRBuff();
st=FM1208_SelectFile(File_3F01,g_cReceBuf,tt); //打开CPU卡中PBOC的3F01文件//
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("用户卡PBOC文件打开错误!");
UART_Send_Enter();
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str(">>用户卡PBOC文件打开成功<<");
UART_Send_Enter();
UART_Send_Enter();
CLRBuff();
st=FM1208_Read_Binary(FM1208_DF_0015_Flag[1],g_cReceBuf, 0x1E ); //读取0015文件公共应用基本数据//
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("公共应用基本文件读取失败:");
UART_Put_Num(g_cReceBuf,2);
UART_Send_Enter();
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str(">>公共应用基本文件读取成功<<");
UART_Send_Enter();
UART_Send_Enter();
memcpy(Serial_Num, &g_cReceBuf[12], 8); //拷入用户卡序号
UART_Send_Str("用户卡序号:");
UART_Put_Num(Serial_Num,8); //用户卡序号
UART_Send_Enter();
UART_Send_Str("启动日期:");
UART_Put_Num(&g_cReceBuf[20],4); //这里可做判断一张卡的生命周期
UART_Send_Str("停用日期:");
UART_Put_Num(&g_cReceBuf[24],4);
UART_Send_Enter();
//////////////////////////////////////////////////////////////
//主要是用户卡判断终端的合法性,即是否是有人伪造的终端机
st=FM1208_GetChallenge(8,Challenge_Num); //从用户卡取一组随机数//
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("用户卡读取随机码错误:");
UART_Put_Num(g_cReceBuf,2);
UART_Send_Enter();
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("取得随机数");
UART_Put_Num(Challenge_Num,8);
UART_Send_Enter();
CLRBuff();
st=Init_for_descrypt(Serial_Num, 0x8, 0x27,DF_ExKey_Flag, g_cReceBuf); //用3DE初始化 1级分散产生过程密钥 27--密钥用途,为加密密钥
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡的3DES初始化失败:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
CLRBuff();
st=Descrypt(Challenge_Num, 0x8, 0, g_cReceBuf, 0x8 ); //3DES算法 对刚才临时保存的随机数进行加密//
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡的3DES计算错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("外部认证的加密结果:");
UART_Put_Num(g_cReceBuf,8);
memcpy(Temporary_Key, g_cReceBuf, 8); //临时保存加密结果
UART_Send_Enter();
CLRBuff();
st=FM1208_External_Authenticate(DF_ExKey_Flag,Temporary_Key,g_cReceBuf);
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("终端POS机非法,外部认证错误:");
UART_Put_Num(g_cReceBuf,2);
UART_Send_Enter();
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("外部认证成功,终端POS机合法!");
UART_Send_Enter();
UART_Send_Enter();
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//主要用于终端判断卡的合法性,也就是说你这张用户卡是否能在我的终端上使用
st=Get_challenge(Challenge_Num, 8); //从SAM卡里取一组随机数//
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡读取随机码错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
CLRBuff();
st=FM1208_Inital_Authenticate(DF_Inital_Key_Flag, 8, Challenge_Num,g_cReceBuf); //用户卡内部认证,加密该随机数//
if(st!=0x9000)
{
UART_Send_Str("内部认证错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
memcpy(Temporary_Key, g_cReceBuf, 8); //临时保存加密结果
CLRBuff();
st=Init_for_descrypt(Serial_Num, 0x8, 0x2C, DF_Inital_Key_Flag, g_cReceBuf); //用3DE初始化 1级分散产生过程密钥 2C--密钥用途,为解密密钥
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡的3DES初始化失败:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
CLRBuff();
st=Descrypt(Temporary_Key, 0x8, 0, g_cReceBuf, 0x8 ); //3DES算法 对刚才临时保存的加密了的数据进行解密//
if(st!=SAM_OK)
{
UART_Send_Str("SAM卡的3DES计算错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("内部认证的解密结果:");
UART_Put_Num(g_cReceBuf,8);
UART_Send_Enter();
for(i=0;i<8;i++)
{
if(g_cReceBuf[i]!=Challenge_Num[i]) //这里判断卡的合法性//
{
status=1;
break;
}
}
if(status==1)
{
status=0;
UART_Send_Str("非法卡!不能在本终端使用!");
UART_Send_Enter();
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str("内部认证成功,用户卡合法!");
UART_Send_Enter();
UART_Send_Enter();
////////////////////////////////////////////////////////////////////
CLRBuff();
st=FM1208_Read_Binary(FM1208_DF_0016_Flag[1],g_cReceBuf, 0x27 ); //读取0016文件持卡人基本信息
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("持卡人基本信息文件读取失败:");
UART_Put_Num(g_cReceBuf,2);
UART_Send_Enter();
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str(">>持卡人基本信息文件读取成功<<");
UART_Send_Enter();
UART_Send_Enter();
UART_Send_Str("卡类型标识:");
UART_Put_Num(&g_cReceBuf[0],1);
UART_Send_Enter();
UART_Send_Str("本行职工标识:");
UART_Put_Num(&g_cReceBuf[1],1);
UART_Send_Enter();
UART_Send_Str("持 卡 人 的姓名:");
UART_Send_Str(&g_cReceBuf[2]);
NameToStr(&g_cReceBuf[2]);
UART_Send_Enter();
UART_Send_Enter();
UART_Send_Str("持 卡 人 的证件类型:");
UART_Put_Num(&g_cReceBuf[38],1);
UART_Send_Enter();
UART_Send_Str("持 卡 人 的证件号码:");
UART_Put_Num(&g_cReceBuf[22],16);
UART_Send_Enter();
CLRBuff();
DataBuf[0]=DPKey_Flag; //1个字节的消费密钥标识
memcpy(&DataBuf[1], Purchase_Pay, 4); //4个字节的交易金额,即扣款金额
memcpy(&DataBuf[5], POSNum, 6); //6个字节的终端机编号
st=FM1208_Initalize_For_Purchase(EP, DataBuf,g_cReceBuf,tt); //消费初始化操作//
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("初始化消费错误:");
UART_Put_Num(g_cReceBuf,tt[0]); //当返回9403时,此时检查一下你的用户卡里面的消费密钥的标识号,是否对应?
UART_Send_Enter();
if(st==0x9401)
DisNotMoney(); //卡余额不足
DelayMs(2000);
Dis_Deduct_Charge(0);
}
CLRBuff();
Request_loop();
continue;
}
UART_Send_Str(">>消费初始化成功<<");
UART_Send_Enter();
UART_Send_Enter();
UART_Send_Str("电子钱包未消费前的余额:");
UART_Put_Num(g_cReceBuf,4);
UART_Send_Enter();
UART_Send_Str("电子钱 包 交 易序号:");
UART_Put_Num(&g_cReceBuf[4],2);
UART_Send_Enter();
UART_Send_Str(" 限 额:");
UART_Put_Num(&g_cReceBuf[6],3);
UART_Send_Enter();
UART_Send_Str("密钥版本号:");
UART_Put_Num(&g_cReceBuf[9],1);
UART_Send_Enter();
UART_Send_Str("算法标识:");
UART_Put_Num(&g_cReceBuf[10],1);
UART_Send_Enter();
UART_Send_Str("伪随机码:");
UART_Put_Num(&g_cReceBuf[11],4);
UART_Send_Enter();
PAY=g_cReceBuf[2]<<8;
PAY|=g_cReceBuf[3];
Dis_Money(NameLen,NameBuf,PAY); //屏显示消费前的余额
memcpy(DataBuf, &g_cReceBuf[11], 4); //拷伪随机数
memcpy(&DataBuf[4], &g_cReceBuf[4], 2); //用户卡交易序号
memcpy(&DataBuf[6], Purchase_Pay, 4); //交易金额
DataBuf[10]=0x06; //交易类型
memcpy(&DataBuf[11], DateTime, 7); //交易日期时间
DataBuf[18]=DPKey_Flag; //消费密钥版本标识号
DataBuf[19]=0x00; //算法标识,3DES
memcpy(&DataBuf[20], Serial_Num, 8); //用户卡序号
memcpy(&DataBuf[28], S_KEY_2, 8); //分散因子2(为各成员银行标识)
memcpy(&DataBuf[36], S_KEY_1, 8); //分散因子1(为各城市标识)
st=Init_SAM_For_Purchase(DataBuf, 0x2C, g_cReceBuf); //MAC1计算初始化//
if(st!=SAM_OK)
{
UART_Send_Str("MAC1计算错误:"); //当返回9403时,此时检查一下你的SAM卡里面的消费密钥的版本标识号,是否对应?
UART_Put_Num(g_cReceBuf,0x02);
UART_Send_Enter();
CLRBuff();
Request_loop();
Dis_Deduct_Charge(0);
continue;
}
UART_Send_Str(">>MAC1计算初始化成功<<");
UART_Send_Enter();
UART_Send_Enter();
UART_Send_Str("终端交易序号:");
UART_Put_Num(g_cReceBuf,0x04);
UART_Send_Enter();
UART_Send_Str("返回的MAC1码:");
UART_Put_Num(&g_cReceBuf[4],0x04);
UART_Send_Enter();
memcpy(DataBuf, g_cReceBuf, 4); //拷终端交易序号
memcpy(&DataBuf[4], DateTime, 7); //拷交易日期时间
memcpy(&DataBuf[11], &g_cReceBuf[4], 4); //拷MAC1
st=FM1208_Debit_For_Capp_Purchase(DataBuf,g_cReceBuf,tt); //消费命令//
if(st!=0x9000)
{
if(st!=ST_ERR)
{
UART_Send_Str("扣款失败:");
UART_Put_Num(g_cReceBuf,tt[0]); //当返回9302时,此时检查一下你的密钥因子是否正确,包括用户卡序列号,成员银行及城市代码,由于密钥因子错了,分散出的过程密钥也是错的,所以计算出的MAC也是错的
UART_Send_Enter();
DisCardfail();
}
CLRBuff();
Request_loop();
Dis_Deduct_Charge(0);
continue;
}
UART_Send_Str("用户卡返回的交易验证TAC:");
UART_Put_Num(g_cReceBuf,4);
UART_Send_Enter();
UART_Send_Str("用户卡返回的MAC1:");
UART_Put_Num(&g_cReceBuf[4],4);
UART_Send_Enter();
memcpy(DataBuf, &g_cReceBuf[4], 4); //拷MAC2,然后发送给PSAM卡进行校验
st=Credit_SAM_For_Purchase(DataBuf, g_cReceBuf); //MAC2校验//
if(st!=SAM_OK)
{
UART_Send_Str("校验MAC2错误:");
UART_Put_Num(g_cReceBuf,2); //显示错误代码
UART_Send_Enter();
DisCardfail();
CLRBuff();
Request_loop();
Dis_Deduct_Charge(0);
continue;
}
UART_Send_Str("扣款MAC2校验成功!");
UART_Send_Enter();
UART_Send_Enter();
st=FM1208_ReadNomey(EP ,g_cReceBuf); //读充值后的余额//
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
CPU卡定额消费带PSAM卡操作并显示屏显示.zip
(222.9 KB, 下载次数: 262)
2018-12-6 18:00 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
wj0755
时间:
2018-12-22 15:35
好的,看看 学习了
作者:
sn300
时间:
2018-12-30 15:38
正找CPU卡的资料来看看
作者:
xiaowu1716
时间:
2019-1-29 16:14
非常感谢!我一直寻找这个代码,终于找到了,谢谢楼主的无私奉献!666
作者:
wang-123
时间:
2019-4-22 18:31
已下载,内容很好
作者:
saj123456
时间:
2019-7-2 22:38
好资料谢谢分享
作者:
loveappletree
时间:
2019-7-11 10:39
谢谢,非常感谢
作者:
Raywang89
时间:
2019-7-24 16:26
非常好的资料,谢谢
作者:
liudi1990
时间:
2019-8-1 19:27
感谢大神分享
作者:
hlmpost
时间:
2019-8-17 12:00
fm1208白卡,rats,无回复?
作者:
随风不留痕
时间:
2019-8-25 19:18
感谢分享,看下内容。
作者:
liy_278
时间:
2019-8-30 17:41
感谢分享
作者:
fl15614
时间:
2019-9-26 09:36
感谢楼主分享!学习了
作者:
plainsailing
时间:
2019-10-15 16:59
感谢楼主分享
作者:
bjghui
时间:
2019-11-24 15:16
感谢楼主分享!学习一下
作者:
zalelife
时间:
2020-2-19 18:20
不错的代码分享
作者:
fengyu200208
时间:
2025-1-15 20:00
感谢楼主分享,学习了。
作者:
mx1117
时间:
2025-8-27 14:35
感谢楼主分享,学习了。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1