RFID课程设计–智能门禁系统
前言
本次课程设计要求如下,我们团队两人完成了90%的功能。
其中我们设置的是刷卡错误3次不报警,密码输入错3次报警(原理相同,大家根据需要自行修改)
然后暂时只能显示卡号和卡是第几个录入到系统中的,想到身份证号和电话(身份信息)输进去有点长就没花太多心思,想实现这个功能会写卡就可以了。这是我的队友 kiro_1023
最初版设计
STM32RCT6+RC522+OLED,刷卡显示卡号文章来源:https://www.toymoban.com/news/detail-793897.html
完整版工程文件下载链接
RFID课程设计工程文件,基于STM32F103RCT6的智能门禁系统文章来源地址https://www.toymoban.com/news/detail-793897.html
摘要
本次课程设计项目完成了一款以STM32F103RCT6单片机为控制中心门禁系统设计。通过RC522模块实现录入卡和刷卡身份识别的功能;4*4矩阵按键模块实现密码的输入和功能的切换;继电器模块和电磁铁控制控制门的开关;DHT11模块采集室内温湿度数据;OLED显示屏显示菜单和各类数据。刷卡验证和密码的验证给门禁系统添加了双重的保险,简约的OLED显示的交互页面在保证信息显示完整的同时也极大地减少了用户的阅读量,降低了操作难度,方便使用。
一、系统的功能描述
首先有四个功能
A刷卡解锁
B输入密码解锁
C录入卡
D修改密码
A功能使用一个大数组card_sql[101]
,存放卡的卡号
存放格式为 1字节序号 4字节卡号
通过刷卡获取的卡号与passwd
数组内的卡号按格式校对,成功则开门,并在OLED上显示DHT11温湿度数据
B功能使用两个数组
passwd_scan
输入数据缓冲数组
passwd
当前密码存放数组
读取按键输入的有效键值存放到passwd_scan
中,输入4位后将passwd_scan
的四位数据与passwd
的四位密码进行一一校对
成功则返回成功标志,失败则返回失败标志
失败三次,报警,只能按*退出
C功能为录入不在card_sql
中的卡号
用追加的方式,将序号和卡号添加到card_sql
中
如果卡已经在库中会显示卡已存在而不进行录入
D功能是B功能的延伸
先输入旧密码,读取按键输入的有效键值存放到passwd_scan
中,输入4位后将passwd_scan
的四位数据与passwd
的四位密码进行一一校对,如果密码认证成功
输入新密码
同样以读取按键输入的有效键值存放到passwd_scan
中,输入4位后将passwd_scan
的四位数据与passwd
的四位密码进行替换
实现新密码的录入
二、系统整体设计
2.1方案描述
本作品通过四个功能解决门禁系统的基本设计要求,分别为A刷卡解锁,B密码解锁,C录入卡号,D修改密码。
通过OLED屏对作品的功能选择进行显示,还能够显示刷卡后状态以及密码输入的状态,利用矩阵按键控制门禁系统的功能选择以及密码输入部分,采用DHT11温湿度传感器模块接收实时的温湿度数据并从OLED屏上显示,开门部分则采用电磁铁模拟小区内开关门的控制部分。系统总体设计框图如图1-1所示。
注:来自队友的制作 这是我的队友 kiro_1023
2.2系统整体设计流程
系统功能流程图如图1-2所示,初始化完成后,OLED屏首先显示菜单界面,等待用户利用44矩阵按键选择功能。
若选择A功能则进入刷卡解锁功能,RC522能够识别并判断通过程序内存储的卡号控制电磁铁开门,同时OLED屏显示刷卡开门的卡号和卡内的身份,三秒后显示当地的温湿度数据,如果卡号并非程序内存储的卡号,则会提示刷正确的卡。
若选择B功能则进入密码解锁功能,用户输入四位密码与存储密码的数组比较,若正确则显示开门,三秒后显示当地的温湿度数据,如果密码错误则提示用户再输入一次,若用户输入错误密码超过三次,OLED屏则显示该功能已被禁用,只能按“”键退出该功能。
若选择C功能则进入录入信息功能,用户可将程序内没有存储的卡进行刷卡,刷卡后OLED屏会显示卡录入成功并显示卡号,如果用程序内已经存储的卡录入信息,OLED屏则会提示该卡已经存在。
若选择D功能则进入修改密码功能,用户需要先输入旧密码让程序进行与旧密码进行比对,若密码正确则进入修改密码界面,用户可以输入新的四位密码修改密码,若用户输入错误密码超过三次,OLED屏则显示该功能已被禁用,只能按“*”键退出该功能。
注:来自队友的制作 这是我的队友 kiro_1023
三、硬件单元的接口连接设计
3.1 硬件总体接线设计
硬件总体接线原理图如图2-1所示,在本系统中,我们采用STM32F103RCT6控制RC522射频模块、OLED屏、4*4矩阵键盘等模块来实现基本功能,并利用电磁铁模拟小区内门禁系统的开关门状态。
图中详细描述了各个模块与单片机各引脚的链接关系。
四、软件详细设计
我们的软件系统一共设计了4个功能,分别是A刷卡解锁、B输入密码解锁、C录入新卡、D修改密码。软件总体设计思路如图3-1所示。
刷卡解锁的软件设计思路如图3-3所示。
密码解锁功能流程图如图3-5所示。
修改密码的功能是密码解锁功能的延伸。当用户按下D进入修改密码模式后,单片机开始循环执行change_passwd()函数。
在change_passwd()函数中会经历输入旧密码的过程,此时输入旧密码的操作和密码解锁的操作完全相同。当旧密码输入正确后,进入新密码的输入循环,此时变量changePasswd用于存放输入新密码的位数,数组scan_key用来存放输入的密码值,当changePasswd等于4时表示已经输入了4位新密码,紧接着进入修改密码的操作。由于程序中lock_passwd指针指向的是存放初始密码的数组p_lock_passwd的首地址,所以修改密码就是将数组scan_key的值逐位赋给数组lock_passwd,从而实现密码替换的效果,若此时再进入密码解锁功能进行解锁时就需要输入新密码。
五、核心函数描述和注释
.c文件内函数简介(有注释,主要提供大家思路
main.c:
个人认为比较精髓的代码(可能是因为是自己理解然后自己写出来的):
因为卡号是4字节数据,而OELD显示屏的函数每次只能显示1个字符即半字节,例如:卡号为3B42A921
,虽然使用%X%X%X%X
在串口可以打印出来,但对于OLED显示屏中我们需要数据分位高低位存入长度为八字节的数组来依次显示。
OLED是通过
//将刷卡的卡号存入主函数的显示数组
*(oled_use_p++) = ((SN[0]>>4)>9) ?(SN[0]>>4)-10+'a' :(SN[0]>>4)+'0';
*(oled_use_p++) = ((SN[0]&0x0f)>9)?(SN[0]&0x0f)-10+'a':(SN[0]&0x0f)+'0';
*(oled_use_p++) = ((SN[1]>>4)>9) ?(SN[1]>>4)-10+'a' :(SN[1]>>4)+'0';
*(oled_use_p++) = ((SN[1]&0x0f)>9)?(SN[1]&0x0f)-10+'a':(SN[1]&0x0f)+'0';
*(oled_use_p++) = ((SN[2]>>4)>9) ?(SN[2]>>4)-10+'a' :(SN[2]>>4)+'0';
*(oled_use_p++) = ((SN[2]&0x0f)>9)?(SN[2]&0x0f)-10+'a':(SN[2]&0x0f)+'0';
*(oled_use_p++) = ((SN[3]>>4)>9) ?(SN[3]>>4)-10+'a' :(SN[3]>>4)+'0';
*(oled_use_p++) = ((SN[3]&0x0f)>9)?(SN[3]&0x0f)-10+'a':(SN[3]&0x0f)+'0';
*(oled_use_p++) = '\0';
刷卡成功后的DHT11数据显示函数
relay = 1;//继电器关闭,电磁铁不通电
OLED_ShowString(0,4,"T=");//oled显示
OLED_ShowString(48,4,"H=");
DHT11_Read_Data(&temp,&humi);//DHT11获取温湿度,存入temp(温度),humi(湿度)
TandH[0] = temp/10+'0';//存放高位
TandH[1] = temp%10+'0';//存放低位
TandH[2] = '%';
TandH[3] = '\0';
TandH[4] = humi/10+'0';
TandH[5] = humi%10+'0';
TandH[6] = '%';
TandH[7] = '\0';
p = TandH;
OLED_ShowString(16,4,p);//OLED_ShowString是遇到'\0'停止打印
p = TandH+4;
OLED_ShowString(64,4,p);
矩阵键盘行列扫描函数:
//mode:0,不支持连续按;1,支持连续按;
u8 JZKEY_Scan(u8 mode)
{
delay_init();
if(mode)
{
key0_up=1;
key1_up=1;
key2_up=1;
key3_up=1;
key4_up=1;
key5_up=1;
key6_up=1;
key7_up=1;
key8_up=1;
key9_up=1;
keyA_up=1;
keyB_up=1;
keyC_up=1;
keyD_up=1;
keyX_up=1;
keyJ_up=1;
}
//第一行
Hang_00_L;//把第一行输出低电平
Hang_01_H;
Hang_02_H;
Hang_03_H;
if(key1_up&&Lie_00_V==0)
{
delay_ms(jpys); //延时20秒,软件消抖
key1_up=0;
if(Lie_00_V==0) //如果第一列是低电平,说明有键被按下,如果没有直接退出if语句
{
return '1';
}
}else if(Lie_00_V==1)key1_up=1;
if(key2_up&&Lie_01_V==0)//如果第二列是低电平,
{
delay_ms(jpys);//延时20秒,软件消抖
key2_up=0;
if(Lie_01_V==0)//如果第二列是低电平,说明有键被按下,如果没有直接退出if语句
{
return '2';
}
}else if(Lie_01_V==1)key2_up=1;
if(key3_up&&Lie_02_V==0)
{
delay_ms(jpys);
key3_up=0;
if(Lie_02_V==0)
{
return '3';
}
}else if(Lie_02_V==1)key3_up=1;
if(keyA_up&&Lie_03_V==0)//如果第四列是低电平
{
delay_ms(jpys);
keyA_up=0;
if(Lie_03_V==0)//如果第四列是低电平,说明有键被按下,如果没有直接退出if语句
{
return 'A';
}
}else if(Lie_03_V==1)keyA_up=1;
//第二行
Hang_00_H;
Hang_01_L;//把第二行拉低
Hang_02_H;
Hang_03_H;
if(key4_up&&Lie_00_V==0)//如果第一列是低电平
{
delay_ms(jpys);
key4_up=0;
if(Lie_00_V==0)//说明有键被按下,如果没有直接退出if语句
{
return '4';
}
}else if(Lie_00_V==1)key4_up=1;
if(key5_up&&Lie_01_V==0)
{
delay_ms(jpys);
key5_up=0;
if(Lie_01_V==0)
{
return '5';
}
}else if(Lie_01_V==1)key5_up=1;
if(key6_up&&Lie_02_V==0)
{
delay_ms(jpys);
key6_up=0;
if(Lie_02_V==0)
{
return '6';
}
}else if(Lie_02_V==1)key6_up=1;
if(keyB_up&&Lie_03_V==0)
{
delay_ms(jpys);
keyB_up=0;
if(Lie_03_V==0)
{
return 'B';
}
}else if(Lie_03_V==1)keyB_up=1;
//第三行
Hang_00_H;
Hang_01_H;
Hang_02_L;//把第三行置低
Hang_03_H;
if(key7_up&&Lie_00_V==0) //如果第一列是低电平
{
delay_ms(jpys);//延时20秒
key7_up=0;
if(Lie_00_V==0)//说明有键被按下,如果没有直接退出if语句
{
return '7';
}
}else if(Lie_00_V==1)key7_up=1;
if(key8_up&&Lie_01_V==0)
{
delay_ms(jpys);
key8_up=0;
if(Lie_01_V==0)
{
return '8';
}
}else if(Lie_01_V==1)key8_up=1;
if(key9_up&&Lie_02_V==0)
{
delay_ms(jpys);
key9_up=0;
if(Lie_02_V==0)
{
return '9';
}
}else if(Lie_02_V==1)key9_up=1;
if(keyC_up&&Lie_03_V==0)
{
delay_ms(jpys);
keyC_up=0;
if(Lie_03_V==0)
{
return 'C';
}
}else if(Lie_03_V==1)keyC_up=1;
//第四行
Hang_00_H;
Hang_01_H;
Hang_02_H;
Hang_03_L;//把第四行置低
if(keyX_up&&Lie_00_V==0)//如果第一列是低电平
{
delay_ms(jpys);
keyX_up=0;
if(Lie_00_V==0)//说明有键被按下,如果没有直接退出if语句
{
return '*';
}
}else if(Lie_00_V==1)keyX_up=1;
if(key0_up&&Lie_01_V==0)
{
delay_ms(10);
key0_up=0;
if(Lie_01_V==0)
{
return '0';
}
}else if(Lie_01_V==1)key0_up=1;
if(keyJ_up&&Lie_02_V==0)//如果第三列是低电平
{
delay_ms(jpys);
keyJ_up=0;
if(Lie_02_V==0)//说明有键被按下,如果没有直接退出if语句
{
return '#';
}
}else if(Lie_02_V==1)keyJ_up=1;
if(keyD_up&&Lie_03_V==0)
{
delay_ms(jpys);
keyD_up=0;
if(Lie_03_V==0)
{
return 'D';
}
}else if(Lie_03_V==1)keyD_up=1;
return 'N';//无按键按下,返回N
}
输入密码开关门函数:
/***********************
输入密码开关门
思路:形参为 主函数中密码存放的数组的首地址
在函数中声明一个数组,用来存放按键输入的密码
输入4位密码后,自动使用指针位运算与密码表内容进行比对
完全匹配则返回给主函数一个开门指令'R'
***********************/
u8 entry_passwd(u8 * lock_passwd) //输入密码,开关门
{
u8 temp = 'N'; //定义临时变量,用来存放按键键值
if((temp=JZKEY_Scan(0))!='N') //判断,按键按下时进入(不按按键返回N)
{
if(temp=='*')
{
for(num=0;num<4;num++) //输入一半返回时,输入缓冲区清零
scan_key[num] = '\0';
num=0;
return 0;
}
scan_key[num] = temp; //把输入的密码存入scan_key数组
//printf("scan_key=%c\n",scan_key[num]);
num++; //计数++,输入密码的位数
OLED_ShowString(56,2,scan_key); //显示屏显示输入的密码
}
// printf("num=%d",num);
if(num==4) //如果输入了四位密码
{
//先将计数清零
if(*(lock_passwd++)==scan_key[0]&&*(lock_passwd++)==scan_key[1]&&*(lock_passwd++)==scan_key[2]&&*(lock_passwd++)==scan_key[3])//逐位判断密码是否和密码表密码相同
{
OLED_ShowString(56,2," ");//OLED显示passwd区域清除
for(num=0;num<4;num++) //密码缓冲区清零
scan_key[num]='\0';
num = 0; //num归零,防止再进入if
lock_passwd = lock_passwd-4;//密码表指针回到0位
return 'R'; //返回开门指令
}
else
{
OLED_ShowString(0,4,"Wrong passwd!!");
for(num=0;num<4;num++) //密码缓冲区清零
scan_key[num]='\0';
num = 0; //num归零,防止再进入if
LED1 = 0;
delay_ms(20000); //红灯亮以示警告
delay_ms(20000);
LED1 = 1;
OLED_ShowString(56,2," ");//OLED显示passwd区域清除
if(++warning==3)
{
warning = 0;
OLED_Clear();
while(1) //错误3次,死循环,led闪烁报警,只能按*返回主页面
{
OLED_ShowString(0,0,"Password has been disabled!Please contact the administrator!");
LED1 = !LED1;
LED0 = !LED0;
delay_ms(50);
if(JZKEY_Scan(0)=='*')
{
LED1=1;
LED0=1;
OLED_Clear();
return 0;
}
}
}
}
}
return 'W'; //返回关门指令
}
/***********************
输入密码开关门
***********************/
修改密码功能函数:
/***********************
修改密码
***********************/
u8 change_passwd(u8 * lock_passwd) //输入密码,开关门
{
u8 changePasswd=0;
u8 temp = 'N'; //定义临时变量,用来存放按键键值
OLED_ShowString(0,2,"OldPasswd:"); //显示屏显示输入的密码
if((temp=JZKEY_Scan(0))!='N') //判断,按键按下时进入(不按按键返回N)
{
if(temp=='*')
{
for(num=0;num<4;num++) //输入一半返回时,输入缓冲区清零
scan_key[num] = '\0';
num=0;
return 0;
}
scan_key[num] = temp; //把输入的密码存入scan_key数组
//printf("scan_key=%c\n",scan_key[num]);
num++; //计数++,输入密码的位数
OLED_ShowString(80,2,scan_key); //显示屏显示输入的密码
}
if(num==4) //如果输入了四位密码
{
//先将计数清零
if(*(lock_passwd++)==scan_key[0]&&*(lock_passwd++)==scan_key[1]&&*(lock_passwd++)==scan_key[2]&&*(lock_passwd++)==scan_key[3])//逐位判断密码是否和密码表密码相同
{
OLED_ShowString(80,2," ");
OLED_ShowString(0,2,"NewPasswd:");
for(num=0;num<4;num++) //输入缓冲区清零
scan_key[num] = '\0';
while(1)
{
if((temp=JZKEY_Scan(0))!='N') //判断,按键按下时进入(不按按键返回N)
{
if(temp=='*')
{
for(num=0;num<4;num++) //输入一半返回时,输入缓冲区清零
scan_key[num] = '\0';
num=0;
changePasswd=0;
return 0;
}
scan_key[changePasswd] = temp; //把输入的密码存入scan_key数组
//printf("scan_key=%c\n",scan_key[num]);
changePasswd++; //计数++,输入密码的位数
OLED_ShowString(80,2,scan_key); //显示屏显示输入的密码
}
if(changePasswd==4)
{
lock_passwd = lock_passwd-4;//密码表指针回到0位
*(lock_passwd++)=scan_key[0];//修改密码
*(lock_passwd++)=scan_key[1];
*(lock_passwd++)=scan_key[2];
*(lock_passwd++)=scan_key[3];
for(num=0;num<4;num++) //输入缓冲区清零
scan_key[num] = '\0';
num=0;
return 'R';
}
}
}
else
{
OLED_ShowString(0,4,"Wrong passwd!!");
for(num=0;num<4;num++) //密码缓冲区清零
scan_key[num]='\0';
num = 0; //num归零,防止再进入if
LED1 = 0;
delay_ms(20000); //红灯亮以示警告
delay_ms(20000);
LED1 = 1;
OLED_ShowString(80,2," ");//OLED显示passwd区域清除
OLED_ShowString(0,4,row_clear);//OLED显示passwd区域清除
if(++warning1==3)
{
warning1 = 0;
OLED_Clear();
while(1) //错误3次,死循环,led闪烁报警,只能按*返回主页面
{
OLED_ShowString(0,0,"Password has been disabled!Please contact the administrator!");
LED1 = !LED1;
LED0 = !LED0;
delay_ms(50);
if(JZKEY_Scan(0)=='*')
{
LED1=1;
LED0=1;
OLED_Clear();
return 0;
}
}
}
}
}
return 'W'; //返回关门指令
}
/***********************
修改密码
***********************/
刷卡解锁功能函数:
u8 card_unlock(void)
{
u8 i = 0;//用于规定匹配次数
u8 falg_sql = 1;//用于操作card_sql数组指针
u8 size=0;//存放card_sql的大小
u8 card_bit=0;//存放卡在card_sql中的序号
//unsigned char test_addr=0x0F;
status = PcdRequest(PICC_REQALL,CT);//寻卡
if(status==MI_OK)// 寻卡成功
{
status=MI_ERR;
status = PcdAnticoll(SN);// 防冲撞 获得UID 存入SN
}
if (status==MI_OK)// 防冲撞成功
{
size = strlen(card_sql);//size存放card_sql的实际长度
status = MI_ERR;
ShowID(SN); // 串口打印卡的ID号 UID
for(i=0;i<(size/5);i++)
{
//先size存放card_sql数组的长度,每5位为一张卡的信息,一字节序号,四字节卡号
if((SN[0]==card_sql[falg_sql])&&(SN[1]==card_sql[falg_sql+1])&&(SN[2]==card_sql[falg_sql+2])&&(SN[3]==card_sql[falg_sql+3])) //刷卡后的卡号与单片机内部的卡数据库进行比较
{
card_bit=card_sql[falg_sql-1];
printf("\r\nThe User is:num%d\r\n",falg_sql);
}
falg_sql += 5;//让数组位置指向下一张卡的序号信息处
printf("card_bit=%d\r\n",card_bit);
}
if(card_bit == 0)//card_bit默认值为0,若进行数据匹配后仍为0则表示,卡的信息没有录入,为无效卡
{
printf("wrong card\r\n");
return 0;
}
else//此时card_bit为卡在caed_sql数组的序号值
{
return card_bit;
}
}
printf("no card\r\n");
return 255;//未寻到卡返回255
}
录入卡操作函数:
u8 card_infor_entry(u8 * oled_use_p)//oled_use_p指向主函数的显示数组
{
u8 i = 0;//用于规定匹配次数
u8 falg_sql = 1;//用于操作card_sql数组指针
u8 size=0;//存放card_sql的大小
u8 card_bit=0;//存放卡在card_sql中的序号
u8 *p = oled_use_p;
status = PcdRequest(PICC_REQALL,CT);//寻卡
if(status==MI_OK)// 寻卡成功
{
status=MI_ERR;
status = PcdAnticoll(SN);// 防冲撞 获得UID 存入SN
}
if (status==MI_OK)// 防冲撞成功
{
size = strlen(card_sql);//size存放card_sql的实际长度
printf("size=%d\r\n",size);
status = MI_ERR;
ShowID(SN); // 串口打印卡的ID号 UID
for(i=0;i<(size/5);i++)
{
//先size存放card_sql数组的长度,每5位为一张卡的信息,一字节序号,四字节卡号
if((SN[0]==card_sql[falg_sql])&&(SN[1]==card_sql[falg_sql+1])&&(SN[2]==card_sql[falg_sql+2])&&(SN[3]==card_sql[falg_sql+3])) //刷卡后的卡号与单片机内部的卡数据库进行比较
{
card_bit=card_sql[falg_sql-1];
printf("\r\nThe User is:num%d\r\n",falg_sql);
}
falg_sql += 5;//让数组位置指向下一张卡的序号信息处
printf("card_bit=%d\r\n",card_bit);
}//匹配卡结束
//将刷卡的卡号存入主函数的显示数组
*(oled_use_p++) = ((SN[0]>>4)>9) ?(SN[0]>>4)-10+'a' :(SN[0]>>4)+'0';
*(oled_use_p++) = ((SN[0]&0x0f)>9)?(SN[0]&0x0f)-10+'a':(SN[0]&0x0f)+'0';
*(oled_use_p++) = ((SN[1]>>4)>9) ?(SN[1]>>4)-10+'a' :(SN[1]>>4)+'0';
*(oled_use_p++) = ((SN[1]&0x0f)>9)?(SN[1]&0x0f)-10+'a':(SN[1]&0x0f)+'0';
*(oled_use_p++) = ((SN[2]>>4)>9) ?(SN[2]>>4)-10+'a' :(SN[2]>>4)+'0';
*(oled_use_p++) = ((SN[2]&0x0f)>9)?(SN[2]&0x0f)-10+'a':(SN[2]&0x0f)+'0';
*(oled_use_p++) = ((SN[3]>>4)>9) ?(SN[3]>>4)-10+'a' :(SN[3]>>4)+'0';
*(oled_use_p++) = ((SN[3]&0x0f)>9)?(SN[3]&0x0f)-10+'a':(SN[3]&0x0f)+'0';
*(oled_use_p++) = '\0';
if(card_bit == 0)//卡不存在,录入卡
{
*(oled_use_p) = size/5+1;
oled_use_p = p;
card_sql[size] = size/5+1;
card_sql[size+1]=SN[0];
card_sql[size+2]=SN[1];
card_sql[size+3]=SN[2];
card_sql[size+4]=SN[3];
card_sql[size+5]='\0';
printf("SN:\r\n");
ShowID(SN);
printf("card_sql:\r\n");
for(i=0;card_sql[i]!='\0';i++)
{
printf("%x",card_sql[i]);
}
printf("wrong card\r\n");
return 0;
}
else//此时card_bit为卡在caed_sql数组的序号值
{
printf("卡已经存在!\r\n");//卡已经存在
return card_bit;
}
}
printf("no card\r\n");
return 255;//未寻到卡返回255
}
六、系统调试过程
1菜单显示
2刷卡解锁显示身份
3显示温湿度
4密码解锁
5.0密码解锁显示温湿度
5.1输入错误密码显示密码错误(默认密码1234)
6输入三次错误密码显示密码解锁功能被禁用
7C功能录入新卡
8录入新卡成功显示卡号
9再用该卡录入信息_显示卡已存在
10用新卡开门_门开了
11换新密码(1234换为5555)
12换新密码成功
13用新密码解锁成功
七、结论与改进
函数中间涉及到指针的操作,也可以不用指针操作,只是想到在练习C语言基础正好拿这个项目训练一下逻辑思维。这只是第一版代码,后期还有很多需要修改的地方。
完成本课程设计需要一些单片机基础和RC522使用基础(学习RC522可看这篇博客,这是该博主花费三天凝结的智慧结晶 基于STM32的RC522模块读写数据块以及电子钱包充值扣款系统的设计)
对于本次课程设计,感觉它是一个对代码的逻辑能力要求比较高的课设,从选择功能、录入新卡、刷卡解锁到密码解锁、修改密码,都要求我们需要有清醒的代码逻辑意识。
最好的解决方法是先列一个清单说出要完成的功能,然后分块去逐个完成它们。写代码时,可以先从dev C++中编写C语言程序来模拟存储卡到模拟数据库中的逻辑和密码存储部分的逻辑。
在改进方面,希望可以获得卡号后直接对卡进行读写操作来进行身份检测。因为第一版没有用上读写卡功能,并且不好删除卡。
暂时想到的第二版方案是:
录入卡,就是往特定的扇区写特定的数据
刷卡开门就是读块数据,如果读到的是和预先写入的是相同信息就开门
如果想删除卡,那就把块内信息进行清空处理(写0)
大家有更好的办法也可以在评论区一起讨论。
最初版设计
STM32RCT6+RC522+OLED,刷卡显示卡号
完整版工程文件下载链接
RFID课程设计工程文件,基于STM32F103RCT6的智能门禁系统
到了这里,关于RFID课程设计--基于STM32F103RCT6的智能门禁系统,STM32RCT6+RC522+OLED+DHT11+4*4矩阵键盘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!