采用51单片机设计门禁系统,4X4键盘用户输入密码,错误蜂鸣器叫一声,正确LED闪烁,12864作为用户界面,初始显示“欢迎光临”,正确与错误时12864有相应的提示。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define _nop {} //空操作
- #define PAGEADD 0xb8 //页地址起始
- #define TIERADD 0x40 //行地址起始
- #define DIS_STARADD 0xc0 //开始命令
- uchar row,column,c;
-
- sbit CS2 = P3 ^ 3;
- sbit CS1 = P3 ^ 4;
- sbit E = P3 ^ 5; //定义使能端
- sbit RW = P3 ^ 6;
- sbit DI = P3 ^ 7;
-
- sbit INT = P3 ^ 2; //外部中断0引脚
- sbit buzzer = P3 ^ 0;
- sbit P3_1 = P3 ^ 1;
- sbit LED = P3 ^ 1;
-
- uchar flog = 0;
- uchar flog1 = 0;
- //键值数组
- uchar cc[] = {0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};
- /****************************
- 汉字显示
- *****************************/
- uchar code table2[] = { //加code在ROM
- //-- 密 --
- 0x10,0x4C,0x24,0x04,0xF4,0x84,0x4D,0x56,0x24,0x24,0x14,0x84,0x24,0x54,0x0C,0x00,//16字节
- 0x00,0x01,0xFD,0x41,0x40,0x41,0x41,0x7F,0x41,0x41,0x41,0x41,0xFC,0x00,0x00,0x00,
- //-- 码 --
- 0x02,0x82,0xF2,0x4E,0x43,0xE2,0x42,0xFA,0x02,0x02,0x02,0xFF,0x02,0x80,0x00,0x00,
- 0x01,0x00,0x7F,0x20,0x20,0x7F,0x08,0x09,0x09,0x09,0x0D,0x49,0x81,0x7F,0x01,0x00,
- //-- 正 --
- 0x00,0x02,0x02,0xC2,0x02,0x02,0x02,0xFE,0x82,0x82,0x82,0xC2,0x83,0x02,0x00,0x00,
- 0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x60,0x40,0x00,
- //-- 确 --
- 0x04,0x84,0xE4,0x9C,0x84,0xC6,0x24,0xF0,0x28,0x27,0xF4,0x2C,0x24,0xF0,0x20,0x00,
- 0x01,0x00,0x7F,0x20,0x20,0xBF,0x40,0x3F,0x09,0x09,0x7F,0x09,0x89,0xFF,0x00,0x00, //半个屏
- //-- 欢 --
- 0x04, 0x34, 0xC4, 0x04, 0xC4, 0x3C, 0x20, 0x10, 0x0F, 0xE8, 0x08, 0x08, 0x28, 0x18, 0x00, 0x00,
- 0x10, 0x08, 0x06, 0x01, 0x82, 0x8C, 0x40, 0x30, 0x0C, 0x03, 0x0C, 0x10, 0x60, 0xC0, 0x40, 0x00,
- //-- 迎 --
- 0x40, 0x42, 0x44, 0xC8, 0x00, 0xFC, 0x04, 0x02, 0x82, 0xFC, 0x04, 0x04, 0x04, 0xFE, 0x04, 0x00,
- 0x00, 0x40, 0x20, 0x1F, 0x20, 0x47, 0x42, 0x41, 0x40, 0x7F, 0x40, 0x42, 0x44, 0x63, 0x20, 0x00,
- //-- 光 --
- 0x40, 0x40, 0x42, 0x44, 0x58, 0xC0, 0x40, 0x7F, 0x40, 0xC0, 0x50, 0x48, 0x46, 0x64, 0x40, 0x00,
- 0x00, 0x80, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00,
- //-- 临 --
- 0x00, 0xFC, 0x00, 0xFF, 0x40, 0x20, 0x10, 0x0C, 0x2B, 0x48, 0xC8, 0x08, 0x08, 0x8C, 0x08, 0x00,
- 0x00, 0x1F, 0x00, 0xFF, 0x00, 0xFF, 0x41, 0x41, 0x41, 0x7F, 0x41, 0x41, 0x41, 0xFF, 0x01, 0x00,
- //-- 密 --
- 0x10, 0x4C, 0x24, 0x04, 0xF4, 0x84, 0x4D, 0x56, 0x24, 0x24, 0x14, 0x84, 0x24, 0x54, 0x0C, 0x00,
- 0x00, 0x01, 0xFD, 0x41, 0x40, 0x41, 0x41, 0x7F, 0x41, 0x41, 0x41, 0x41, 0xFC, 0x00, 0x00, 0x00,
- //-- 码 --
- 0x02, 0x82, 0xF2, 0x4E, 0x43, 0xE2, 0x42, 0xFA, 0x02, 0x02, 0x02, 0xFF, 0x02, 0x80, 0x00, 0x00,
- 0x01, 0x00, 0x7F, 0x20, 0x20, 0x7F, 0x08, 0x09, 0x09, 0x09, 0x0D, 0x49, 0x81, 0x7F, 0x01, 0x00,
- //-- 错 --
- 0x80, 0x40, 0x70, 0xCF, 0x48, 0x48, 0x48, 0x48, 0x7F, 0x48, 0x48, 0x7F, 0xC8, 0x68, 0x40, 0x00,
- 0x00, 0x02, 0x02, 0x7F, 0x22, 0x12, 0x00, 0xFF, 0x49, 0x49, 0x49, 0x49, 0xFF, 0x01, 0x00, 0x00,
- //-- 误 --
- 0x40, 0x42, 0xC4, 0x0C, 0x00, 0x40, 0x5E, 0x52, 0x52, 0xD2, 0x52, 0x52, 0x5F, 0x42, 0x00, 0x00,
- 0x00, 0x00, 0x7F, 0x20, 0x12, 0x82, 0x42, 0x22, 0x1A, 0x07, 0x1A, 0x22, 0x42, 0xC3, 0x42, 0x00,
- };
- //延迟函数
- void Delay_nms(uchar n)
- {
- uchar a;
- for (; n>0; n--)
- for (a = 0; a<100; a++);
- }
- //检查状态
- void LCD_Busy()
- {
- uchar busy;
- E = 0; //RW=1,E信号下降沿锁存DB7~DB0;RW=1,E=1,DDRAM数据读到DB7~DB0
- DI = 0; //DB7~DB0为指令数据
- RW = 1;
- while (1)
- {
- E = 1; //DDRAM数据读到DB7~DB0
- _nop;
- _nop;
- busy = P2;//读状态标志寄存器
- _nop;
- E = 0; // 下降沿锁存DB7~DB0
- if ((busy & 0x90) == 0)//检测BF和RST(复位重启)位,两者都为零时表示可以进行写入
- break;
- }
- }
- //左屏输入指令
- void WRCommand_L(uchar command)
- {
- CS1 = 1;
- CS2 = 0;
- LCD_Busy(); //检查状态
- DI = 0; //DB7~DB0为指令数据
- _nop;
- RW = 0;
- _nop;
- E = 1;
- _nop;
- P2 = command;
- _nop;
- E = 0; //RW=0,E下降沿数据写到DB7~DB0
- _nop;
- }
- //右屏输入指令
- void WRCommand_R(uchar command)
- {
- CS1 = 0;
- CS2 = 1;
- LCD_Busy();
- DI = 0;//指令
- _nop;
- RW = 0; //写
- _nop;
- E = 1;
- _nop;
- P2 = command;
- _nop;
- E = 0;
- _nop;
- }
- //左屏输入数据 (写一个字节的显示数据)
- void WRdata_L(uchar ucdata)
- {
- CS1 = 1;
- CS2 =0;
- LCD_Busy();
- DI = 1; //DB7~DB0为显示数据
- _nop;
- RW = 0;
- _nop;
- E = 1;
- _nop;
- P2 = ucdata;
- _nop;
- E = 0;
- _nop;
- }
- //右屏输入数据
- void WRdata_R(uchar ucdata)
- {
- CS1 =0;
- CS2 = 1;
- LCD_Busy();
- DI =1;
- _nop;
- RW = 0;
- _nop;
- E = 1;
- _nop;
- P2 = ucdata;
- _nop;
- E = 0;
- _nop;
- }
- //左屏显示
- //字符为16*16显示,分为两部分写入32字节。前16个字节写入第一页(16*8) 后16个字节写入第二页(16*8)
- void C_display_L(uchar C_Pagenum, uchar C_Tiernum, uchar C_Temp) //C_Pagenum:页,C_Tiernum:行char C_Temp:第几个字符
- {
- uchar k;
- C_Pagenum = PAGEADD | C_Pagenum; //首页地址为 0xb8
- C_Tiernum = TIERADD | C_Tiernum; //首行地址为 0x40
- WRCommand_L(C_Pagenum); //左屏输入
- WRCommand_L(C_Tiernum);
- for (k = 0; k<16; k++)
- {
- WRdata_L(table2[C_Temp * 32 + k]); //左屏输入数据
- };
- C_Pagenum = C_Pagenum + 1; //下页
- WRCommand_L(C_Pagenum);
- WRCommand_L(C_Tiernum);
- for (k = 0; k<16; k++)
- {
- WRdata_L(table2[C_Temp * 32 + k + 16]);
- }
- }
- //右屏显示
- void C_display_R(uchar C_Pagenum, uchar C_Tiernum, uchar C_Temp)
- {
- uchar k;
- C_Pagenum = PAGEADD | C_Pagenum;
- C_Tiernum = TIERADD | C_Tiernum;
- WRCommand_R(C_Pagenum);
- WRCommand_R(C_Tiernum);
- for (k = 0; k<16; k++)
- {
- WRdata_R(table2[C_Temp * 32 + k]);
- }
- C_Pagenum = C_Pagenum + 1;
- WRCommand_R(C_Pagenum);
- WRCommand_R(C_Tiernum);
- for (k = 0; k<16; k++)
- {
- WRdata_R(table2[C_Temp * 32 + k + 16]);
- }
- }
- //清除所有显示寄存器
- void CLR_DisplayRAM()
- {
- uchar C_page, i, k;
- for (i = 0; i<8; i++)
- {
- C_page = PAGEADD | i;//清除起始页为0
- WRCommand_L(C_page); //清除起始页写入
- WRCommand_L(TIERADD); //清除起始行地址写入
- WRCommand_R(C_page);
- WRCommand_R(TIERADD);
- for (k = 0; k<64; k++)
- {
- WRdata_L(0x00);
- WRdata_R(0x00); //lcm的ram自动加1,只允许循环64次
- }
- }
- }
- //LCD初始化
- void Init_LCD(void)
- {
- CLR_DisplayRAM();// 清除所有显示寄存器
- WRCommand_L(DIS_STARADD);
- WRCommand_R(DIS_STARADD);// 设置显示起始列地址0xc0
- WRCommand_L(0x3f);
- WRCommand_R(0x3f);
- }
- //延迟函数
- void delay()
- {
- uchar i;
- uchar j;
- for(i = 0;i < 100;i++)
- {
- for(j = 200;j>0;j--);
- }
- }
- //键盘扫描
- char keyscan()
- {
- uchar cord_h,cord_l;
- uchar key=0;
- P1=0xf0;
- if(P1!=0xf0)
- {
- delay(); //消抖动
- if(P1!=0xf0)
- {
- cord_l=P1;
- P1=0x0f;
- cord_h=P1;
- key=cord_l|cord_h; //键值
- }
- }
- P1=0xf0;
- return key;
- }
- //密码输入成功
- void Pass()
- {
- uchar a = 0, pagenum = 0,i =0;
- LED = 1;
- Init_LCD(); //lcd初始化
- //中文显示“密码正确”
- pagenum = 0;//从第一排开始显示
- for (a = 0; a<4; a++)
- {
- C_display_L(pagenum, a * 16, a);
- }
-
- //中文显示“欢迎光临”
- pagenum = 2;//从第二排开始显示
- for (a = 0; a<4; a++)
- {
- C_display_R(pagenum, a * 16, a + 4);
- }
- while(1);
- }
- //按键中断(int0)
- void IntoPro() interrupt 0
- {
- uchar a = 0,pagenum = 0,i = 0,key;
- flog1++; //记录按键的次数
- key=keyscan(); //扫描键盘是否按下
-
- CLR_DisplayRAM(); //清屏
-
- if(key == cc[0]) //判断第一位密码是否正确,正确flog++
- {
- flog=flog+1;} //P3_1 = 0;
- if(key == cc[1])
- {if(flog % 3 == 1)
- flog=flog+1;} //P3_1 = 1;
- if(key== cc[2])
- {if(flog % 3 == 2)
- flog=flog+1;} //P3_1 = 0;
- if(key == cc[3])
- {if(flog % 3 == 0)
- {
- P3_1 = 1;Pass(); //显示密码正确信 led灯亮
- }
- }
- if(flog1 % 4 == 0) //密码错误
- {
- buzzer = 1; //蜂鸣器响
- delay();
- buzzer = 0;
- Init_LCD(); //lcd初始化
- pagenum = 0;//从第一排开始显示
- //显示按键错误
- for (a = 0; a<4; a++)
- {
- C_display_L(pagenum, a * 16, a + 8);
- }
- }
- }
- void main()
- {
- LED = 0;
- buzzer = 0;//蜂鸣器关闭
- P1 = 0xf0;
-
- EA = 1; //中断总允许
- EX0 = 1; //外部中断0
- IT0 = 1; //下降沿触发
-
- while(1);
-
- }
复制代码
所有资料51hei提供下载:
实验七.rar
(99.17 KB, 下载次数: 223)
|