单片机学习笔记————51单片机实现在数码管中实现iphone4S开机密码锁的程序
一、使用proteus绘制简单的电路图,用于后续仿真
二、编写程序
/********************************************************************************************************************
---- @Project: LED-74HC595
---- @File: main.c
---- @Edit: ZHQ
---- @Version: V1.0
---- @CreationTime: 20200627
---- @ModifiedTime: 20200627
---- @Description: 数字1键对应S1键,数字2键对应S2键,数字3键对应S3键…. 数字9键对应S9键, 数字0键对应S10键。其他的按键不用。
---- 本程序有3个窗口。
---- 开机显示第1个密码登录框窗口“----”,在这个窗口下输入密码,如果密码等于”9922”表示密码正确,将会切换到第2个显示按键值的窗口。在窗口2下,按不同的按键会显示不同的按键值,如果10秒内没有按键操作,将会自动切换到第1个密码登录窗口,类似手机上的自动锁屏操作。在密码登录窗口1下,如果密码不正确,会自动清除密码的数字,继续在窗口1下显示”----”。
---- 窗口3是用来停留0.5秒显示全部密码的信息,然后根据密码的正确与否自动切换到对应的窗口。
---- 单片机:AT89C52
********************************************************************************************************************/
#include "reg52.h"
/*——————宏定义——————*/
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/500) /*0.5ms timer calculation method in 12Tmode*/#define const_voice_short 18 /*蜂鸣器短叫的持续时间*/
#define const_key_time 9 /*按键去抖动延时的时间*/#define const_no_key_push 960 /*大概10秒内无按键按下的时间*/
#define const_0_1s 48 /*大概0.5秒的时间*//*——————变量函数定义及声明——————*/
/*定义数码管的74HC595*/
sbit Dig_Hc595_Sh = P2^0;
sbit Dig_Hc595_St = P2^1;
sbit Dig_Hc595_Ds = P2^2;/*定义蜂鸣器*/
sbit Beep = P2^7;/*作为中途暂停指示灯 亮的时候表示中途暂停*/
sbit LED = P3^5;/*定义按键*/
sbit Key_S1 = P0^0; /*第一行输入*/
sbit Key_S2 = P0^1; /*第二行输入*/
sbit Key_S3 = P0^2; /*第三行输入*/
sbit Key_S4 = P0^3; /*第四行输入*/sbit Key_D1 = P0^4; /*第一列输入*/
sbit Key_D2 = P0^5; /*第二列输入*/
sbit Key_D3 = P0^6; /*第三列输入*/
sbit Key_D4 = P0^7; /*第四列输入*/unsigned char ucKeyStep = 1; /*按键扫描步骤变量*/
unsigned int uiKeyTimeCnt = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock = 0; /*按键触发后自锁的变量标志*/unsigned char ucRowRecord = 1; /*记录当前扫描到第几列了*/
unsigned char ucKeySec = 0; /*被触发的按键编号*/unsigned char ucDigShow8; /*第8位数码管要显示的内容*/
unsigned char ucDigShow7; /*第7位数码管要显示的内容*/
unsigned char ucDigShow6; /*第6位数码管要显示的内容*/
unsigned char ucDigShow5; /*第5位数码管要显示的内容*/
unsigned char ucDigShow4; /*第4位数码管要显示的内容*/
unsigned char ucDigShow3; /*第3位数码管要显示的内容*/
unsigned char ucDigShow2; /*第2位数码管要显示的内容*/
unsigned char ucDigShow1; /*第1位数码管要显示的内容*/unsigned char ucDigDot8; /*数码管8的小数点是否显示的标志*/
unsigned char ucDigDot7; /*数码管7的小数点是否显示的标志*/
unsigned char ucDigDot6; /*数码管6的小数点是否显示的标志*/
unsigned char ucDigDot5; /*数码管5的小数点是否显示的标志*/
unsigned char ucDigDot4; /*数码管4的小数点是否显示的标志*/
unsigned char ucDigDot3; /*数码管3的小数点是否显示的标志*/
unsigned char ucDigDot2; /*数码管2的小数点是否显示的标志*/
unsigned char ucDigDot1; /*数码管1的小数点是否显示的标志*/unsigned char ucDigShowTemp = 0; /*临时中间变量*/
unsigned char ucDisplayDriveStep = 1; /*动态扫描数码管的步骤变量*/unsigned char ucWd1Update = 1; /*窗口1更新显示标志*/
unsigned char ucWd2Update = 0; /*窗口2更新显示标志*/
unsigned char ucWd3Update = 0; /*窗口2更新显示标志*/
unsigned char ucWd = 1; /*本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。*/unsigned char ucInputPassword[4]; /*在第1个窗口下,显示输入的4个密码*/
unsigned char ucPasswordCnt = 0; /*记录当前已经输入到哪一位密码了*/
unsigned char ucKeyNumber = 1; /*在第2个窗口下,显示当前被按下的按键*/unsigned int uiNoKeyPushTimer = const_no_key_push; /*10秒内无按键按下的计时器*/
unsigned int uiPasswordTimer = const_0_1s; /*显示0.5秒钟全部密码的计时器,让窗口3停留显示0.5秒钟之后自动消失*/unsigned char ucTemp1 = 0; /*中间过渡变量*/
unsigned char ucTemp2 = 0; /*中间过渡变量*/
unsigned char ucTemp3 = 0; /*中间过渡变量*/
unsigned char ucTemp4 = 0; /*中间过渡变量*/unsigned int uiVoiceCnt = 0; /*蜂鸣器鸣叫的持续时间计数器*/void Dig_Hc595_Drive(unsigned char, unsigned char);/*根据原理图得出的共阴数码管字模表*/
code unsigned char Dig_Table[] =
{
0x3f, /*0 序号0*/
0x06, /*1 序号1*/
0x5b, /*2 序号2*/
0x4f, /*3 序号3*/
0x66, /*4 序号4*/
0x6d, /*5 序号5*/
0x7d, /*6 序号6*/
0x07, /*7 序号7*/
0x7f, /*8 序号8*/
0x6f, /*9 序号9*/
0x00, /*不显示 序号10*/
0x40, /*- 序号11*/
0x73, /*P 序号12*/
};/**
* @brief 定时器0初始化函数
* @param 无
* @retval 初始化T0
**/
void Init_T0(void)
{TMOD = 0x01; /*set timer0 as mode1 (16-bit)*/TL0 = T1MS; /*initial timer0 low byte*/TH0 = T1MS >> 8; /*initial timer0 high byte*/
}
/**
* @brief 外围初始化函数
* @param 无
* @retval 初始化外围
* 让数码管显示的内容转移到以下几个变量接口上,方便以后编写更上一层的窗口程序。
* 只要更改以下对应变量的内容,就可以显示你想显示的数字。
**/
void Init_Peripheral(void)
{unsigned int i;ucDigDot8 = 0; ucDigDot7 = 0; ucDigDot6 = 0; ucDigDot5 = 0; ucDigDot4 = 0;ucDigDot3 = 0; ucDigDot2 = 0; ucDigDot1 = 0; for(i = 0; i < 4; i ++){ucInputPassword[i] = 11; /*开机默认密码全部显示"----"*/}ET0 = 1;/*允许定时中断*/TR0 = 1;/*启动定时中断*/EA = 1;/*开总中断*/
}/**
* @brief 初始化函数
* @param 无
* @retval 初始化单片机
**/
void Init(void)
{LED = 0;Beep = 1; Dig_Hc595_Drive(0x00, 0x00); /*关闭所有经过另外两个74HC595驱动的LED灯*/Init_T0();
}
/**
* @brief 延时函数
* @param 无
* @retval 无
**/
void Delay_Long(unsigned int uiDelayLong)
{unsigned int i;unsigned int j;for(i=0;i<uiDelayLong;i++){for(j=0;j<500;j++) /*内嵌循环的空指令数量*/{; /*一个分号相当于执行一条空语句*/}}
}
/**
* @brief 延时函数
* @param 无
* @retval 无
**/
void Delay_Short(unsigned int uiDelayShort)
{unsigned int i;for(i=0;i<uiDelayShort;i++){; /*一个分号相当于执行一条空语句*/}
}/**
* @brief 显示数码管字模的驱动函数
* @param 无
* @retval 动态驱动数码管的原理
* 在八位数码管中,在任何一个瞬间,每次只显示其中一位数码管,另外的七个数码管
* 通过设置其公共位com为高电平来关闭显示,只要切换画面的速度足够快,人的视觉就分辨不出来,感觉八个数码管
* 是同时亮的。以下dig_hc595_drive(xx,yy)函数,其中第一个形参xx是驱动数码管段seg的引脚,第二个形参yy是驱动
* 数码管公共位com的引脚。
**/
void Display_Drive(void)
{switch(ucDisplayDriveStep){case 1: /*显示第1位*/ucDigShowTemp = Dig_Table[ucDigShow1];if(ucDigDot1 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xfe);break;case 2: /*显示第2位*/ucDigShowTemp = Dig_Table[ucDigShow2];if(ucDigDot2 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xfd);break;case 3: /*显示第3位*/ucDigShowTemp = Dig_Table[ucDigShow3];if(ucDigDot3 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xfb);break;case 4: /*显示第4位*/ucDigShowTemp = Dig_Table[ucDigShow4];if(ucDigDot4 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xf7);break;case 5: /*显示第5位*/ucDigShowTemp = Dig_Table[ucDigShow5];if(ucDigDot5 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xef);break;case 6: /*显示第6位*/ucDigShowTemp = Dig_Table[ucDigShow6];if(ucDigDot6 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xdf);break;case 7: /*显示第7位*/ucDigShowTemp = Dig_Table[ucDigShow7];if(ucDigDot7 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0xbf);break;case 8: /*显示第8位*/ucDigShowTemp = Dig_Table[ucDigShow8];if(ucDigDot8 == 1){ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/}Dig_Hc595_Drive(ucDigShowTemp, 0x7f);break;}ucDisplayDriveStep ++; /*逐位显示*/if(ucDisplayDriveStep > 8) /*扫描完8个数码管后,重新从第一个开始扫描*/{ucDisplayDriveStep = 1;}
}
/**
* @brief 数码管的595驱动函数
* @param 无
* @retval
* 如果直接是单片机的IO口引脚驱动的数码管,由于驱动的速度太快,此处应该适当增加一点delay延时或者
* 用计数延时的方式来延时,目的是在八位数码管中切换到每位数码管显示的时候,都能停留一会再切换到其它
* 位的数码管界面,这样可以增加显示的效果。但是,由于是间接经过74HC595驱动数码管的,
* 在单片机驱动74HC595的时候,dig_hc595_drive函数本身内部需要执行很多指令,已经相当于delay延时了,
* 因此这里不再需要加delay延时函数或者计数延时。
**/
void Dig_HC595_Drive(unsigned char ucDigStatusTemp16_09, unsigned char ucDigStatusTemp08_01)
{unsigned char i;unsigned char ucTempData;Dig_Hc595_Sh = 0;Dig_Hc595_St = 0; ucTempData = ucDigStatusTemp16_09; /*先送高8位*/for(i = 0; i < 8; i ++){if(ucTempData >= 0x80){Dig_Hc595_Ds = 1;}else{Dig_Hc595_Ds = 0;}/*注意,此处的延时delay_short必须尽可能小,否则动态扫描数码管的速度就不够。*/Dig_Hc595_Sh = 0; /*SH引脚的上升沿把数据送入寄存器*/Delay_Short(1); Dig_Hc595_Sh = 1;Delay_Short(1); ucTempData = ucTempData <<1;}ucTempData = ucDigStatusTemp08_01; /*再先送低8位*/for(i = 0; i < 8; i ++){if(ucTempData >= 0x80){Dig_Hc595_Ds = 1;}else{Dig_Hc595_Ds = 0;}Dig_Hc595_Sh = 0; /*SH引脚的上升沿把数据送入寄存器*/Delay_Short(1); Dig_Hc595_Sh = 1;Delay_Short(1); ucTempData = ucTempData <<1;}Dig_Hc595_St = 0; /*ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来*/Delay_Short(1);Dig_Hc595_St = 1;Delay_Short(1);Dig_Hc595_Sh = 0; /*拉低,抗干扰就增强*/Dig_Hc595_St = 0;Dig_Hc595_Ds = 0;
}
/**
* @brief 扫描按键
* @param 无
* @retval 放在定时中断里
**/
void Key_Scan(void)
{switch(ucKeyStep){case 1: /*按键扫描输出第ucRowRecord列低电平*/if (ucRowRecord == 1) /*第一列输出低电平*/{Key_D1 = 0;Key_D2 = 1;Key_D3 = 1;Key_D4 = 1;}else if(ucRowRecord == 2) /*第二列输出低电平*/{Key_D1 = 1;Key_D2 = 0;Key_D3 = 1;Key_D4 = 1; }else if(ucRowRecord == 3) /*第三列输出低电平*/{Key_D1 = 1;Key_D2 = 1;Key_D3 = 0;Key_D4 = 1; }else if(ucRowRecord == 4) /*第四列输出低电平*/{Key_D1 = 1;Key_D2 = 1;Key_D3 = 1;Key_D4 = 0; } uiKeyTimeCnt = 0; /*延时计数器清零*/ucKeyStep ++; /*切换到下一个运行步骤*/ break;case 2: /*此处的小延时用来等待刚才列输出信号稳定,再判断输入信号。不是去抖动延时。*/uiKeyTimeCnt ++;if(uiKeyTimeCnt > 1){uiKeyTimeCnt = 0;ucKeyStep ++; /*切换到下一个运行步骤*/ }break;case 3:if(Key_S1 == 1 && Key_S2 == 1 && Key_S3 == 1 && Key_S4 == 1){ucKeyStep = 1; /*如果没有按键按下,返回到第一个运行步骤重新开始扫描*/ucKeyLock = 0; /*按键自锁标志清零*/uiKeyTimeCnt = 0; /*按键去抖动延时计数器清零*/ucRowRecord ++; /*输出下一列*/if(ucRowRecord > 4){ucRowRecord = 1; /*依次输出完四列之后,继续从第一列开始输出低电平*/}}else if(ucKeyLock == 0) /*有按键按下,且是第一次触发*/{if(Key_S1 == 0 && Key_S2 == 1 && Key_S3 == 1 && Key_S4 == 1){uiKeyTimeCnt ++;if(uiKeyTimeCnt > const_key_time){uiKeyTimeCnt = 0;ucKeyLock = 1;if(ucRowRecord == 1) /*第一列输出低电平*/{ucKeySec = 1; /*触发1号键*/}else if(ucRowRecord == 2) /*第二列输出低电平*/{ucKeySec = 2; /*触发2号键*/}else if(ucRowRecord == 3) /*第三列输出低电平*/{ucKeySec = 3; /*触发3号键*/}else /*第四列输出低电平*/{ucKeySec = 4; /*触发4号键*/}}}else if(Key_S1 == 1 && Key_S2 == 0 && Key_S3 == 1 && Key_S4 == 1){uiKeyTimeCnt ++;if(uiKeyTimeCnt > const_key_time){uiKeyTimeCnt = 0;ucKeyLock = 1;if(ucRowRecord == 1) /*第一列输出低电平*/{ucKeySec = 5; /*触发5号键*/}else if(ucRowRecord == 2) /*第二列输出低电平*/{ucKeySec = 6; /*触发6号键*/}else if(ucRowRecord == 3) /*第三列输出低电平*/{ucKeySec = 7; /*触发7号键*/}else /*第四列输出低电平*/{ucKeySec = 8; /*触发8号键*/}}}else if(Key_S1 == 1 && Key_S2 == 1 && Key_S3 == 0 && Key_S4 == 1){uiKeyTimeCnt ++;if(uiKeyTimeCnt > const_key_time){uiKeyTimeCnt = 0;ucKeyLock = 1;if(ucRowRecord == 1) /*第一列输出低电平*/{ucKeySec = 9; /*触发9号键*/}else if(ucRowRecord == 2) /*第二列输出低电平*/{ucKeySec = 10; /*触发10号键*/}else if(ucRowRecord == 3) /*第三列输出低电平*/{ucKeySec = 11; /*触发11号键*/}else /*第四列输出低电平*/{ucKeySec = 12; /*触发12号键*/}}}else if(Key_S1 == 1 && Key_S2 == 1 && Key_S3 == 1 && Key_S4 == 0){uiKeyTimeCnt ++;if(uiKeyTimeCnt > const_key_time){uiKeyTimeCnt = 0;ucKeyLock = 1;if(ucRowRecord == 1) /*第一列输出低电平*/{ucKeySec = 13; /*触发13号键*/}else if(ucRowRecord == 2) /*第二列输出低电平*/{ucKeySec = 14; /*触发14号键*/}else if(ucRowRecord == 3) /*第三列输出低电平*/{ucKeySec = 15; /*触发15号键*/}else /*第四列输出低电平*/{ucKeySec = 16; /*触发16号键*/}}}}break;}
}
/**
* @brief 按键输入函数
* @param 无
* @retval 由于数字按键的代码相似度高,因此封装在这个函数里
**/
void number_key_input(unsigned char ucWhichKey)
{switch(ucWd){case 1: /*在显示密码登录框的窗口下*/ucInputPassword[ucPasswordCnt] = ucWhichKey; /*输入的密码值显示*/ucPasswordCnt ++;if(ucPasswordCnt >= 4){ucPasswordCnt = 0;ucWd = 3; /*切换到第3个的窗口,停留显示1秒钟全部密码*/ucWd3Update = 1; /*更新显示窗口3*/uiPasswordTimer = const_0_1s; /*显示0.5秒钟全部密码的计时器,让窗口3停留显示0.5秒钟之后自动消失*/}ucWd1Update = 1; /*更新显示窗口1*/uiNoKeyPushTimer = const_no_key_push; /*10秒内无按键按下的计时器赋新值*/break;case 2: /*在显示按键值的窗口下*/ucKeyNumber = ucWhichKey; /*输入的按键数值显示*/ucWd2Update = 1;uiNoKeyPushTimer = const_no_key_push; /*10秒内无按键按下的计时器赋新值*/break;}
}/**
* @brief 按键服务的应用程序
* @param 无
* @retval 无
**/
void Key_Service(void)
{switch(ucKeySec) /*按键服务状态切换*/{case 1:number_key_input(1); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 2:number_key_input(2); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 3:number_key_input(3); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 4:number_key_input(4); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 5:number_key_input(5); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 6:number_key_input(6); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 7:number_key_input(7); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 8:number_key_input(8); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 9:number_key_input(9); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 10:number_key_input(0); /*由于数字按键的代码相似度高,因此把具体代码封装在这个函数里*/uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 11:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 12:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 13:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 14:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 15:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;case 16:uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/break;}
}
/**
* @brief 显示的窗口菜单服务程序
* @param 无
* @retval
*凡是人机界面显示,不管是数码管还是液晶屏,都可以把显示的内容分成不同的窗口来显示,
*每个显示的窗口中又可以分成不同的局部显示。其中窗口就是一级菜单,用ucWd变量表示。
*局部就是二级菜单,用ucPart来表示。不同的窗口,会有不同的更新显示变量ucWdXUpdate来对应,
*表示整屏全部更新显示。不同的局部,也会有不同的更新显示变量ucWdXPartYUpdate来对应,表示局部更新显示。
**/
void Display_Service(void) /*显示的窗口菜单服务程序*/
{switch(ucWd){case 1: /*显示窗口1的数据*/ /*窗口1要全部更新显示*/if(ucWd1Update == 1) {ucWd1Update = 0; /*及时清零标志,避免一直进来扫描*/ucDigShow8 = 10; /*显示空*/ucDigShow7 = 10; /*显示空*/ucDigShow6 = 10; /*显示空*/ucDigShow5 = 10; /*显示空*/ucDigShow4 = ucInputPassword[0]; /*第4位数码管显示输入的密码*/ucDigShow3 = ucInputPassword[1]; /*第3位数码管显示输入的密码*/ucDigShow2 = ucInputPassword[2]; /*第2位数码管显示输入的密码*/ucDigShow1 = ucInputPassword[3]; /*第1位数码管显示输入的密码*/}break;case 2: /*显示被按下的键值*/ /*窗口2要全部更新显示*/if(ucWd2Update == 1) {ucWd2Update = 0; /*及时清零标志,避免一直进来扫描*/ucDigShow8 = 10; /*显示空*/ucDigShow7 = 10; /*显示空*/ucDigShow6 = 10; /*显示空*/ucDigShow5 = 10; /*显示空*/ucDigShow4 = 10; /*显示空*/ucDigShow3 = 10; /*显示空*/ucDigShow2 = 10; /*显示空*/ucDigShow1 = ucKeyNumber; /*第1位数码管显示被按下的键值*/ }break;case 3: /*当输入完4个密码后,显示1秒钟的密码登录框*/ /*窗口3要全部更新显示*/if(ucWd3Update == 1) {ucWd3Update = 0; /*及时清零标志,避免一直进来扫描*/ucDigShow8 = 10; /*显示空*/ucDigShow7 = 10; /*显示空*/ucDigShow6 = 10; /*显示空*/ucDigShow5 = 10; /*显示空*/ucDigShow4 = ucInputPassword[0]; /*第4位数码管显示输入的密码*/ucDigShow3 = ucInputPassword[1]; /*第3位数码管显示输入的密码*/ucDigShow2 = ucInputPassword[2]; /*第2位数码管显示输入的密码*/ucDigShow1 = ucInputPassword[3]; /*第1位数码管显示输入的密码*/ }break; }
}/**
* @brief 定时器0中断函数
* @param 无
* @retval 无
**/
void ISR_T0(void) interrupt 1
{unsigned int i;TF0 = 0; /*清除中断标志*/TR0 = 0; /*关中断*/if(ucWd == 3) /*在窗口3下*/{if(uiPasswordTimer > 0){uiPasswordTimer --;}if(uiPasswordTimer == 0){/*如果密码等于9922,则正确*/if(ucInputPassword[0] == 9 && ucInputPassword[1] == 9 && ucInputPassword[2] == 2 && ucInputPassword[3] == 2){ucWd = 2; /*切换到第2个显示按键的窗口*/ucWd2Update = 1; /*更新显示窗口2*/}else /*如果密码不正确,则继续显示----*/{for(i = 0; i < 4; i ++){ucInputPassword[i] = 11; /*开机默认密码全部显示"----"*/}ucWd = 1;ucWd1Update = 1; /*更新显示窗口1*/}}}if(ucWd == 2) /*在窗口2下*/{if(uiNoKeyPushTimer > 0){uiNoKeyPushTimer --;}if(uiNoKeyPushTimer == 0) /*如果10秒内无按键按下,则自动切换到显示密码登录框的界面*/{for(i = 0; i < 4; i ++){ucInputPassword[i] = 11; /*开机默认密码全部显示"----"*/}ucWd = 1;ucWd1Update = 1; /*更新显示窗口1*/}}if(uiVoiceCnt != 0){uiVoiceCnt--; /*每次进入定时中断都自减1,直到等于零为止。才停止鸣叫*/Beep=0; /*蜂鸣器是PNP三极管控制,低电平就开始鸣叫。*/}else{; /*此处多加一个空指令,想维持跟if括号语句的数量对称,都是两条指令。不加也可以。*/Beep=1; /*蜂鸣器是PNP三极管控制,高电平就停止鸣叫。*/} Key_Scan(); /*按键扫描函数*/Display_Drive(); /*数码管字模的驱动函数*/TL0 = T1MS; /*initial timer0 low byte*/TH0 = T1MS >> 8; /*initial timer0 high byte*/TR0 = 1; /*开中断*/
}
/*————————————主函数————————————*/
/**
* @brief 主函数
* @param 无
* @retval 实现LED灯闪烁
**/
void main()
{/*单片机初始化*/Init();/*延时,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定*/Delay_Long(100);/*单片机外围初始化*/ Init_Peripheral();while(1){/*按键服务的应用程序*/Key_Service();/*显示的窗口菜单服务程序*/Display_Service();}
}
三、仿真实现
51单片机实现在数码管中实现iphone4S开机密码锁的程序
单片机学习笔记————51单片机实现在数码管中实现iphone4S开机密码锁的程序相关推荐
- 单片机学习笔记————51单片机实现带数码管显示的象棋比赛专用计时器
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- 单片机学习笔记————51单片机实现数码管中的倒计时程序
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- 单片机学习笔记————51单片机实现带数码管显示的加法简易计算器
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- 单片机学习笔记————51单片机实现主机的串口收发
proteus虚拟串口的实现:https://mp.csdn.net/console/editor/html/107251649 一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 / ...
- 单片机学习笔记————51单片机实现用LED灯和按键来模拟工业自动化设备的运动控制
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- 单片机学习笔记————51单片机实现矩阵键盘的组合按键触发
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- 单片机学习笔记————51单片机实现按住一个独立按键不松手的加速匀速触发
一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...
- C51汇编语言寻址方式,单片机学习:51单片机寻址方式详解
原标题:单片机学习:51单片机寻址方式详解 51单片机是对所有兼容Intel 8031指令系统的单片机的统称.该系列单片机的始祖是Intel 8031单片机,后来随着Flash rom 技术的发展,8 ...
- 单片机位寻址举例_单片机学习:51单片机寻址方式详解
51单片机是对所有兼容Intel 8031指令系统的单片机的统称.该系列单片机的始祖是Intel 8031单片机,后来随着Flash rom 技术的发展,8031单片机取得了长足的发展,成为了应用最广 ...
最新文章
- 2019-06-12 学习日记 day33 JDBC
- String类型的认识以及编译器优化
- vba 压缩图片_1分钟批量处理100张图片,Word图片批量压缩/提取/居中统统搞定
- 牛客18987 粉嘤花之恋(矩阵快速幂、斐波那契数列)
- php unserialize 实例,PHP ArrayIterator unserialize()用法及代码示例
- 《OpenGL编程指南(原书第9版)》——1.4 OpenGL渲染管线
- 在Linux下面的某一个文件的查找命令
- 如何避免_如何避免钢板弹簧受损
- 电力载波通信模块JST-HPLC-S-C在物联网通信领域的应用
- Postgresql 客户端连接问题
- word添加脚注后正文跑到下一页
- 图神经网络在知识图谱中的应用
- 过往记忆大数据 USDP 实测搭建,可替代CDH的免费大数据套件平台
- 网络重置后网络适配器丢失和网络适配器前面是黄色叹号怎么办?
- SAP 采购订单入库——收货业务分析
- html制作钟表盘,CSS3简易表盘时钟
- Centos7 源码安装mysql5.6
- 15必须掌握的win7快捷键
- 【ABAP】SE38的一些使用技巧
- 【算法】【递归与动态规划模块】两个字符串的公共最长子序列
热门文章
- 关于EAD: Elastic-Net Attacks to Deep Neural Networks via Adversarial Examples的理解
- 密码算法分类 (学习笔记)
- 一文弄懂Python中的 if __name__ == __main__
- 各种校验(手机号,银行卡,身份证,邮箱等)
- java Comparator 多个字段比较
- 如何使用设计模式——qq交流群讨论纪实
- 5.4 一家人才测评机构低随机抽取的10名小企业的经理人用两种方法进行自信心测试,得到的自信心测试分数如下
- 再谈 Linux下的nanosleep函数【转】
- 开发的vscode插件,如何在用户卸载该插件时,删除该插件对应的文件
- 利用oc门或od门实现线与_oc门_od门_ttl三态门电路特点总汇