探究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