1348|7

32

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【极海APM32F407 Tiny Board】RFID读写IC卡(RC522) [复制链接]

 

这段时间正在研究IC卡操作,正好借助APM32开发板做一次完整的读写验证。
刚开始接触相关产品,主要研究M1类IC卡。本测试基于RC522进行学习测试,手上的卡片是NXP的S50卡。

RC522芯片支持UART,IIC,SPI三种通信,手上的模组是SPI接口,相比IIC和UART,SPI操作速度应该是最快的。
板子连接如下图所示:

RC522模块连接在SPI1,管脚配置如下:

// SPI1-PB3:SCK-PB4:MISO-PB5:MOSI
{GPIOB, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_PUPD_NOPULL, GPIO_AF_SPI1, GPIO_SPEED_50MHz, 1, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5},
// SPI1 AUX
{GPIOB, GPIO_MODE_OUT, GPIO_OTYPE_PP, GPIO_PUPD_NOPULL, 0, GPIO_SPEED_25MHz, 1, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 },

port_io_pin_make(rfid_cs, PB, 6);
port_io_pin_make(rfid_rst, PB, 7);

控制RC522通信除了SPI接口之外还需要一个RST脚控制其复位。

M1卡的结构这里不做赘述,可以将其看作是无线通信且有密钥保护的EEPROM。
对M1卡的操作主要包含:选卡、密钥验证、读卡、写卡。
卡的读写以块为基本单位,每块16B。每扇区4块,4块中的最后一块为密钥及保护信息。

GITHUB上有基于LPC4xxx的操作代码,不过嵌入了fls驱动库,需要对底层操作进行替换。
为方便移植,本测试将底层操作全部使用函数指针实现,底层主要包含如下操作:

void MFRC522_SS_enable(void)
{
	rfid_cs.dis();
}

void MFRC522_SS_disable(void)
{
	rfid_cs.en();
}

void MFRC522_RST_enable(void)
{
	rfid_rst.dis();
}

void MFRC522_RST_disable(void)
{
	rfid_rst.en();
}

const struct MFRC522_HAL_T rc522_hal = {
	MFRC522_SS_enable, // 片选生效
	MFRC522_SS_disable, // 片选取消
	MFRC522_RST_enable, // 复位生效
	MFRC522_RST_disable, // 复位取消
	ext_spi_rw}; // SPI读写

 

应用代码如下,一个串口命令输入处理函数和IC扫描程序:


/*******************************************************************************
 * @brief: rc522 lib app
 ******************************************************************************/
struct MFRC522_T rfid_obj;
int last_balance = 0;
unsigned int last_user_ID;
uu08 rc522_scan_en = 0;
uu08 rc522_scan_mode = 0;
	
#define MIN_BALANCE 300

/*******************************************************************************
 * @brief: rc522 lib start
 * @param argc 参数数量
 * @param argv 参数指针
 * [url=home.php?mod=space&uid=784970]@return[/url] 错误代码
 ******************************************************************************/
int rc522_lib_init(int argc, char *argv[])
{
	uu08 buff[80];

	rfid_cs.dir_out_pp();
	rfid_rst.dir_out_pp();
	
	rc522_scan_mode = 0;
	
	if(argc > 1)
	{
		if(argv[1][0] == 'w')
			rc522_scan_mode = 1;
	}

	rfid_obj.hal = &rc522_hal;

	setupRFID(&rfid_obj);

	rc522_scan_en = 1;

	dbg_puts(SYMBOL_LINE_DOT PTCR);
	return 0;
}
DBG_FUNX_EXPORT(rc522_lib_init, "[r/w]");

/*******************************************************************************
 * @brief: rc522 scan
 * @param none
 * @return none
 ******************************************************************************/
void MFRC522_scan(void)
{
	if (rc522_scan_en)
	{
		// Look for new cards in RFID2
		if (PICC_IsNewCardPresent(&rfid_obj))
		{
			// Select one of the cards
			if (PICC_ReadCardSerial(&rfid_obj))
			{
				// int status = writeCardBalance(rfid_obj, 100000); // used to recharge the card
				ic_card_opt();
			}
		}
	}
}
obj_app_order(MFRC522_scan);

/*******************************************************************************
 * @brief: rc522 opt
 * @param none
 * @return none
 ******************************************************************************/
void ic_card_opt(void)
{
	//	show card UID
	dbg_print("\nCard uid bytes: ");
	for (uint8_t i = 0; i < rfid_obj.uid.size; i++)
	{
		dbg_print(" %X", rfid_obj.uid.uidByte[i]);
	}
	dbg_print("\n\r");

	// Convert the uid bytes to an integer, byte[0] is the MSB
	last_user_ID =
		(int)rfid_obj.uid.uidByte[3] |
		(int)rfid_obj.uid.uidByte[2] << 8 |
		(int)rfid_obj.uid.uidByte[1] << 16 |
		(int)rfid_obj.uid.uidByte[0] << 24;

	dbg_print("\nCard Read user ID: %X ", last_user_ID);

	if(0 == rc522_scan_mode)
	{
		// Read the user balance
		last_balance = readCardBalance(&rfid_obj);

		if (last_balance == (-999))
		{
			// Error handling, the card does not have proper balance data inside
		}
		else
		{
			// Check for minimum balance
			if (last_balance < MIN_BALANCE)
			{
				dbg_print("%08X, Insufficient balance\n", last_balance);
			}
			else
			{
				dbg_print("%08X, Balance OK\n", last_balance);
			}
		}
	}
	else
	{
		writeCardBalance(&rfid_obj, 0);
	}
	dbg_puts(SYMBOL_LINE_ADD PTCR);
}

演示视频:
调试串口启动IC卡扫描程序。
rc522_lib_init w 命令指示扫描到IC卡后执行写操作,具体是将IC的块0读出,将读取的数据写入块4
rc522_lib_init r 命令指示扫描到IC卡后执行读操作,具体是分别读取IC卡的块0和块4

发送rc522_lib_init w后将卡片开机驱动板,提示写操作后拿开IC卡。然后发送rc522_lib_init r指令,再次将卡片接近驱动板完成读卡操作。

rfid

 

测试代码托管在gitee平台:

链接已隐藏,如需查看请登录或者注册

最新回复

感谢分享这么好的例程,手上还有吃灰的刷卡器,看能不能用得上。  详情 回复 发表于 2023-6-1 07:41
点赞 关注
 
 

回复
举报

5262

帖子

239

TA的资源

管理员

沙发
 

视频里,这熟悉的电流声音,是因为什么来?

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

点评

没有麦,应该是插孔噪声信号被录进来了  详情 回复 发表于 2023-5-31 12:36
 
 
 

回复

32

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
nmg 发表于 2023-5-31 08:47 视频里,这熟悉的电流声音,是因为什么来?

没有麦,应该是插孔噪声信号被录进来了

 
 
 

回复

363

帖子

3

TA的资源

纯净的硅(初级)

4
 

到现在我都没明白RFID到底有多少种卡,好像金融行业用的又不是M0卡,也不是M1卡。。。。

点评

可以拿有NFC的手机扫一扫,就知道是什么卡了。  详情 回复 发表于 2023-5-31 17:20
我了解到常见的应该有ID卡,IC卡,CUP卡。 安全要求高的基本都是CPU卡,身份证、金融卡都是这种,号称不可破解。  详情 回复 发表于 2023-5-31 13:45
 
 
 

回复

32

帖子

0

TA的资源

一粒金砂(中级)

5
 
hjl2832 发表于 2023-5-31 12:54 到现在我都没明白RFID到底有多少种卡,好像金融行业用的又不是M0卡,也不是M1卡。。。。

我了解到常见的应该有ID卡,IC卡,CUP卡。

安全要求高的基本都是CPU卡,身份证、金融卡都是这种,号称不可破解。

点评

IC卡确实可以暴力破解,因为密码就那么多位。  详情 回复 发表于 2023-5-31 17:20
 
 
 

回复

7175

帖子

2

TA的资源

版主

6
 
hjl2832 发表于 2023-5-31 12:54 到现在我都没明白RFID到底有多少种卡,好像金融行业用的又不是M0卡,也不是M1卡。。。。

可以拿有NFC的手机扫一扫,就知道是什么卡了。

 
 
 

回复

7175

帖子

2

TA的资源

版主

7
 
aple0807 发表于 2023-5-31 13:45 我了解到常见的应该有ID卡,IC卡,CUP卡。 安全要求高的基本都是CPU卡,身份证、金融卡都是这种,号称 ...

IC卡确实可以暴力破解,因为密码就那么多位。

 
 
 

回复

6969

帖子

11

TA的资源

版主

8
 
感谢分享这么好的例程,手上还有吃灰的刷卡器,看能不能用得上。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表