12864门禁系统

该博客介绍了使用51单片机设计的一个门禁系统,通过4X4键盘输入密码,系统会验证密码的正确性。如果密码错误,蜂鸣器会发出警告;正确时,LED会闪烁。12864液晶显示屏用作用户界面,初始显示‘欢迎光临’,并提供相应操作提示。
摘要由CSDN通过智能技术生成

12864门禁系统

采用51单片机设计门禁系统,4X4键盘用户输入密码,错误蜂鸣器叫一声,正确LED闪烁,12864作为用户界面,初始显示“欢迎光临”,正确与错误时12864有相应的提示。

代码

main.c

#include <reg51.h>
#include <intrins.h> //引入_nop_();函数
/*
	_nop_();指令需要的只是一个机械周期
	也就是12个时钟周期(震荡周期)
	_nop_(); 指令的延迟时间为 1us。
	可以较为精确得控制延迟时间。
*/

#include "zh-hans.h" //导入我们自己写的中文编码库

#define LCD_databus P1 //LCD8位数据口

sbit INT = P3^2;
sbit CS1 = P3^3;  //片选1,1有效,控制左半屏
sbit CS2 = P3^4;  //片选2,1有效,控制右半屏
sbit E = P3^5;    //使能信号
sbit RW = P3^6;   //读/写,1为读、0为写
sbit RS = P3^7;   //代码/数据,1为数据、0为代码

sbit BU = P3^1; //蜂鸣器,1为响
sbit LED = P3^0;    //小灯,1为亮

unsigned char key = 0x77;     //按键值
char key_press = 0; //按键是否按下

/*
	AMPIRE12864的组成:可以看成是两个64*64的屏幕
	通过CS1、CS2两个片选信号来控制,低电平选通
	RST复位信号,我们这里置为高电平表示不用复位
	
	DBx是并行输入端
	
	E是使能信号,置1可以设置DBx,置0表示交换结束
	RW为低电平表示写入数据,高电平表示读出数据
	
	RS为低电平表示指令操作,高电平表示数据操作
*/

/*
	键盘4x4
	1 2 3 返回
	4 5 6 清空
	7 8 9 退位
	# 0 * 确定
*/

/*************************函数声明***************************/
void delay(int z);
void read_busy();
void write_LCD_cmd(char value);
void write_LCD_data(char value);
void set_page(char page);
void set_line(char startline);
void set_column(char column);
void set_on_or_off(char choose);
void select_screen(char screen);
void clear_screen(char screen);
void clear_bottom_screen();
void init_LCD();
void display(char screen,char page,char column,char *p);
void display_charactars(char screen,char page,char column,char datacode);
void init_sys();
void tip_overlength();
void tip_lesslength();
void tip_pwderror();
void input_passwd();
void enter_sys();
/**************************************************************/


// 延时
void delay(int z)  
{
   
	int x,y;
	for(x=z;x>0;x--)
		for(y=114;y>0;y--);
}

//读“忙”函数——数据线最高位DB7=1则busy
void read_busy()
{
   
	P1 = 0x00; //DB送数
	RS = 0;  //代码
	RW = 1;  //读
	E = 1;   //1可设置DB
	while(P1 & 0x80);
	E = 0;
}

/***************************写入LCD***************************/
//向LCD中写入命令
void write_LCD_cmd(char value)
{
   
	read_busy(); //每次读写都要进行忙判断
	RS = 0;      //选择命令
	RW = 0;      //写操作  
	LCD_databus = value;
	E = 1;       //E由1->0锁存有效数据
	_nop_();     //空操作,用作延时一个机械周期1us
	_nop_();     //同上
	E = 0;
}

/*可以写成一个函数简便一点,
但是为了让大家好理解就先这样吧*/

//向LCD中写入数据
void write_LCD_data(char value)
{
   
	read_busy(); //每次读写都要进行忙判断
	RS = 1;      //选择数据
	RW = 0;      //写操作
	LCD_databus = value;
	E = 1;       //E由1->0锁存有效数据
	_nop_();     //空操作,用作延时一个机械周期1us
	_nop_();     //同上
	E = 0;
}
/**************************************************************/

/***************************设置*******************************/
//设置“页”,LCD12864共8页,一页是8行
void set_page(char page)
{
   
	page = 0xB8|page; //页的首地址0xB8
	write_LCD_cmd(page);
}

//设置显示的起始行
void set_line(char startline)
{
   
	startline = 0xC0|startline; //起始地址0xC0
	write_LCD_cmd(startline);
	//设置从哪行开始:共0-63;一般从0行开始显示
}

//设置显示的列
void set_column(char column)
{
   
	column = column & 0x3F; //列的最大值为64
	column = 0x40|column;   //列的首地址0x40
	write_LCD_cmd(column);  //列位置
}

//显示开、关函数,0x3E是关闭显示,0x3F是开启显示
void set_on_or_off(char choose)
{
   
	choose = 0x3E|choose; //0011 111x, choose只能为0或者1
	write_LCD_cmd(choose);
}
/**************************************************************/

/**************************屏幕选择***************************/
//选屏
void select_screen(char screen)
{
   
	switch(screen){
   
		case 0: CS1=0;CS2=0;break; //全屏
		case 1: CS1=0;CS2=1;break; //左半屏
		case 2: CS1=1;CS2=0;break; //右半屏
		default:break;
	}
}

//清屏
void clear_screen(char screen)
{
   
	char i,j;
	select_screen(screen);
	for(i=0;i<8;i++){
    //控制页数0-7,共8页
		set_page(i);
		set_column(0);
		for(j=0;j<64;j++){
    //控制列数0-63,共64列
			write_LCD_data(0x00); //写入0,地址指针自加1
		}
	}
}

//清最后一行屏
void clear_bottom_screen()
{
   
	char i;
	select_screen(0);
	
	set_page(6);   //最后一行
	set_column(0); //从第一列开始
	for(i=0;i<64;i++){
    //控制列数0-63,共64列
		write_LCD_data(0x00); //写入0,地址指针自加1
	}
	set_page(7);
	set_column(0); //从第一列开始
	for(i=0;i<64;i++){
    //控制列数0-63,共64列
		write_LCD_data(0x00); //写入0,地址指针自加1
	}
}
/**************************************************************/

//LCD的初始化
void init_LCD()
{
   
	read_busy();
	select_screen(0); //全屏
	set_on_or_off(0); //关闭显示
	select_screen(0); //全屏
	set_on_or_off(1); //开显示
	select_screen(0); //全屏
	clear_screen(0);  //清屏
	set_line(0);      //开始行:0
}

//显示汉字
void display(char screen,char page,char column,char *p)
{
   
	char i;
	select_screen(screen); //选屏
	set_page(page);        //控制页
	set_column(column);    //控制列
	for(i=0;i<16;i++){
        //控制16列的数据输出
		write_LCD_data(p[i]); 
		//汉字的上半部分
	}
	set_page(page+1);        //写下半页
	set_column(column);
	for(i=0;i<16;i++){
   
		write_LCD_data(p[i+16]); 
		//汉字的下半部分
	}
}

//显示字符
void display_charactars(char screen,char page,char column,char datacode)
{
   
	char i;
	select_screen(screen); //选屏
	set_page(page);        //控制页
	set_column(column);    //控制列
	for(i=0;i<16;i++){
        //控制16列的数据输出
		write_LCD_data(datacode); 
	}
}

/**************************************************************/
//初始化屏幕显示
void init_sys()
{
   	
	clear_screen(0); //清屏
	display(1,3,2*16,huan);
	display(1,3,3*16,ying);
	display(2,3,0*16,guang);
	display(2,3,1*16,lin);
	
	while(1){
   
		if(key_press){
    //有按键按下
			if(key == 0x77){
    //按下确认键
				key_press = 0;
				break;
			}
		}
	
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值