摘要:利用STM32作为微控制器,使用RC522模块检测S50卡,实现电子钱包功能。
知识点铺垫:
一、IC卡标准协议
1、非接触式IC卡标准协议:ISO 14443 typeA/typeB协议(根据加密方式区分) 2、typeA:一般用于私用,会员卡消费卡等 ?? typeB:加密特性好,用于公用,例如身份证 3、扩展:15693--与上者的区别在于耦合方式不同,前者为近场耦合,后者为远场耦合,距离更远。
二、IC卡的分类:
三、程序分析
1、初始化相关引脚:涉及SPI通信相关、模块io等
2、初始化RC522:
/*================== 初始化RC522 ===================*/
void RC522_Init(void)
{
PcdReset(); /*读写模块复位初始化*/
PcdAntennaOff(); /*关闭天线*/
PcdAntennaOn(); /*开启天线*/
M500PcdConfigISOType( 'A' ); /*设置为ISO 14443A 模式*/
}
3、PcdReset();? //再次复位
4、对卡操作:寻卡--->防冲突--->选卡--->操作卡(固定程序,有时间再仔细分析)
重点分析对卡进行充值扣费操作:
/*=======================================================================
* 功 能:已注册卡片充值
* PICC_AUTHENT1A :验证A密钥的
* Card_Number_Buf:存储卡号的缓存区
* New_Key :新密码
* Write_First_Data:要写入块的清零数据
* Read_Data :从块中读出数据的缓存
* 返 回 值:1 或 MI_OK【注:MI_OK = 0】;
* 验证密码、写密码、写数据任一环节出错则返回1
* 验证密码、写密码、写数据所以环节都正确在返回MI_OK
=========================================================================*/
u8 Add_Money_Card(void)
{
// u8 i;
u8 status ;
u16 money;
Card_Mode = CONSUME; // 注册完成之后,切换到消费功能
status = PcdAuthState(PICC_AUTHENT1A, 7, New_Key, Card_Number_Buf); // 验证卡片密码
if (status != MI_OK) { return 1; } // 验证密码失败,可能卡没有被注册
/******** 读出 block 4(扇区2 的 block0) 16字节数据到Read_Data中 **********/
status=PcdRead(4, Read_Data);
if (status != MI_OK) { return 1; } // 读出数据
/***** 将前两个字节合并成一个金额数值money ******/
money = (u16) (Read_Data[1] << 8);
money |= Read_Data[0];
// printf("充值前%d \n",money);
/********* 金额数值加10 *********/
money = money + 10;
/********** 将增加后的金额数值拆分成两个字节 *********/
Read_Data[0] = (u8)(money);
Read_Data[1] = (u8)(money >> 8);
// printf("充值后%d \n",money);
/*向block 4(扇区2 的 block0) 中写入充值后的数据Read_Data*/
status = PcdWrite(4, Read_Data);
if (status != MI_OK) { return 1; } // 写入数据失败
printf("充值10元 \n");
return MI_OK;
}
/*假设钱包余额为10元*/ ??
??? money? = (u16) (Read_Data[1] << 8);? //0x00==0000 0000 0000 0000 ?? ?money |= Read_Data[0]; ? ? ? ? ? ? ? ? ? ? //money==0000 0000 0001 0000 ?? ?/********* 金额数值加10 *********/ ?? ?money = money + 10;?????????????????????? //money=0000 0000 0010 0000 ?? ?/********** 将增加后的金额数值拆分成两个字节 *********/ ?? ?Read_Data[0] = (u8)(money);????????? //Data[0]=0010 0000 ?? ?Read_Data[1] = (u8)(money >> 8); //Data[1]= 0000 0000????
/*向block 4(扇区2 的 block0) 中写入充值后的数据Read_Data*/ ??? status = PcdWrite(4, Read_Data); ?? //扇区0中是block0,block1,block2,block3
余额变为20元。
|