⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwlock.c

📁 51单片机C语言应用程序设计实例精讲.rar
💻 C
字号:
/*****************************************/
/* Copyright (c) 2005, 通信工程学院      */
/* All rights reserved.                  */
/* 作    者:戴 佳						 */
/*****************************************/

#include "PWLock.h"

/* 键消抖延时函数 */
void delay(void)
{
	uchar i;
	for (i=300;i>0;i--);
}

/* 键扫描函数 */
uchar keyscan(void)
{
	uchar scancode,tmpcode;
	P1 = 0xf0;			 					// 发全0行扫描码
	if ((P1&0xf0)!=0xf0)					// 若有键按下
	{
		delay();							// 延时去抖动
		if ((P1&0xf0)!=0xf0)				// 延时后再判断一次,去除抖动影响
		{
			scancode = 0xfe;
			while((scancode&0x10)!=0)		// 逐行扫描
			{
				P1 = scancode;				// 输出行扫描码
				if ((P1&0xf0)!=0xf0)		// 本行有键按下
				{
					tmpcode = (P1&0xf0)|0x0f;

					/* 返回特征字节码,为1的位即对应于行和列 */
					return((~scancode)+(~tmpcode));
				}
				else scancode = (scancode<<1)|0x01;		// 行扫描码左移一位
			}
		}
	}
	return(0);								// 无键按下,返回值为0 	
}

/* 定时器0中断服务子程序,2ms定时动态扫描显示 */
void time0_int(void) interrupt 1 
{
	/* 重置2ms定时 */
	TH0 = -2000/256;
	TL0 = -2000%256;

	if (showflag==1)
		display();				// 调用显示函数
}

/* 定时器1中断服务子程序,50ms*/
void time1_int(void) interrupt 3 
{
	uchar k;
	/* 重置50ms定时 */
	TH1 = -50000/256;
	TL1 = -50000%256;

	if (t1count<20)				
	{
		t1count++;
	}
	else						// 计时到1s
	{
		TR1 = 0;				// 关闭计数器1
		t1count = 0;	
		green = 1;				// 绿灯不亮
		red = 1;				// 红灯不亮
		showflag = 1;			// 打开数码管显示
		digbit = 0x01;			// 从数码管第1位开始动态显示
		for (k=0;k<6;k++)		// 显示888888
			wordbuf[k] = 8;
	}
}

/* 根据共阴极字型编码表获取0~9,A~B字型代码 */
uchar getcode(uchar i)
{
	uchar p;
	switch (i)
	{
		case 0:	 p=0x3f;	break;			/* 0 */
		case 1:	 p=0x06;	break;			/* 1 */
		case 2:	 p=0x5B;	break;			/* 2 */
		case 3:	 p=0x4F;	break;			/* 3 */
		case 4:	 p=0x66;	break;			/* 4 */
		case 5:	 p=0x6D;	break;			/* 5 */
		case 6:	 p=0x7D;	break;			/* 6 */
		case 7:	 p=0x07;	break;			/* 7 */
		case 8:	 p=0x7F;	break;			/* 8 */
		case 9:	 p=0x67;	break;			/* 9 */
		case 10: p=0x77;	break;			/* A */
		case 11: p=0x7C;	break;			/* B */
		case 12: p=0x39;	break;			/* C */
		case 13: p=0x5E;	break;			/* D */
		case 14: p=0x79;	break;			/* E */
		case 15: p=0x71;	break;			/* F */
		default: 			break;
	}
	return(p);
}

/* 显示函数 */
void display(void)
{
	uchar i;
	switch (digbit)
	{
		case 1:		i=0;	break;
		case 2:		i=1;	break;
		case 4:		i=2;	break;
		case 8:		i=3;	break;
		case 16:	i=4;	break;
		case 32:	i=5;	break;
		default: 	break;
	}

	P2 = 0x0;						// 关闭显示
	P0 = getcode(wordbuf[i]);		// 送字型码
	P2 = digbit;					// 送字位码
	
	if (digbit<0x20)				// 共6位
		digbit = digbit*2;			// 左移一位
	else
	    digbit = 0x01;
}

/* 密码比较函数 */
bit pwcmp(void)
{
	bit flag;
	uchar i;
	for (i=0;i<6;i++)
	{
		if (pw[i]==pwbuf[i])
			flag = 1;
		else
		{
			flag = 0;
			i = 6;
		}
	}
	return(flag);
}

/* 主程序 */
void main()
{
	uchar j,key;

	P2 = 0x0;							// 关闭数码管显示
	
	TMOD = 0x11;						// T0,T1工作方式1

	/* 2ms 定时设置 */
	TH0 = -2000/256;
	TL0 = 2000%256;

	/* 50ms 定时设置 */
	TH1 = -50000/256;
	TL1 = -50000%256;
	
	/* 启动计数器0,关闭计数器1 */
	TR0 = 1;
	ET0 = 1;
	TR1 = 0;
	ET1 = 1;
	EA = 1;

	count = 0;						// 初始没有输入密码,计数器设为0
	enterflag = 0;					// 没有按下确认键
	pwflag = 0;						// 密码标志先置为0
    green = 1;						// 绿灯不亮
	red = 1;						// 红灯不亮
	
	/* 假设内定密码为937602 */
	pw[0] = 9;
	pw[1] = 3;
	pw[2] = 7;
	pw[3] = 6;
	pw[4] = 0;
	pw[5] = 2;
	
	digbit = 0x01;					// 从第一位数码管开始动态扫描

	/* 刚加电时,显示888888 */
	for (j=0;j<6;j++)
		wordbuf[j] = 8;

	showflag = 1;					// 打开数码管显示

  	while(1)
    {
		key = keyscan();					// 调用键盘扫描函数
		switch(key)
   		{
      		case 0x11:						// 1行1列,数字0
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F”
					pwbuf[count] = 0;
					count++;
				}
				break;
			case 0x21:						// 1行2列,数字1
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 1;
					count++;
				}
				break;			
			case 0x41:						// 1行3列,数字2
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 2;
					count++;
				}
				break;
     		case 0x81:						// 1行4列,数字3
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 3;
					count++;
				}
				break;
			case 0x12:						// 2行1列,数字4
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 4;
					count++;
				}
				break;
			case 0x22:						// 2行2列,数字5
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 5;
					count++;
				}
				break;
			case 0x42:						// 2行3列,数字6
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 6;
					count++;
				}
				break;
			case 0x82:						// 2行4列,数字7
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 7;
					count++;
				}
				break;
			case 0x14:						// 3行1列,数字8
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 8;
					count++;
				}
				break;
			case 0x24:						// 3行2列,数字9
				if (count<6)
				{
					wordbuf[count] = 0x0f;	// 对应密码位上显示“F"
					pwbuf[count] = 9;
					count++;
				}
				break;
			case 0x44:						// 3行3列,确认键
				enterflag = 1;				// 确认键按下
				if (count==6) 				// 只有输入6个密码后按确认键才作密码比较
					pwflag = pwcmp();
				else						
					pwflag = 0;				// 否则直接pmflag赋0
				break;
			case 0x84:						// 3行4列,取消键
				count = 0;					// 密码计数清零
				for (j=0;j<6;j++)
				{
					wordbuf[j] = 8;			// 数码管显示888888
					pwbuf[j] = 0x0f;		// 用FFFFFF清除已经输入的密码
				}
				break;
			default:break;
		}

		if (enterflag==1)					// 如果按下确认键
		{
			enterflag = 0; 					// 标志位置回0
			count = 0;						// 密码位计数器清零
			for (j=0;j<6;j++)
				pwbuf[j] = 0x0f;			// 用FFFFFF清除已经输入的密码			
			showflag = 0;					// 关闭数码管显示
			TR1 = 1;						// 计数器1开始计数
			t1count = 0;					// 定时器1由50ms累积到1s所用的计数器
			if (pwflag==1)			
				green = 0; 					// 绿灯亮
			else							
				red = 0; 					// 红灯亮		
		}
	}    
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -