探究51单片机与NFC单片机的功能与应用

上学期间经常忘记带宿舍钥匙,所以便设计了一款NFC门锁。

该系统以传统stc89c52rc为主芯片,以rc522为NFC感应模块,外加lcd1602显示卡片信息,制作的一款NFC门锁。最多可以有10张卡片,卡片信息可以随意更改。

 该门锁检测到正确的卡片时舵机转动,蜂鸣器响一声,检测到错误卡片时舵机不会转动,同时蜂鸣器连响三声。

lcd1602显示屏可有可无,现在安装上只是为了方便查看卡片数据。通过串口通信也可以查看卡片信息。

效果展示:

51单片机nfc智能门锁

 识别到正确卡片:

 识别到错误图片:

串口通信效果:

 主要程序:

#include <reg52.h>
#include "main.h"
#include "rc522.h"
#include <string.h>
#include "LCD1602.h"
#include "Delay.h"
#include "Buzzer.h"

sbit PWM=P2^0;	 //舵机


//舵机要是方向反了,就把PWMmax改成7,把PWMmin改成22,如果还反就再次把PWMmax改成22,把PWMmin改成7
#define  PWMmax 	22	 //舵机最大角度
#define  PWMmin 	 7	 //舵机最小角度
/*
**********************************************************************
*                         本地全局变量
**********************************************************************
*/
	
u8 UID[5],Temp[4];
u16 count = PWMmin, time=0;//count控制舵机角度,7是最小角度,22是最大角度
u8 UI0[5]={0xE3,0x63,0xCF,0xFE};	   //	此处为6张卡的信息,UI0到UI5
u8 UI1[5]={0x00,0x54,0x87,0x11}; 
u8 UI2[5]={0x51,0x7E,0xC9,0xCF}; 		  
u8 UI3[5]={0x31,0x11,0x1B,0xD0}; 
u8 UI4[5]={0x8C,0xF3,0xDA,0x0B}; 
u8 UI5[5]={0x19,0x74,0xD9,0x59}; 
void Rc522Test1(void);
void Rc522Test2(void);

void T0_init()//定时器T0初始化
{	
   TMOD=0x01;	
   //初始化定时器值
   TH0=(65536-50000)/256;	
   TL0=(65536-50000)%256;	
   //打开中断
   EA=1;	
   TR0=1;	
   ET0=1;
}	


/*********************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void init0()
{
	TMOD = 0x21; 	// 方式一
	TH0 = 0X0FF;
	TL0 = 0X0A4;
	TR0 = 1;       // 开启定时器0
	EA = 1;		   // 开启总中断
	ET0 = 1;       // 定时器0允许中断
}

//舵机
void T0_inter() interrupt 1
{
	
	TH0 = 0X0FF;
	TL0 = 0X0A4;	
	time ++ ;
	if (time < count)	
	{
		PWM = 1;
	}
	else
	{
		PWM = 0;
	}
	if (time >= 200)
	{
		time = 0;
	}
}

void main(void)
{
	T0_init();
	LCD_Init();	
    init0();

	
	SysInit();
	
	Rc522Test1(); //最终运行工作模式
	//Rc522Test2(); //读取卡片数据的模式,视情况test1和test2选一
	
}

/*********************************************************************
* 函 数 名       : delay1ms
* 函数功能		 : 延时
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void delay1ms(unsigned int i)   //误差 0us,括号内填什么数字就是多少毫秒
{
    unsigned char a,b,c;
	for(;i>0;i--)
 	   for(c=1;c>0;c--)
    	    for(b=142;b>0;b--)
        	    for(a=2;a>0;a--);
}


/*********************************************************************
* 函 数 名       : delay10us
* 函数功能		 : 延时
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void delay10us(unsigned char i)   //误差 0us,括号内填什么数字就是多少个十微秒
{
    unsigned char a,b;
	for(;i>0;i--)
    	for(b=1;b>0;b--)
        	for(a=2;a>0;a--);
}

/*********************************************************************
* 函 数 名       : UartSendBytes
* 函数功能		 : 通过串口往外发送数据
* 参数列表       : unsigned char *c,要发的数据
* 函数输出    	 : 无
*********************************************************************/

void UartSendByte(u8 c)	//从串口发送1字节数据
{
	u8 i = 0;
	EA = 0;

	SBUF = c;
	while (!TI);
	TI = 0;

	EA = 1;
}

/*********************************************************************
* 函 数 名       : Rc522Test
* 函数功能		 : test1为运行代码,test2用于读取卡片id
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
//运行代码,正确的卡号响一次,其他卡响三次
void Rc522Test1(void)
{
	ce:
   while(1)
   {
	   		
   	   if (PcdRequest(0x52, Temp) == MI_OK)
	   {
	   		if (PcdAnticoll(UID) == MI_OK)
			{
			//此处为判断是否为代码内有标注的卡序列号,除非这五张卡,否则不执行判断
				if(strcmp(UID,UI0)==0||strcmp(UID,UI4)==0||strcmp(UID,UI1)==0||strcmp(UID,UI2)==0||strcmp(UID,UI5)==0)
				{
					Buzzer_Time(100);
	 				Rc522Test2();
					LCD_ShowHexNum(1,1,UID[0],2);
					LCD_ShowHexNum(1,4,UID[1],2);
					LCD_ShowHexNum(1,7,UID[2],2);
					LCD_ShowHexNum(1,10,UID[3],2);
					LCD_ShowString(2,1,"YES");
					count = PWMmax;						  //舵机转动
					Delay(1500);			
					count=PWMmin;						   //舵机转回去
					Delay(1000);	
					LCD_Init();	
					goto ce;

				}
				else
				{  
					int i;
					LCD_ShowString(1,1,"NO");
					for(i=0;i<3;i++)
					{
						Buzzer_Time(100);
						delay1ms(20);
					}
					
					LCD_Init();	
					goto ce;
				}	
			}
	   }
   }
}

//读取卡数据
void Rc522Test2(void)
{

   	   if (PcdRequest(0x52, Temp) == MI_OK)
	   {
	   		if (PcdAnticoll(UID) == MI_OK)
			{

	 			UartSendByte(UID[0]);		//读取卡序列号前四位
				UartSendByte(UID[1]);
				UartSendByte(UID[2]);
				UartSendByte(UID[3]);
				delay1ms(100);
				
				
													
			}
	   }
}

/*********************************************************************
* 函 数 名       : SysInit
* 函数功能		 : 串口初始化为2400波特率,寻卡,读写卡数据
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void SysInit(void)
{
    TMOD = 0x21;		// T1设置为8位自动重装载定时器			
    SCON = 0x40;		// 串口工作在模式1:8位UART波特率可变,且禁止接收
    TH1 = 0xE8;			// 单片机小精灵V1.3算出的2400波特率且波特率,晶振为11.0592MHz把这里改成0xE8,12M改成0xE8;
    TL1 = TH1;			// 加倍时的定时器设置值。
    PCON = 0x80;		// 设置为波特率加倍
	EA = 1;				// 开总中断
	ES = 1;			    // 开串口中断
	TR1 = 1;		    // 定时器1开启计数

    PcdReset();				//复位RC522
    PcdAntennaOff(); 	 	//关天线 		
    PcdAntennaOn();  		//开天线
	M500PcdConfigISOType('A');
}

接线为:

sbit     MF522_NSS  =    P1^4;		//这是SDA
sbit     MF522_SCK  =    P1^3;
sbit     MF522_SI   =    P1^2;
sbit     MF522_SO   =    P1^1;
sbit     MF522_RST  =    P1^0;		//RC500片选

 哔站视频连接:

【51单片机nfc智能门锁】 https://www.bilibili.com/video/BV1m7pveZEbe/?share_source=copy_web&vd_source=def262a63373c4f1afd6aee74809b6e1

记得看评论区

作者:山川行鹤scxh

物联沃分享整理
物联沃-IOTWORD物联网 » 探究51单片机与NFC单片机的功能与应用

发表回复