【STM32实战项目】基于STM32和RFID技术的门禁系统设计

🎀 文章作者:二土电子

🌸 关注公众号获取完整程序工程!

🐸 期待大家一起学习交流!


文章封面

一、项目简介

本项目基于STM32F103C8T6核心板,利用MF RC522射频模块、IC卡以及按键模块实现一个门禁系统设计,能够实现卡片添加、删除和识别,使用串口输出全部信息。

🔧软件工具:Keil5、串口助手

二、硬件简介

  • 主控:STM32F103C8T6核心板
  • 射频模块:MF RC522,使用软件模拟的SPI通信
  • 两张IC卡
  • 三个独立按键,一端接地
  • USB-TTL,用于输出信息

引脚分配

引脚对应IO
模式切换按键PA1
添加卡片按键PA2
删除卡片按键PA3
RC522_CSPA4
RC522_SCKPA5
RC522_MISOPA6
RC522_MOSIPA7
RC522_RSTPB0

三、软件设计思路

该项目除了一些驱动和功能程序设计外,主要有两个业务,一个是卡片ID库管理业务,用来管理卡片ID库,实现卡片的添加和删除,另一个是卡识别测业务,用来检测卡片是否已经入库,开机默认在卡片识别模式,通过模式切换按键实现两种模式的切换。

3.1 卡片ID库管理业务

3.1.1 添加卡片

每一个IC卡都会有一个四字节的ID号作为唯一标识,我们添加或者删除卡片时只需要存储或者删除这个ID号即可。程序设计时定义了四个四字节长度的数组用来存储卡片ID号,当然也可以根据自己的需求添加更多的卡片。

只有在该业务中添加按键和删除按键才可以生效,利用switch实现不同功能之间的切换。

当按下进入添加卡片模式时,会首先等待寻卡结果,也就是有没有检测到有IC卡被放到了感应区。如果在一段时间内没有检测到IC卡,会自动退出添加卡片模式并输出提示信息。如果检测到了IC卡,首先会检测一下ID库是否已经存储满了,如果存储满了会输出存满提示,如果仍有空位,会将新的ID按照顺序存储到空位并输出提示信息,最后退出添加卡片模式。

3.1.2 删除卡片

删除卡片与添加卡片大同小异,当按下删除卡片按键时会进入删除卡片功能,如果在一段时间内没有检测到IC卡,会自动退出删除卡片模式并输出提示信息。如果检测到了IC卡,会将卡片ID与库内已经存储的ID进行比较,如果有该卡片,将会清除并输出提示信息,如果没有找到对应ID,则退出删除卡片模式并输出提示信息。

3.2 卡片识别业务

该业务只有一个功能,检测卡片是否已经在库内,在或不在都会输出提示信息。

四、程序设计

关于MF RC522的驱动函数和功能函数的实现已经在外设系列专栏中呈现,这里就不再赘述。

4.1 卡片库管理业务函数

/*
 *==============================================================================
 *函数名称:App_Rc522_CardIdLib_Manage
 *函数功能:卡片ID库管理
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
void App_Rc522_CardIdLib_Manage (void)
{
	u8 keyValue = 0;            // 存储按键键值
	u8 cardId[4] = {0,0,0,0};   // 存储读取到的卡片ID
	u8 cardSaveIndex = 0;       // 卡片存储位置索引
	u32 timeOutCunt = 0;        // 超时计数变量
	u8 findFlag = 0;            // 寻卡成功标志位
	u8 modeRunFlg = 1;          // 模式运行标志位,1:运行中;0:退出
	
	printf ("Enter card library manage mode!\r\n");
	
	while (modeRunFlg)
	{
		keyValue = Med_KeyScan();   // 按键扫描
		
		switch (keyValue)
		{
			case 0xAD:   // 添加卡片
				printf ("Add card!\r\n");
				// 等待读取到卡片ID
			  while (1)
				{
					findFlag = Med_Rc522_GetId(cardId);
					
					timeOutCunt ++;
					if (timeOutCunt >= 65530)
					{
						timeOutCunt = 0;
						break;
					}
					else if (findFlag == 1)
						break;
				}
				if (findFlag == 1)
				{
					// 查看当前卡片库是否已经存储满
					if (gCardId1[0] == 0x00 && gCardId1[1] == 0x00 && gCardId1[2] == 0x00 && gCardId1[3] == 0x00)
						cardSaveIndex = 1;
					else if (gCardId2[0] == 0x00 && gCardId2[1] == 0x00 && gCardId2[2] == 0x00 && gCardId2[3] == 0x00)
						cardSaveIndex = 2;
					else if (gCardId3[0] == 0x00 && gCardId3[1] == 0x00 && gCardId3[2] == 0x00 && gCardId3[3] == 0x00)
						cardSaveIndex = 3;
					else if (gCardId4[0] == 0x00 && gCardId4[1] == 0x00 && gCardId4[2] == 0x00 && gCardId4[3] == 0x00)
						cardSaveIndex = 4;
					else
						cardSaveIndex = LIB_FULL;
					// 判断新卡是否已经在库内
					if (cardId[0] == gCardId1[0] && cardId[1] == gCardId1[1] && cardId[2] == gCardId1[2] && cardId[3] == gCardId1[3])
						cardSaveIndex = CARD_EXIST;
					else if (cardId[0] == gCardId2[0] && cardId[1] == gCardId2[1] && cardId[2] == gCardId2[2] && cardId[3] == gCardId2[3])
						cardSaveIndex = CARD_EXIST;
					else if (cardId[0] == gCardId3[0] && cardId[1] == gCardId3[1] && cardId[2] == gCardId3[2] && cardId[3] == gCardId3[3])
						cardSaveIndex = CARD_EXIST;
					else if (cardId[0] == gCardId4[0] && cardId[1] == gCardId4[1] && cardId[2] == gCardId4[2] && cardId[3] == gCardId4[3])
						cardSaveIndex = CARD_EXIST;
					
					switch (cardSaveIndex)
					{
						case 1:
							gCardId1[0] = cardId[0];
							gCardId1[1] = cardId[1];
							gCardId1[2] = cardId[2];
							gCardId1[3] = cardId[3];
							printf ("Add card1 is successful!\r\n");
							break;
						
						case 2:
							gCardId2[0] = cardId[0];
							gCardId2[1] = cardId[1];
							gCardId2[2] = cardId[2];
							gCardId2[3] = cardId[3];
							printf ("Add card2 is successful!\r\n");
							break;
						
						case 3:
							gCardId3[0] = cardId[0];
							gCardId3[1] = cardId[1];
							gCardId3[2] = cardId[2];
							gCardId3[3] = cardId[3];
							printf ("Add card3 is successful!\r\n");
							break;
						
						case 4:
							gCardId4[0] = cardId[0];
							gCardId4[1] = cardId[1];
							gCardId4[2] = cardId[2];
							gCardId4[3] = cardId[3];
							printf ("Add card4 is successful!\r\n");
							break;
						
						case LIB_FULL:
							printf ("Card library is full!\r\n");
							break;
						
						case CARD_EXIST:
							printf ("Card already exists!\r\n");
							break;
						
						default:
							break;
					}
					findFlag = 0;
				}
				else
					printf ("No card found!\r\n");
				break;
			
			case 0xDE:   // 删除卡片
				printf ("Delete card!\r\n");
				// 等待读取到卡片ID
			  while (1)
				{
					findFlag = Med_Rc522_GetId(cardId);
					
					timeOutCunt ++;
					if (timeOutCunt >= 65530)
					{
						timeOutCunt = 0;
						break;
					}
					else if (findFlag == 1)
						break;
				}
				if (findFlag == 1)
				{
					// 判断卡片是否已经在库内
					if (cardId[0] == gCardId1[0] && cardId[1] == gCardId1[1] && cardId[2] == gCardId1[2] && cardId[3] == gCardId1[3])
					{
						gCardId1[0] = 0x00;
						gCardId1[1] = 0x00;
						gCardId1[2] = 0x00;
						gCardId1[3] = 0x00;
						printf ("Delete card1 is successful!\r\n");
					}
					else if (cardId[0] == gCardId2[0] && cardId[1] == gCardId2[1] && cardId[2] == gCardId2[2] && cardId[3] == gCardId2[3])
					{
						gCardId2[0] = 0x00;
						gCardId2[1] = 0x00;
						gCardId2[2] = 0x00;
						gCardId2[3] = 0x00;
						printf ("Delete card2 is successful!\r\n");
					}
					else if (cardId[0] == gCardId3[0] && cardId[1] == gCardId3[1] && cardId[2] == gCardId3[2] && cardId[3] == gCardId3[3])
					{
						gCardId3[0] = 0x00;
						gCardId3[1] = 0x00;
						gCardId3[2] = 0x00;
						gCardId3[3] = 0x00;
						printf ("Delete card3 is successful!\r\n");
					}
					else if (cardId[0] == gCardId4[0] && cardId[1] == gCardId4[1] && cardId[2] == gCardId4[2] && cardId[3] == gCardId4[3])
					{
						gCardId4[0] = 0x00;
						gCardId4[1] = 0x00;
						gCardId4[2] = 0x00;
						gCardId4[3] = 0x00;
						printf ("Delete card4 is successful!\r\n");
					}
					else
						printf ("Not found this card!\r\n");
					findFlag = 0;
				}
				else
					printf ("No card found!\r\n");
				break;
			
			case 0x55:
				printf ("Quit card library manage mode!\r\n");
				modeRunFlg = 0;
				break;
			
			default:
				break;
		}
	}
}

4.2 卡片识别业务函数

/*
 *==============================================================================
 *函数名称:App_Rc522_IdentifyCard
 *函数功能:卡片识别
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
*/
void App_Rc522_IdentifyCard (void)
{
	u8 keyValue = 0;            // 存储按键键值
	u8 cardId[4] = {0,0,0,0};   // 存储读取到的卡片ID
	u32 timeOutCunt = 0;        // 超时计数变量
	u8 findFlag = 0;            // 寻卡成功标志位
	u8 modeRunFlg = 1;          // 模式运行标志位,1:运行中;0:退出
	
	printf ("Enter card identify mode!\r\n");
	
	while (modeRunFlg)
	{
		keyValue = Med_KeyScan();   // 按键扫描
		
		switch (keyValue)
		{
			case 0x55:
				printf ("Quit card identify mode!\r\n");
				modeRunFlg = 0;
				break;
			
			default:
				// 等待读取到卡片ID
				while (1)
				{
					keyValue = Med_KeyScan();   // 按键扫描
					findFlag = Med_Rc522_GetId(cardId);
					
					timeOutCunt ++;
					if (timeOutCunt >= 65530)
					{
						timeOutCunt = 0;
						break;
					}
					else if (findFlag == 1)
						break;
					else if (keyValue == 0x55)
					{
						printf ("Quit card identify mode!\r\n");
						modeRunFlg = 0;
						break;
					}
				}
				if (findFlag == 1)
				{
					// 逐一对比卡片库ID
					if (cardId[0] == gCardId1[0] && cardId[1] == gCardId1[1] && cardId[2] == gCardId1[2] && cardId[3] == gCardId1[3])
						printf ("The cards are in the library!\r\n");
					else if (cardId[0] == gCardId2[0] && cardId[1] == gCardId2[1] && cardId[2] == gCardId2[2] && cardId[3] == gCardId2[3])
						printf ("The cards are in the library!\r\n");
					else if (cardId[0] == gCardId3[0] && cardId[1] == gCardId3[1] && cardId[2] == gCardId3[2] && cardId[3] == gCardId3[3])
						printf ("The cards are in the library!\r\n");
					else if (cardId[0] == gCardId4[0] && cardId[1] == gCardId4[1] && cardId[2] == gCardId4[2] && cardId[3] == gCardId4[3])
						printf ("The cards are in the library!\r\n");
					else
						printf ("The card is not in the library!\r\n");
					findFlag = 0;
				}
				break;
		}
	}
}

五、总结与展望

本项目基于STM32,利用RFID技术实现了门禁系统设计,但是仍有一些地方可以进行优化

  • 可以增加OLED用来显示提示信息
  • 可以增加舵机模拟开关门
  • 可以利用Flash实现卡片ID库的掉电存储

虽然上面列出来的这些内容本文并没有实现,但是别慌!

  • OLED模块指路:“STM32开发笔记—外设系列”专栏
  • SG90舵机指路:“STM32开发笔记—外设系列”专栏
  • FLASH指路:“STM32速成笔记”专栏

另外在学习SG90舵机时会涉及到定时器和PWM相关知识,也可以到“STM32速成笔记”专栏查看!

### STM32项目中实现RFID功能 #### RFID模块简介 RFID(射频识别)技术是一种利用无线电波来自动识别物体的技术。在嵌入式系统开发中,STM32微控制器常用于控制RFID读写器设备。为了使STM32能够操作RFID标签,通常会连接专用的RFID芯片,如MFRC522。 #### 实现过程概述 要让STM32支持RFID功能,主要涉及以下几个方面的工作: - **硬件连接**:将STM32RFID模块相连,一般采用SPI接口进行通信。 - **软件配置**:编写或移植适用于所选MCU平台的驱动库文件;初始化外设并设置参数以便正常工作。 - **应用层编程**:根据具体需求调用API函数完成相应的业务逻辑处理,比如查询是否有卡存在、获取UID序列号等操作[^1]。 #### 示例代码展示 下面给出一段简单的C语言源码片段作为参考,展示了如何基于STM32MFRC522实现基本的RFID读取功能: ```c #include "stm32f1xx_hal.h" #include "mfrc522.h" // 初始化 SPI MFRC522 模块 void SystemInit(void){ HAL_Init(); /* 配置系统时钟 */ MX_GPIO_Init(); // GPIO 初始化 MX_SPI1_Init(); // SPI 接口初始化 MFRC522_Init(SPI1); // 调用 mfrc522 库中的初始化方法 } int main(void){ uint8_t uid[4]; // 存储 UID 的数组 char strUid[10]; SystemInit(); while (1){ if(MFRC522_Request(PICC_REQIDL,uid)==MI_OK){ // 寻找未上电卡片 sprintf(strUid,"%02X%02X%02X%02X",uid[0],uid[1],uid[2],uid[3]); printf("Card detected! UID:%s\n",strUid); delay_ms(1000); // 延迟一秒防止重复打印 memset(uid, 0 ,sizeof(uid)); // 清除上次读到的数据 } HAL_Delay(100); // 循环等待时间间隔 } } ``` 此段程序实现了最基本的卡片检测以及唯一标识符(UID)显示功能。实际应用场景下可能还需要加入更多特性,例如防冲突机制、密码验证流程等等[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二土电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值