单片机C语言实例:32、实用密码锁

程序实例1:延时函数

#ifndef __DELAY_H__
#define __DELAY_H__
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t);
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t);

#endif

 

#include "delay.h"
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

程序实例2:1602驱动

#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include

#ifndef __1602_H__
#define __1602_H__


 bit LCD_Check_Busy(void) ;

 void LCD_Write_Com(unsigned char com) ;

 void LCD_Write_Data(unsigned char Data) ;

 void LCD_Clear(void) ;

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;

 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) ;

 void LCD_Init(void) ;
   
#endif
#include "1602.h"
#include "delay.h"

#define CHECK_BUSY

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
#ifdef CHECK_BUSY
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
#else
	return 0;
#endif
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}


/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{           
	while (*s) 
 	{     
		LCD_Write_Char(x,y,*s);     
		s ++;  x++;   
 	}
 }
 
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}

程序实例3:按键驱动

#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void);  //键盘扫描函数,使用行列反转扫描法

/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void);

#endif
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include"keyboard.h"
#include"delay.h"

#define KeyPort P3

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
{
	unsigned char cord_h,cord_l;//行列值中间变量
	KeyPort=0x0f;            //行线输出全为0
	cord_h=KeyPort&0x0f;     //读入列线值
	if(cord_h!=0x0f)    //先检测有无按键按下
	{
		DelayMs(10);        //去抖
		if((KeyPort&0x0f)!=0x0f)
		{
			cord_h=KeyPort&0x0f;  //读入列线值
			KeyPort=cord_h|0xf0;  //输出当前列线值
			cord_l=KeyPort&0xf0;  //读入行线值
	
			while((KeyPort&0xf0)!=0xf0);//等待松开并输出
	
			return(cord_h+cord_l);//键盘最后组合码值
		}
	}
	return(0xff);     //返回该值
}

/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
{
	switch(KeyScan())
	{
		case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
		case 0x7d:return 1;break;//1
		case 0x7b:return 2;break;//2
		case 0x77:return 3;break;//3
		case 0xbe:return 4;break;//4
		case 0xbd:return 5;break;//5
		case 0xbb:return 6;break;//6
		case 0xb7:return 7;break;//7
		case 0xde:return 8;break;//8
		case 0xdd:return 9;break;//9
		case 0xdb:return 10;break;//a
		case 0xd7:return 11;break;//b
		case 0xee:return 12;break;//c
		case 0xed:return 13;break;//d
		case 0xeb:return 14;break;//e
		case 0xe7:return 15;break;//f
		default:return 0xff;break;
	}
}

程序实例4:main文件

#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include
#include"1602.h"
#include"delay.h"
#include"keyboard.h"


unsigned char code password[]={1,2,3,4,5,6,7,8};//可以更改此密码做多组测试
//定义密码,实际上密码需要存在eeprom中,可以通过程序更改。请用户自行添加


/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
	unsigned char num,i,j;                  
	unsigned char passwordtemp[16];        //最大输入16个
	unsigned char inputtimes;              //密码输入错误次数
	unsigned char passwordlength,PLEN;     //输入密码长度,实际密码长度
	bit Flag;
	
	PLEN=sizeof(password)/sizeof(password[0]);//用于计算出实际密码长度
	
	LCD_Init();         //初始化液晶屏
	DelayMs(10);        //延时用于稳定,可以去掉
	LCD_Clear();        //清屏
	LCD_Write_String(0,0,"  Welcome! ");    //写入第一行信息,主循环中不再更改此信息,所以在while之前写入
	LCD_Write_String(0,1,"Input password!");    //写入第二行信息,提示输入密码
	while (1)         //主循环
	{
		num=KeyPro();  //扫描键盘
		if(num!=0xff)  //如果扫描是按键有效值则进行处理
		{ 
			if(i==0)    //输入是第一个字符的时候需要把改行清空,方便观看密码
			LCD_Write_String(0,1,"                ");//清除该行
			if(i<16)
			{
				passwordtemp[i]=num;
				LCD_Write_Char(i,1,'*');//输入的密码用"*"代替
			}
			i++;   //输入数值累加
			if((15==num)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对
			{
				passwordlength=i-1;  //计算输入密码长度
				i=0;  //计数器复位
				if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误
				{
					Flag=1;//先把比较位置1
					for(j=0;j>>>");//密码正确显示的信息
					inputtimes=0;//输入正确则次数清零,重新计数
					Flag=0;      //清除正确标志
				}
				else 
				{
					LCD_Write_String(0,1,"                ");//清除该行
					LCD_Write_String(0,1,"Wrong! Retry!");//密码错误,提示重新输入
					inputtimes++;//连续输入错误,则次数累加
					if(inputtimes==3)
					{
						LCD_Write_String(0,1,"                ");//清除该行
						LCD_Write_String(0,1,"Wrong 3 times!");//密码错误,提示重新输入
						while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
					}
				}

			}
		}	
	}
}

你可能感兴趣的:(单片机项目,单片机,c语言,嵌入式硬件)