4X4矩阵式密码锁(西电微机原理课设第八题)

一、实现功能

(1)具有开锁、修改用户密码、进入管理员权限的基本功能。

(2)输入密码过程中可短暂查看已输入密码以确保输入;

         对于输入密码部分超过3次密码错误,锁定键盘5秒,系统报警,5秒后解除锁定;

         对于修改密码和管理员密码部分输入一次错误即锁定键盘5秒,系统报警,5秒后接触。

(3)通过LCD字符液晶和LED指示灯(红,绿,黄)实时显示相关信息。

(4)用户密码为6位数字,显示采用“*”号表示。

二、操作内容

(1)初始密码为“123456”;管理员初始密码为“12345678”;

(2)所有输入以键盘值“0X0a”(即‘#’键)开始和结束;

三、键盘布局

4X4矩阵密码锁

0(0x00)

    0

1(0x01)

    1

2(0x02)

2

3(0x03)

3

4(0x04)

4

5(0x05)

5

6(0x06)

6

7(0x07)

7

8(0x08)

8

9(0x09)

9

A(0x0a)

#

B(0x0b)

Modify

C(0x0c)

Admin

D(0x0d)

显示输入

E(0x0e)

Shift

F(0x0f)

Delete

四、具体代码

// 12864j液晶显示器
//后三位分别代表:CS1/2(左右半屏片选,高左低右) RS(指令/数据传送,高数低指) RW(读写,高读低写)
#define WR_COM_AD_L		0x264				//写左半屏指令地址  100
#define WR_COM_AD_R		0x260				//写右半屏指令地址  000
#define WR_DATA_AD_L 	0x266				//写左半屏数据地址	110
#define WR_DATA_AD_R	0x262				//写右半屏数据地址  010
#define RD_BUSY_AD 		0x261				//查忙地址          001
#define RD_DATA_AD 		0x263				//读数据地址        011
// DB7-DB0初始化设置内容
#define X 			0xB8					//起始显示行基址    10111000,行号为0-7 (10111xxx)
#define Y			0x40					//起始显示列基址    01000000,列号为0-63(01xxxxxx)
#define FirstLine	0xC0					//起始显示行        11000000

//输出字节到硬件端口中
extern void outportb(unsigned int, char);
//从指定硬件端口读入一个字节
extern char inportb(unsigned int);			


//ZIMO221软件提取16x16汉字,符号点阵图。1表示为输出黑色像素的点,0则表示不显示的点
//--  文字: 密  --
unsigned char Line1_1[] = {		
		0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
       	0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00};
//--  文字: 码  --
unsigned char Line1_2[] = {
		0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
        0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00};
//--  文字: 错  --
unsigned char Line1_3[] = {
		0x40,0x30,0xEF,0x24,0x64,0x48,0x48,0x7F,0x48,0x48,0x48,0x7F,0x48,0x48,0x40,0x00,
       	 0x01,0x01,0x7F,0x21,0x11,0x00,0xFF,0x49,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00};
//--  文字: 误  --
unsigned char Line1_4[] = {
		0x40,0x42,0xCC,0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,
        0x00,0x00,0x7F,0x20,0x94,0x84,0x44,0x24,0x14,0x0F,0x14,0x24,0x44,0x84,0x84,0x00};
        
//--  文字: 正  --
unsigned char Line1_5[] = {
		0x00,0x02,0x02,0xC2,0x02,0x02,0x02,0xFE,0x82,0x82,0x82,0x82,0x82,0x02,0x00,0x00,
       	0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00};
//--  文字: 确  --
unsigned char Line1_6[] = {
		0x04,0x84,0xE4,0x5C,0x44,0xC4,0x20,0x10,0xE8,0x27,0x24,0xE4,0x34,0x2C,0xE0,0x00,
		0x02,0x01,0x7F,0x10,0x10,0x3F,0x80,0x60,0x1F,0x09,0x09,0x3F,0x49,0x89,0x7F,0x00};

//--  文字: 系  --
unsigned char Line2_1[] = {
		0x00,0x00,0x22,0x32,0x2A,0xA6,0xA2,0x62,0x21,0x11,0x09,0x81,0x01,0x00,0x00,0x00,
		0x00,0x42,0x22,0x13,0x0B,0x42,0x82,0x7E,0x02,0x02,0x0A,0x12,0x23,0x46,0x00,0x00};

//--  文字: 统  --
unsigned char Line2_2[] = {
		0x20,0x30,0xAC,0x63,0x30,0x00,0x88,0xC8,0xA8,0x99,0x8E,0x88,0xA8,0xC8,0x88,0x00,
		0x22,0x67,0x22,0x12,0x12,0x80,0x40,0x30,0x0F,0x00,0x00,0x3F,0x40,0x40,0x71,0x00};

//--  文字: 锁  --
unsigned char Line2_3[] = {
		0x20,0x10,0x2C,0xE7,0x24,0x24,0x00,0xE2,0x2C,0x20,0xBF,0x20,0x28,0xE6,0x00,0x00,
		0x01,0x01,0x01,0x7F,0x21,0x11,0x80,0x4F,0x20,0x10,0x0F,0x10,0x20,0x4F,0x80,0x00};

//--  文字: 定  --
unsigned char Line2_4[] = {
		0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00,
		0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00};

//--  文字: 开  --
unsigned char Line3_1[] = {
		0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00,
		0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00};

//--  文字: 放  --
unsigned char Line3_2[] = {
		0x08,0x08,0xF9,0x4A,0x48,0xC8,0x48,0x20,0xD8,0x17,0x10,0x10,0xF0,0x10,0x10,0x00,
		0x40,0x30,0x0F,0x20,0x40,0x3F,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00};

//--  文字: 输  --
unsigned char Line3_3[] = {
		0x88,0x68,0x1F,0xC8,0x08,0x10,0xC8,0x54,0x52,0xD1,0x12,0x94,0x08,0xD0,0x10,0x00,
		0x09,0x19,0x09,0xFF,0x05,0x00,0xFF,0x12,0x92,0xFF,0x00,0x5F,0x80,0x7F,0x00,0x00};

//--  文字: 入  --
unsigned char Line3_4[] = {
		0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00};

//--  文字: 修  --
unsigned char Line4_1[] = {
		0x40,0x20,0xF8,0x07,0xF0,0xA0,0x90,0x4C,0x57,0x24,0xA4,0x54,0x4C,0x80,0x80,0x00,
		0x00,0x00,0xFF,0x00,0x1F,0x80,0x92,0x52,0x49,0x29,0x24,0x12,0x08,0x00,0x00,0x00};

//--  文字: 改  --
unsigned char Line4_2[] = {
		0x04,0x84,0x84,0x84,0x84,0xFC,0x40,0x30,0xCC,0x0B,0x08,0x08,0xF8,0x08,0x08,0x00,
		0x00,0x7F,0x20,0x10,0x10,0x08,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00};

//--  文字: 成  --
unsigned char Line4_3[] = {
		0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x08,0x00,
		0x80,0x60,0x1F,0x00,0x10,0x20,0x1F,0x80,0x40,0x21,0x16,0x18,0x26,0x41,0xF8,0x00};

//--  文字: 功  --
unsigned char Line4_4[] = {
		0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00,
		0x10,0x30,0x10,0x1F,0x08,0x88,0x48,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00};

//--  符号:*   --
unsigned char Line5_1[] = {
		0x00,0x00,0x84,0x88,0x90,0xA0,0xC0,0xFC,0xC0,0xA0,0x90,0x88,0x84,0x80,0x00,0x00,
        0x00,0x00,0x10,0x08,0x04,0x02,0x01,0x1F,0x01,0x02,0x04,0x08,0x10,0x00,0x00,0x00};
        	
//--  文字:输   --
unsigned char Line6_1[] = {
		0x88,0x68,0x1F,0xC8,0x08,0x10,0xC8,0x54,0x52,0xD1,0x12,0x94,0x08,0xD0,0x10,0x00,
		0x09,0x19,0x09,0xFF,0x05,0x00,0xFF,0x12,0x92,0xFF,0x00,0x5F,0x80,0x7F,0x00,0x00};

//--  文字:入   --
unsigned char Line6_2[] = {
		0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00};

//--  文字:按   --
unsigned char Line6_3[] = {
		0x10,0x10,0x10,0xFF,0x90,0x20,0x98,0x88,0x88,0xE9,0x8E,0x88,0x88,0xA8,0x98,0x00,
		0x02,0x42,0x81,0x7F,0x00,0x00,0x80,0x84,0x4B,0x28,0x10,0x28,0x47,0x80,0x00,0x00};

//--  文字:键   --
unsigned char Line6_4[] = {
		0x40,0x30,0xEF,0x24,0x24,0x80,0xE4,0x9C,0x10,0x54,0x54,0xFF,0x54,0x7C,0x10,0x00,
		0x01,0x01,0x7F,0x21,0x51,0x26,0x18,0x27,0x44,0x45,0x45,0x5F,0x45,0x45,0x44,0x00};
		
//--  文字:再   --
unsigned char Line7_1[] = {
		0x02,0x02,0xF2,0x92,0x92,0x92,0x92,0xFE,0x92,0x92,0x92,0x92,0xF2,0x02,0x02,0x00,
		0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x44,0x84,0x7F,0x04,0x04,0x00};

//--  文字:次   --
unsigned char Line7_2[] = {
		0x00,0x02,0x0C,0x80,0x60,0x80,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00,
		0x02,0x02,0x7E,0x01,0x80,0x40,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00};

//--  文字:新   --		
unsigned char Line8_1[] ={
		0x40,0x44,0x54,0x65,0xC6,0x64,0x54,0x44,0x00,0xFC,0x44,0x44,0xC4,0x42,0x40,0x00,
		0x20,0x12,0x4A,0x82,0x7F,0x02,0x0A,0x92,0x60,0x1F,0x00,0x00,0xFF,0x00,0x00,0x00};
//--  文字:旧   --
unsigned char Line8_2[] ={
		0x00,0x00,0xFF,0x00,0x00,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x00,
		0x00,0x00,0xFF,0x00,0x00,0x00,0x7F,0x20,0x20,0x20,0x20,0x20,0x20,0x7F,0x00,0x00};
//--  文字:的   --
unsigned char Line8_3[] ={
		0x00,0xF8,0x0C,0x0B,0x08,0x08,0xF8,0x40,0x30,0x8F,0x08,0x08,0x08,0xF8,0x00,0x00,
		0x00,0x7F,0x21,0x21,0x21,0x21,0x7F,0x00,0x00,0x00,0x43,0x80,0x40,0x3F,0x00,0x00};
//--  文字:重   --
unsigned char Line9_1[] = {
		0x10,0x10,0x14,0xD4,0x54,0x54,0x54,0xFC,0x52,0x52,0x52,0xD3,0x12,0x10,0x10,0x00,
		0x40,0x40,0x50,0x57,0x55,0x55,0x55,0x7F,0x55,0x55,0x55,0x57,0x50,0x40,0x40,0x00};
//--  文字:置   --	
unsigned char Line9_2[] = {
		0x00,0x17,0x15,0xD5,0x55,0x57,0x55,0x7D,0x55,0x57,0x55,0xD5,0x15,0x17,0x00,0x00,
		0x40,0x40,0x40,0x7F,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x7F,0x40,0x40,0x40,0x00};
//--  文字:0   --	
unsigned char Line6_5[] = {
		0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00};
//--  文字:1   --	
unsigned char Line6_6[] = {
		0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00};
//--  文字:2   --	
unsigned char Line6_7[] = {
		0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00};
//--  文字:3   --	
unsigned char Line6_8[] = {
		0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00};
//--  文字:4   --	
unsigned char Line6_9[] = {
		0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00};
//--  文字:5   --	
unsigned char Line7_3[] = {
		0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00};
//--  文字:6   --	
unsigned char Line7_4[] = {
		0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00};
//--  文字:7   --	
unsigned char Line7_5[] = {
		0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00};
//--  文字:8   --	
unsigned char Line7_6[] = {
		0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00};
//--  文字:9   --	
unsigned char Line7_7[] = {
		0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00};
//--  文字:a   --	
unsigned char Line7_8[] = {
		0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20};
//--  文字:b   --	
unsigned char Line7_9[] = {
		0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00};
//--  文字:c   --	
unsigned char Line9_4[] = {
		0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00};
//--  文字:d   --	
unsigned char Line8_4[] = {
		0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20};
//--  文字:e   --	
unsigned char Line8_5[] = {
		0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00};
//--  文字:f   --	
unsigned char Line8_6[] = {
		0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00};
//--  文字:g   --	
unsigned char Line8_7[] = {
		0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00};
//--  文字:h   --	
unsigned char Line8_8[] = {
		0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20};
//--  文字:i   --	
unsigned char Line8_9[] = {
		0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00};
//--  文字:j   --	
unsigned char Line9_3[] = {
		0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00};


		
//***************************************
//基本控制		
//***************************************					
//写左半屏控制指令,需要先写指令才能写数据
void WRComL(unsigned char _data)
{
	outportb(WR_COM_AD_L, _data);
	while (inportb(RD_BUSY_AD) & 0x80)	//检查液晶显示是否处于忙状态 BUSY位为DB7, 所以只需要 & 10000000B 来判断是否BUSY,下同
	{;}
}

//写右半屏控制指令,需要先写指令才能写数据
void WRComR(unsigned char _data)
{
	outportb(WR_COM_AD_R, _data);
	while (inportb(RD_BUSY_AD) & 0x80)	//检查液晶显示是否处于忙状态
	{;}
}

//写左半屏数据
void WRDataL(unsigned char _data)
{
	outportb(WR_DATA_AD_L, _data);
	while (inportb(RD_BUSY_AD) & 0x80)	//检查液晶显示是否处于忙状态
	{;}
}

//写右半屏数据
void WRDataR(unsigned char _data)
{
	outportb(WR_DATA_AD_R, _data);
	while (inportb(RD_BUSY_AD) & 0x80)	//检查液晶显示是否处于忙状态
	{;}
}

//显示左半屏数据,count-显示数据个数
void DisplayL(unsigned char *pt, char count)
{
	while (count--)
	{
		WRDataL(*pt++);			//写左半屏数据
	}
}

//显示右半屏数据,count-显示数据个数
void DisplayR(unsigned char * pt, char count)
{
	while (count--)
	{
		WRDataR(*pt++);			//写右半屏数据
	}
}

//设置左半屏起始显示行列地址,x-X起始行序数(0-7),y-Y起始列序数(0-63)
void SETXYL(unsigned char x, unsigned char y)
{
	WRComL(x+X);				//行地址=行序数+行基址
	WRComL(y+Y);				//列地址=列序数+列基址
}

//设置右半屏起始显示行列地址,x:X起始行序数(0-7),y:Y起始列序数(0-63)
void SETXYR(unsigned char x, unsigned char y)
{
	WRComR(x+X);				//行地址=行序数+行基址
	WRComR(y+Y);				//列地址=列序数+列基址
}

//***************************************
//显示图形		
//***************************************
//显示左半屏一行图形,A-X起始行序数(0-7),B-Y起始列地址序数(0-63)
void LineDisL(unsigned char x, unsigned char y, unsigned char * pt)
{
	SETXYL(x,y);				//设置起始显示行列
	DisplayL(pt, 64);			//显示数据
}

//显示右半屏一行图形,A-X起始行地址序数(0-7),B-Y起始列地址序数(0-63)
void LineDisR(unsigned char x, unsigned char y, unsigned char * pt)
{
	SETXYR(x,y);				//设置起始显示行列
	DisplayR(pt, 64);			//显示数据
}


//显示字体,显示一个数据要占用X行两行位置

//右半屏显示一个字节:x-起始显示行序数X(0-7);y-起始显示列序数Y(0-63);pt-待显示数据的首地址,显示类型为ASCII码范围,总计16x8
void ByteDisR(unsigned char x, unsigned char y,unsigned char * pt)
{
	SETXYR(x,y);			//设置起始显示行列地址
	DisplayR(pt, 8);	    //显示上半行数据,8x8
	SETXYR(x+1,y);			//设置起始显示行列地址
	DisplayR(pt+8, 8);		//显示下半行数据,8x8
}

//右半屏显示一个字:x-起始显示行序数X(0-7);y-起始显示列序数Y(0-63);pt-待显示数据的首地址,显示类型为GBK或Unicode,总计16x16
void WordDisR(unsigned char x, unsigned char y,unsigned char * pt)
{
	SETXYR(x,y);			//设置起始显示行列地址
	DisplayR(pt, 16);		//显示上半行数据 8x16bit
	SETXYR(x+1,y);			//设置起始显示行列地址
	DisplayR(pt+16, 16);	//显示下半行数据 8x16bit
}

//左半屏显示一个字节:x-起始显示行序数X(0-7);y-起始显示列序数Y(0-63);pt-显示字数据首地址
void ByteDisL(unsigned char x, unsigned char y,unsigned char * pt)
{
	SETXYL(x,y);			//设置起始显示行列地址
	DisplayL(pt, 8);		//显示上半行数据
	SETXYL(x+1,y);			//设置起始显示行列地址
	DisplayL(pt+8, 8);		//显示下半行数据
}

//左半屏显示一个字:x-起始显示行序数X(0-7);y-起始显示列序数Y(0-63);pt-显示字数据首地址
void WordDisL(unsigned char x, unsigned char y,unsigned char * pt)
{
	SETXYL(x,y);			//设置起始显示行列地址
	DisplayL(pt, 16);		//显示上半行数据
	SETXYL(x+1,y);			//设置起始显示行列地址
	DisplayL(pt+16, 16);	//显示下半行数据
}
//清屏
void LCDClear()
{
//清左半屏
	unsigned char x,y;
	char j;
	x = 0;						//起始行,第0行
	y = 0;						//起始列,第0列
	for (x = 0; x < 8; x++)		//共8行
	{
		SETXYL(x,y);			//设置起始显示行列地址
		j = 64;
		while (j--)
			WRDataL(0);
	}
//清右半屏
	x = 0;						//起始行,第0行
	y = 0;						//起始列,第0列
	for (x = 0; x < 8; x++)		//共8行
	{
		SETXYR(x,y);			//设置起始显示行列地址
		j = 64;
		while (j--)
			WRDataR(0);
	}
}

//液晶初始化	
void LCD_INIT()
{
	WRComL(0x3e);			//初始化左半屏,关显示
	WRComL(FirstLine);		//设置起始显示行,第0行
	WRComR(0x3e);			//初始化右半屏,关显示
	WRComR(FirstLine);		//设置起始显示行,第0行
	LCDClear();				//清屏
	WRComL(0x3f);			//开显示
	WRComR(0x3f);			//开显示
}

//第2行显示"密码错误"
void showWrongPwd()
{
	WordDisL(2,32,Line1_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line1_2);
	WordDisR(2,0,Line1_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line1_4);
}

//第2行显示"密码正确"
void showCorrectPwd()
{
	WordDisL(2,32,Line1_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line1_2);
	WordDisR(2,0,Line1_5);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line1_6);
}

//第2行显示"系统锁定"
void showSystemLocked()
{
	WordDisL(2,32,Line2_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line2_2);
	WordDisR(2,0,Line2_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line2_4);
}

//第2行显示"开放输入"
void showEnableInput()
{
	WordDisL(2,32,Line3_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line3_2);
	WordDisR(2,0,Line3_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line3_4);
}

//第2行显示"修改成功"
void showModifiedSuccess()
{
	WordDisL(2,32,Line4_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line4_2);
	WordDisR(2,0,Line4_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line4_4);
}

//第2行显示"输入按键"
void showInputButton()
{
	WordDisL(2,32,Line6_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line6_2);
	WordDisR(2,0,Line6_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line6_4);
}

//第2行显示"输入密码"
void showEnterPwd()
{
	WordDisL(2,32,Line3_3);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line3_4);
	WordDisR(2,0,Line1_1);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line1_2);
}

//第2行显示"再次输入"
void showEnterAgain()
{
	WordDisL(2,32,Line7_1);		//第2行,第32列,左半屏,显示一个字子程序
	WordDisL(2,48,Line7_2);
	WordDisR(2,0,Line3_3);		//右半屏,显示一个字子程序
	WordDisR(2,16,Line3_4);
}

//延时程序
void delayTime()
{
	unsigned char i;
	unsigned int j;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 0xffff; j++)
		{;}
	}
}


//显示一个*
void show1Star()
{
	WordDisL(2,16,Line5_1);
}

//显示两个*
void show2Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
}

//显示三个*
void show3Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
}

//显示四个*
void show4Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
	WordDisR(2,0,Line5_1);
}

//显示五个*
void show5Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
	WordDisR(2,0,Line5_1);
	WordDisR(2,16,Line5_1);
}

//显示六个*
void show6Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
	WordDisR(2,0,Line5_1);
	WordDisR(2,16,Line5_1);
	WordDisR(2,32,Line5_1);
}

//显示七个*
void show7Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
	WordDisR(2,0,Line5_1);
	WordDisR(2,16,Line5_1);
	WordDisR(2,32,Line5_1);
	WordDisL(4,16,Line5_1);
}

//显示八个*
void show8Stars()
{
	WordDisL(2,16,Line5_1);
	WordDisL(2,32,Line5_1);
	WordDisL(2,48,Line5_1);
	WordDisR(2,0,Line5_1);
	WordDisR(2,16,Line5_1);
	WordDisR(2,32,Line5_1);
	WordDisL(4,16,Line5_1);
	WordDisL(4,32,Line5_1);
}

//显示"旧的密码"
void showUsedPwd()
{
	WordDisL(2,32,Line8_2);
	WordDisL(2,48,Line8_3);
	WordDisR(2,0,Line1_1);
	WordDisR(2,16,Line1_2);
}


//显示"新的密码"
void showNewPwd()
{
	WordDisL(2,32,Line8_1);
	WordDisL(2,48,Line8_3);
	WordDisR(2,0,Line1_1);
	WordDisR(2,16,Line1_2);
}


//显示"重置成功"
void showResetSuccess()
{		
	WordDisL(2,32,Line9_1);
	WordDisL(2,48,Line9_2);
	WordDisR(2,0,Line4_3);
	WordDisR(2,16,Line4_4);
}


//显示"重新输入"
void showReEnter()
{
	WordDisL(2,32,Line9_1);
	WordDisL(2,48,Line8_1);
	WordDisR(2,0,Line3_3);
	WordDisR(2,16,Line3_4);
}	


//#########################################################################################
// 8255
#define PA_Addr		0x270   // A口地址270,控制LED
#define PB_Addr		0x271   // B口地址271,键盘列扫描信号
#define PC_Addr		0x272   // C口地址272,读键盘KL1 KL2信号
#define	CON_Addr	0x273   // 控制字地址273

#define u8	unsigned char   // 自定义数据类型u8,用于表示按键的键值
#define u16	unsigned int    // 自定义数据类型u16,用于表示整形数据

extern char inportb(unsigned int);				// 读8255函数
extern void outportb(unsigned int, char);		// 写8255函数
unsigned char * address(u8 buf);
u16 present(u8 * buf,u16 i);

u8 pwd[6] = {'1','2','3','4','5','6'}; 			// 初始密码,定义为字符数组
u16 adminPassword = 12345678; 					// 管理员密码,定义为整型
u8 tt;  										// 用于main函数,存放用户按下的键的键值


// 延时子程序
void delay(u16 ms) 		 // 1000
{
	u16 i;
	while(ms--)    		 // 1000
	{
		i = 100;
		do
		{;}while(--i);   // 100
	}  				     // 100000
}

// 判断是否有键被按下
u8 AllKey()
{
	u8 i;						   // i是标志,i=0表示没有键被按下,否则表示有键被按下
	outportb(PB_Addr, 0x0);		   // B口送出信号,同时检测所有按键
	i = (~inportb(PC_Addr) & 0x3); // 读C口数据,若PC1(KL2) PC0(KL1)为1 1,说明没有键被按下,返回0,一旦有某个键被按下,则返回非0
	return i;
}

// 读取键盘输入
u8 key()
{
	u8 i, j, keyResult;
	u8 bNoKey = 1;				// 初始化没有键被按下为1
	while(bNoKey)
	{
		if (AllKey() == 0)		// 判断是否有键被按下
		{
			continue;           // 若当前未按下任何键,则直接进入下一循环,重复监听
		}
        // 下面处理已经有键被按下的情况
		i = 0xfe;				// i是B口送出的列扫描信号,初值为1111 1110,表示从第一列开始扫描
		keyResult = 0;			// 初始化键值为0
		do
		{
			outportb(PB_Addr, i);		// 扫描某列
			j = ~inportb(PC_Addr);		// 读取KL2 KL1的值
			if (j & 3)					// 若当前扫描的列中有键按下(KL2 KL1不为全1)
			{
				bNoKey = 0;				// bNoKey标志置0
				if (j & 2)				// 若次行有键闭合(KL2=0 KL1=1)
					keyResult += 8;     // 键值+8
			}
			else						// 若当前扫描的列中没有键被按下
			{
				keyResult++;			// 键值+1
				i = ((i << 1) | 1);		// 让i左移一位,在下一轮循环时好扫描下一列
			}
		}while(bNoKey && (i != 0xff));  // 当bNoKey为0(已有键被按下)或者扫描完所有列时,退出循环
	}

	if (!bNoKey)
	{
		while(AllKey())		  // 判断刚才按下的键是否被释放,若未被释放,则一直陷入循环
		{   }
	}
	return keyResult;
}

// shift键获取字母
u8 shift()
{
	u8 currChar = key();
	while(currChar > 0x09) 		// 若按下的键值大于9,则不断要求用户重新输入
		currChar = key();
	return currChar + (u8)'a';  // 在'a'的ASCII码基础上进行0-9的偏移,得到不同字母('a'-'j')的ASCII码
}

// 绿灯亮10s
void greenl()
{
	outportb(PA_Addr, 0xfe);  // 绿灯1111 1110(参考硬件F4模块电路原理图)
	delay(10000);
}

// 红灯亮5s
void redl()
{
	outportb(PA_Addr, 0xfb);  // 红灯1111 1011
	delay(5000);
}

// 黄灯闪烁5s及蜂鸣器发出警报声
void yellowl()
{
	u8 i;
	for(i = 0; i < 10; i++)
	{
		outportb(PA_Addr, 0xfd);   // 黄灯1111 1101
		outportb(CON_Addr,0x0e);   // 写控制字0000 1110————C口位操作:PC7复位,蜂鸣器响
		delay(250);
		outportb(PA_Addr, 0xff);   // 黄灯熄灭
		outportb(CON_Addr,0x0f);   // 写控制字0000 1111————C口位操作:PC7置位,蜂鸣器停
		delay(250);
	}
}

// 全熄灭
void blackl()     
{
	outportb(PA_Addr, 0xff);  // 全灭 1111 1111
}


// -----------------------------------------下面是功能函数-----------------------------------------
// 输入密码并与原密码进行比较,如果正确则返回1,否则返回0
u16 checkPwd()
{
	u16 i;
	u8 buf[6];
	
	//	u16 inputPassword = 0;
	// 重复扫描6次键盘输入
	for(i = 0;i < 6;i ++)
	{
		buf[i] = key();
		if(buf[i] == 0x0f)    // 若按下了我们设定的微机键盘del键,则清屏后重新输入密码
		{
			i = -1;			  // 先置i=-1,以使continue之后i=0,可以继续按键盘6次
			LCD_INIT();       // 液晶初始化
			showReEnter();    // 显示"重新输入"汉字
			delayTime();      // 延时一段时间
			LCD_INIT();       // 液晶初始化
			continue;         // 进入下一循环
		}
		if(buf[i] == 0x0e)
			buf[i] = shift();	
		else
			buf[i] += (u8)'0';
		
		LCD_INIT();       // 清屏,液晶初始化
		if(i == 0)
			show1Star();  // 按下1个键,显示1个*
		else if(i == 1)
			show2Stars();  // 按下2个键,显示2个*
		else if(i == 2)
			show3Stars();  // 按下3个键,显示3个*
		else if(i == 3)
			show4Stars();  // 按下4个键,显示4个*
		else if(i == 4)
			show5Stars();  // 按下5个键,显示5个*
		else if(i == 5)
			show6Stars();  // 按下6个键,显示6个*
			
				i = present(buf,i);
	}
	
	while(1)
	{
        //依位比较输入密码和保存的密码,如果中间有一位不匹配,则返回0,完全匹配说明密码正确
		if(key() == 0x0a) { 
			for(i = 0; i < 6; i++)
			{
				if(buf[i] != pwd[i])
					return 0;
			}
			return 1;
		}	
	}	
}
//-------------------------------------------------------修改部分
//-------------------------------------------------------新增函数
unsigned char * address(u8 buf){
    unsigned char * mpt;
    switch(buf)
	         {
		         case 0x30:
			        mpt=Line6_5;
			        break;
		        case 0x31:
					mpt=Line6_6;
					break;
				case 0x32:
					mpt=Line6_7;
					break;
				case 0x33:
					mpt=Line6_8;
					break;
				case 0x34:
					mpt=Line6_9;
					break;
				case 0x35:
					mpt=Line7_3;
					break;
				case 0x36:
					mpt=Line7_4;
					break;
				case 0x37:
					mpt=Line7_5;
					break;
				case 0x38:
					mpt=Line7_6;
					break;
				case 0x39:
					mpt=Line7_7;
					break;
                                case 0x61:
					mpt=Line7_8;
					break;
                                case 0x62:
					mpt=Line7_9;
					break;
                                case 0x63:
					mpt=Line9_4;
					break;
                                case 0x64:
					mpt=Line8_4;
					break;
                                case 0x65:
					mpt=Line8_5;
					break;
                                case 0x66:
					mpt=Line8_6;
					break;
				case 0x67:
					mpt=Line8_7;
					break;
                                case 0x68:
					mpt=Line8_8;
					break;
                                case 0x69:
		 			mpt=Line8_9;
					break;
				case 0x6a:
					mpt=Line9_3;
					break;
			}
			return (unsigned char *)mpt;
}
u16 present(u8 * buf,u16 i){
	if(buf[i]==0x3d){
                LCD_INIT();
                if(i==1)
			        ByteDisL(2,20,address(buf[0]));
			    if(i==2){
				    ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
				}
			    
			    if(i==3){
			    	ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
			        ByteDisL(2,52,address(buf[2]));
				}
			    
			    if(i==4){
			    	ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
			        ByteDisL(2,52,address(buf[2]));
			        ByteDisR(2,4,address(buf[3]));
				}
			    
			    if(i==5){
			    	ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
			        ByteDisL(2,52,address(buf[2]));
			        ByteDisR(2,4,address(buf[3]));
			        ByteDisR(2,20,address(buf[4]));
				}
				 if(i==6){
			    	ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
			        ByteDisL(2,52,address(buf[2]));
			        ByteDisR(2,4,address(buf[3]));
			        ByteDisR(2,20,address(buf[4]));
			        ByteDisR(2,36,address(buf[5]));
				}
				 if(i==7){
			    	ByteDisL(2,20,address(buf[0]));
			        ByteDisL(2,36,address(buf[1]));
			        ByteDisL(2,52,address(buf[2]));
			        ByteDisR(2,4,address(buf[3]));
			        ByteDisR(2,20,address(buf[4]));
			        ByteDisR(2,36,address(buf[5]));
			        ByteDisL(4,20,address(buf[6]));
				}
				i--;
			    delayTime(20000);
			    LCD_INIT();
			    
		if(i == 0)
			show1Star();  // 按下1个键,显示1个*
		else if(i == 1)
			show2Stars();  // 按下2个键,显示2个*
		else if(i == 2)
			show3Stars();  // 按下3个键,显示3个*
		else if(i == 3)
			show4Stars();  // 按下4个键,显示4个*
		else if(i == 4)
			show5Stars();  // 按下5个键,显示5个*
		else if(i == 5)
			show6Stars(); 
			
           
	}
	return i;
}
//-------------------------------------------------------新增函数
// 更改密码_输入新密码
void changePwd()
{
	u16 i;
	u8 buf[6];
	//u16 inputPassword = 0;
	// 重复6次读取键盘输入
	for(i = 0;i < 6;i ++)
	{
		buf[i] = key();
		if(buf[i] == 0x0f)    // 若按下了我们设定的微机键盘del键,则清屏后重新输入密码
		{
			i = -1;			  // 先置i=-1,以使continue之后i=0,可以继续按键盘6次
			LCD_INIT();       // 液晶初始化
			showReEnter();     // 显示"重新输入"汉字
			delayTime();      // 延时一段时间
			LCD_INIT();       // 液晶初始化
			continue;         // 进入下一循环
		}
		if(buf[i] == 0x0e) //如果按下shift键
			buf[i] = shift();	//获取字母型变量,原先0-9的数字键现在变为a-j字母键
		else //如果未按下shift键
			buf[i] += (u8)'0'; //数字变量要转成unsigned char类型,即转成ASCII码型数字,方便显示
		LCD_INIT();
        switch(i)
		{
			case 0:
				show1Star();
				break;
			case 1:
				show2Stars();
				break;
			case 2:
				show3Stars();
				break;
			case 3:
				show4Stars();
				break;
			case 4:
				show5Stars();
				break;
			case 5:
				show6Stars();
				break;
		}
	}
	while(1)
	{
		if(key() == 0x0a) { //依位次替换原先密码为新密码
			for(i = 0; i < 6; i++)
				pwd[i] = buf[i];
			break;
		}		
	}
	
}


//修改密码,如果修改密码成功,返回1,否则返回0
u16 modify()
{
	if(checkPwd())   // 首先让用户重新输入密码并与原密码进行比较,如果正确则返回1,否则返回0
	{   // 原密码输入正确
		LCD_INIT();       // 清屏,液晶初始化
		showNewPwd();      // 显示"新的密码"汉字
		changePwd(); // 让用户输入新密码,实现更改密码
		return 1;
	}
	else
		return 0;
}

//管理员功能:如果管理员密码输入正确,则将开锁密码重置为123456,并返回1,管理员密码只允许数字出现。
u16 adminOption()
{
	u8 i;
	u16 buf[8];
	while(1)
	{
		u16 inputPassword = 0;   // !!!!!!!!!初始化!!!!!!!!!
		for(i = 0;i < 8;i++)     // 管理员输入密码(扫描8次键盘)
		{
			buf[i] = key();
			if(buf[i] == 0x0f)    // 若按下了我们设定的微机键盘del键,则清屏后重新输入密码
			{
				i = -1;			  // 先置i=-1,以使continue之后i=0,可以继续按键盘6次
				LCD_INIT();       // 液晶初始化
				showReEnter();     // 显示"重新输入"汉字
				delayTime();      // 延时一段时间
				LCD_INIT();       // 液晶初始化
				continue;         // 进入下一循环
			}
			LCD_INIT();
			switch(i)
			{
				case 0:
					show1Star();
					break;
				case 1:
					show2Stars();
					break;
				case 2:
					show3Stars();
					break;
				case 3:
					show4Stars();
					break;
				case 4:
					show5Stars();
					break;
				case 5:
					show6Stars();
					break;
				case 6:
					show7Stars();
					break;
				case 7:
					show8Stars();
					break;
               	} 
		}
	
		for(i = 0; i < 8; i++)   // 计算管理员密码对应的十进制值
		{
			inputPassword = inputPassword*10 + buf[i];
		}
		while(1)
		{
			if(key() == 0x0a)
				break;
		}
		if(inputPassword == adminPassword)
		{
			//password = 123456; // 重置密码为123456
			for(i = 0; i < 6; i++)
			{
				pwd[i] = i + (u8)'1';
			}
			LCD_INIT();        // 液晶初始化
			showCorrectPwd();        // 显示密码正确
			delayTime();
			return 1;
		}
			// 密码错误,锁定系统
			else				
			{
				LCD_INIT();					
				delayTime();
				showSystemLocked();     // 第2行显示"系统锁定"
				yellowl();		// 黄灯闪烁5s
				     	LCD_INIT();    // 液晶初始化
						delayTime();
				return 0;       // 进入下一循环
			}
	}
}

//a键代表开锁,如果开锁成功则返回1,如果密码错误超过三次则返回0
u16 openLock()
{
	u16 errorcount = 0;
	u16  t;
	while(1)
	{
		// 若输错3次,返回0
		if(errorcount >= 3)   
			return 0;
		// 若输错没到3次,液晶显示提示信息"再次输入"
		if(errorcount != 0 && errorcount != 3)
		{
			LCD_INIT();					
			delayTime();
			showEnterAgain();       // 第2行显示"再次输入"
		}

		t = checkPwd();  // 输入密码并与原密码进行比较,如果正确则返回1,否则返回0
		if(t)
			return 1;
		else 
			errorcount++;     // 输入错误,error数加一
	}
}

void main()
{
	outportb(CON_Addr, 0x81);	// 写控制字1000 0001————A口、B口方式0,输出;C口低4位:输入
	outportb(CON_Addr,0x0f);    // 写控制字0000 1111————C口位操作:将PC7置位,控制蜂鸣器
	blackl();    			    // 一加电应该保持8个LED灯全灭
	while(1)
	{
		//液晶显示 请输入按键
		LCD_INIT();					
		delayTime();
		showInputButton();
		tt = key();
		// 输入a,尝试开锁
		if(tt == 0x0a)   		
		{
			LCD_INIT();
			delayTime();
			showEnterPwd();			// 第2行显示"输入密码"

			// 如果开锁成功则返回1,如果密码错误超过三次则返回0
			if(openLock())
			{
				LCD_INIT();		// 液晶初始化
				delayTime();
				showCorrectPwd();     // 第2行显示"密码正确"
				delayTime();
				greenl();       // 绿灯亮10s
				redl();         // 红灯亮5s
				blackl();       // 全熄灭
				continue;       // 进入下一循环
			}

			// 三次密码错误,锁定系统
			else				
			{
				LCD_INIT();					
				delayTime();
				showSystemLocked();     // 第2行显示"系统锁定"
				yellowl();		// 黄灯闪烁5s
				continue;       // 进入下一循环
			}
		}

		// 输入b,修改密码功能	
		else if(tt == 0x0b)
		{
			// 打印输入原密码
			LCD_INIT();
			showUsedPwd();
			if(modify())   	    // 修改密码,如果修改密码成功,返回1,否则返回0
			{
				LCD_INIT();
				showModifiedSuccess();
				delayTime();
			}
				// 密码错误,锁定系统
			else				
			{
				LCD_INIT();					
				delayTime();
				showSystemLocked();     // 第2行显示"系统锁定"
				yellowl();		// 黄灯闪烁5s
				continue;       // 进入下一循环
			}
		}

		//输入c,进入管理员功能:将开锁密码重置为123456
		else if(tt == 0x0c)    
		{
			LCD_INIT();
			showEnterPwd();        // 第2行显示"输入密码"
			delayTime();
			if(adminOption())        // adminOption()函数:如果管理员密码输入正确,将开锁密码重置为123456并返回1
			{
				LCD_INIT();
			  	showResetSuccess();   // 显示"重置成功"
			  	delayTime();
			}
			
			
		}
	}
}






 注释:代码大部分源于demo文件和学长的帮助

基本功能具体可参考学长的文章:西电微原课设——矩阵式键盘数字密码锁设计_矩阵按键密码锁-CSDN博客

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值