基于单片机的RFID门禁卡的设计
proface:随着电子行业不断发展,人们对开锁的多样化,要求越来越高,本系统是利用单片机对射频卡RFID-RC522的操作,对卡的读写,单片机做判断,从而决定门锁的开与关,同时它还具备了密码开锁的功能。
接下来,介绍一下我做的过程!!!
一、RFID-RC522射频卡的介绍
1、MFRC522是高密度集成的非接触式(13.56MHz)读写卡芯片。此模块利用调制和解调原理,并将它们完全集成到各种非接触式通信方法和协议中(13.56MHz)。
可实现各种不同主机接口的功能:
SPI通信方式,串行UART(类似RS232,电压电平取决于提供的管脚电压),IIC通信方式。
我采用的SPI通信方式。
接口介绍:
RFID_RC522 | STC89C52 |
SDA | P2^7 |
SCK | P2^6 |
MOSI | P2^0 |
MISO | P2^3 |
NC | 悬空 |
GND | 地 |
RST | P2^2 |
3V3 | 3.3V |
SDA:使用SPI通信方式时,此端口相当于NSS(片选)。
SCK:SPI的时钟信号由主机产生。
MOSI:数据由主机发送到射频卡MFRC522。
MISO:数据由MFRC522返回到主机。
2、SPI通信方式
读:
按照读写时序输出字节(MOSI)就会从MSB 循环输出,同将输入字节(MISO)从LSB 循环移入,每次移动一位。
代码:
unsigned char SPIReadByte(void)
{unsigned char SPICount; // Counter used to clock out the dataunsigned char SPIData; SPIData = 0;for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock in the data to be read{SPIData <<=1; // Rotate the dataCLR_SPI_CK; //nop();//nop(); // Raise the clock to clock the data out of the MAX7456if(STU_SPI_MISO){SPIData|=0x01;}SET_SPI_CK; //nop();//nop(); // Drop the clock ready for the next bit} // and loop backreturn (SPIData); // Finally return the read data
}
写:
代码:
void SPIWriteByte(unsigned char SPIData)
{unsigned char SPICount; // Counter used to clock out the datafor (SPICount = 0; SPICount < 8; SPICount++){if (SPIData & 0x80){SET_SPI_MOSI;}else{CLR_SPI_MOSI;} nop();nop();CLR_SPI_CK;nop();nop();SET_SPI_CK;nop();nop();SPIData <<= 1;}
}
3、射频卡的操作
第7位,为1,表示为读的状态;为0,表示为写的状态。
举个例子:
我要读下面这个寄存器的东西
它的默认地址是0x08H(0000 1000B),根据上面说的传输规则,实际操作的值应该是0x88H(1000 1000B);
例如我要写下面这个寄存器:
它的默认地址是0x04H(0000 0100B),根据上面说的传输规则,实际操作的值应该是0x04H(0000 0100B);
写RCC522寄存器:
/
//功 能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
/
void WriteRawRC(unsigned char Address, unsigned char value)
{ unsigned char ucAddr;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E);SPIWriteByte(ucAddr);SPIWriteByte(value);SET_SPI_CS;
}
读RC522寄存器:
/
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/
unsigned char ReadRawRC(unsigned char Address)
{unsigned char ucAddr;unsigned char ucResult=0;CLR_SPI_CS;ucAddr = ((Address<<1)&0x7E)|0x80;SPIWriteByte(ucAddr);ucResult=SPIReadByte();SET_SPI_CS;return ucResult;
}
复位RCC522:
在这里需要搞懂几个寄存器和命令,
CommandReg寄存器:
向此寄存器写入0x0F时,激活复位RC522;
向ModeReg寄存器写Ox3D表明复位的时候定义了我们的RC522和Mifare卡进行通信,因为我们通信的CRC校验码为6363 ;
代码如下:
/
//功 能:复位RC522
//返 回: 成功返回MI_OK
/
char PcdReset(void)
{SET_RC522RST;delay_ns(10);CLR_RC522RST;delay_ns(10);SET_RC522RST;delay_ns(10);// PCD_RESETPHASE位RC522中的复位字,CommandReg地址用来控制启动或停止命令的执行 // PCD_RESETPHASE = 0x0F WriteRawRC(CommandReg,PCD_RESETPHASE);delay_ns(10);WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363WriteRawRC(TReloadRegL,30); WriteRawRC(TReloadRegH,0);WriteRawRC(TModeReg,0x8D);WriteRawRC(TPrescalerReg,0x3E);WriteRawRC(TxAutoReg,0x40);//必须要return MI_OK;
}
其他的就不多说了,一般模块资料里面都有,只要清楚怎么移植就行!!!!
二、LCD12864液晶屏
1、 LCD12864能显示汉字、字母、字符、数字,能显示数字和字符的个数为64个(一共4行,每行16个),能显示汉字的个数为32个(一共4行,每行8个)。
外观尺寸图:
2、每一行显示地址:
可以看到第一行的起始地址是80H,末尾地址是87H,当每一次需要向该位置写入指定的东西,都要调用它的写命令函数,写入对应的地址信息(类似于标定坐标),同理第二行的地址范围(90H~97H),第三行的地址范围(88H~8FH),第四行的地址范围(98H~9FH)。
于是可以写一个标定坐标的函数
/*********************************************************/
/* 设定显示位置 X:行数 Y:列数 */
/*********************************************************/
void lcd_pos(uchar X,uchar Y)
{ uchar pos;if (X==0){X=0x80;}else if (X==1){X=0x90;}else if (X==2){X=0x88;}else if (X==3){X=0x98;}pos = X+Y ; lcd_wcmd(pos); //显示地址
}
2、写指令、写数据函数
/*******************************************************************/
/*写指令数据到LCD */
/*RS=L。RW=L,E=高脉冲,D0-D7=指令码。*/
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{ while(lcd_busy());LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;delay(1);LCD_data = cmd;delay(1);LCD_EN = 1;delay(1);LCD_EN = 0;
}
/*******************************************************************/
/*写显示数据到LCD */
/*RS=H,RW=L。E=高脉冲,D0-D7=数据。 */
/*******************************************************************/
void lcd_wdat(uchar dat)
{ while(lcd_busy());LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;LCD_data = dat;delay(1);LCD_EN = 1;delay(1);LCD_EN = 0;
}
在写入显示的数据之前,有两种显示方式。第一种的先通过lcd_wcmd()这个函数,标定你要显示的位置,在利用lcd_wdat()这个函数写入你要显示的数据;第二种方式是先通过lcd_pos()这个函数标定你要显示的坐标,在通过lcd_wdat()函数传入你要显示的数据,即可。
清除某一行函数:
/********************清除某一行*********************/
void display_clear_line(uchar a)
{uchar i;lcd_pos(a,0);for(i=0;i<16;i++)lcd_wdat(' ');
}
三、密码键盘设计
密码键盘我采用的是4*4的矩阵按键,用单片机的8个I/o口控制的。原理图如下:
矩阵按键的原理:有两种不同的写法,扫描和状态机的方法;
第一种,列扫描法,通过预先将矩阵按键的某一行置为0,其他行包括列全部置为1,然后去判断那一列为低电平(0),从而确定那个按键被按下;举个例子
void Key_Scanf(void)
{p33=0;p32=p31=p30=1;p34=1;p35=1;p36=1;p37=1;if(p37==0){delay(1);if(p37==0){while(!p37);number=0;display(number); //number指代键值}}else if(p36==0){delay(1);if(p36==0){while(!p36);number=1;display(number);}}else if(p35==0){delay(1);if(p35==0){while(!p35);number=2;display(number);}}else if(p34==0){delay(1);if(p34==0){while(!p34);number=3;display(number);}} //第一行
}
首先把第一行的P33端口置为0,其他P3口为1,然后去检测P37,P36,P35,P34这四个列端口值的变化,如果P37为0,表示第一行第一列第一个按键按下,返回键值0,其他情况同理可得。
第二种写法:
uchar key_scan(void) //键盘扫描
{num=16;//16表示没按键输入P1=0xfe; //扫描第一行temp=P1;temp&=0xf0;if(temp!=0xf0) //检测有按键按下{Delay_ms(5);temp=P1;temp&=0xf0;if(temp!=0xf0){temp=P1;switch(temp) //判断按下是哪一个按键{case 0xee:num=1;break;case 0xde:num=2;break;case 0xbe:num=3;break;case 0x7e:num=12;break;}while(temp!=0xf0){temp=P1;temp&=0xf0; }}}P1=0xfd; //扫描第二行temp=P1;temp&=0xf0;if(temp!=0xf0){Delay_ms(5);temp=P1;temp&=0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xed:num=4;break;case 0xdd:num=5;break;case 0xbd:num=6;break;case 0x7d:num=13;break;}while(temp!=0xf0){temp=P1;temp&=0xf0; } }}P1=0xfb; //扫描第三行temp=P1;temp&=0xf0;if(temp!=0xf0){Delay_ms(5);temp=P1;temp&=0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xeb:num=7;break;case 0xdb:num=8;break;case 0xbb:num=9;break; case 0x7b:num=14;break;}while(temp!=0xf0){temp=P1;temp&=0xf0; } }}P1=0xf7; //扫描第四行temp=P1;temp&=0xf0;if(temp!=0xf0){Delay_ms(5);temp=P1;temp&=0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xe7:num=10;break;case 0xd7:num=0;break;case 0xb7:num=11;break;case 0x77:num=15;break;}while(temp!=0xf0){temp=P1;temp&=0xf0; } }}return num; //返回按键对应编号
}
区别第一种写法,第二种是去判断整个P3端口的值,从而确定,状态,返回键值的大小。
开锁与锁门我是用继电器模拟的,继电器闭合模拟开门,反之,关门状态。
当线圈里面没有电流时,A,B两端是连在一起的,当线圈中有电流流过时,电磁铁会吸住衔铁,B,C就会连在一起,A,B就会断开。一般我们把B端叫做公共端(com),A端叫做常闭端,C端叫做常开端。
整个工程如下,有需要请自取,作者能力有限,不喜勿喷,谢谢啦!!!!!!!
(45条消息) 基于51单片机的智能门禁系统设计资源-CSDN文库https://download.csdn.net/download/qq_62291061/87745877?spm=1001.2014.3001.5503
基于单片机的RFID门禁卡的设计相关推荐
- 基于STM32单片机的RFID门禁显示系统
基于STM32单片机的RFID门禁显示系统 本设计由STM32F103C8T6单片机最小系统+RFID-RC522模块+继电器模块+蜂鸣器电路+LCD1602液晶显示电路+按键电路+电源电路组成 1. ...
- 单片机毕设 RFID门禁防盗报警系统(源码+论文)
文章目录 1 简介 2 绪论 2.1 课题背景与目的 3 射频识别 3.1 射频识别技术 3.2 射频识别模块 3.2.1 RFID模块 3.2.2 RFID模块组成 4 系统设计 4.1 系统架构 ...
- NFC - PN532复制RFID门禁卡
楼下小区门禁卡50一张?就这? 使用 PN532 对 M1卡.UID卡进行复制.转录. 适用绝大多数未加密的小区.公司.物业门禁. 读取 UID卡内容,保存为.dump文件 准备材料: PN532模块 ...
- 基于单片机的RFID刷卡门禁电路设计(#0206)
功能描述 1.采用51/52单片机作为主控芯片: 2.采用LCD12864标准字符型液晶显示: 3.专用读卡器模块RC522用来读射频卡的信息,当有卡进入到读卡器读卡的范围内时就会读取到相应的卡序列号 ...
- 基于单片机的RFID考勤刷卡电路设计(#0207)
功能描述 1.采用51/52单片机: 2.采用RC522射频模块读卡功能: 3.采用AT24C02存储职位登记信息功能: 4.采用蜂鸣器提示功能: 5.采用DS1302实时时钟功能; 6.可设置射频卡 ...
- 51单片机的RFID门禁系统
一.硬件方案 本RFID系统设计可分为硬件部分和软件部分.硬件部分以MFRC522射频识别模块为核心,结合主控模块STC89C52设计系统的外围硬件电路,实现对射频卡的控制与MCU之间的互通.软件部分 ...
- 实验33:RFID门禁卡实验
OK,本实验分为两个部分 一.读卡 二.显示不同的卡的信息,同时继电器动作 01 硬件电路设计 读卡ID,两张卡,白卡和蓝卡,用txt文件名称体现 lib里面是库文件 把它放在自己的Arduino相应 ...
- arduino控制RFID门禁卡
一.实物连接 二.代码实现 #include"rfid.h" #include <LiquidCrystal_I2C.h> #include <Wire.h> ...
- 【ESP 保姆级教程】疯狂毕设篇 —— 案例:基于ESP8266的RFID门禁系统
忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️ ❤️ 本篇创建记录 2022-12-29 ❤️ ❤️ 本篇更新记录 2022-12-29 ❤️
最新文章
- 研发管理工具之迭代管理测评:PingCode VS Jira
- 基于Grafana的监控数据钻取功能应用实践
- vaadin_Vaadin提示:延迟加载和商品标识
- leetcode6. Z 字形变换
- 接口的定义与实现(重要)
- cnpm能用npm install吗_指纹锁一般能用几年? 指纹锁没电了怎么办
- 对文本文件的各操作(一)
- Java基础-面向接口(interface)编程
- Spring Cloud Alibaba | Dubbo 与 Spring Cloud 完美结合
- Flutter最佳入门方式——写一个计算器
- iOS如何优雅的处理“回调地狱Callback hell”(一)——使用PromiseKit
- 四种JSON解析工具--(json-libJacksonGsonFastJson)
- 分享CFA一级考试干货
- Moo Slidebox
- php-ftm,关于KEA128中FTM0/1的问题
- scrapy 报错401
- win10迁移C盘Administrator目录
- 2021年,第一份值得职场人“跪读”的书单来了
- python办公自动化价值是什么意思_用python进行办公自动化都需要学习什么知识呢?...
- 2021SC@SDUSC基于人工智能的多肽药物分析问题(六)