密码锁设计要求如下:1、数字密码锁能够设置14位数字密码;2、输入密码正确显示”ON”,输入错误显示”OFF”;3、密码初始值为“8889999999999999999998”;4、输入原密码正确可以修改密码。根据设计要求,在设计时采用89C52单片机作为核心器件,利用C语言作为开发源程序。四位数字密码在硬件上由4位LED数码显示器显示,单片机采取动态显示方式控制数码显示管,可同时显示4位数字,用4个三极管驱动4位LED显示器;由单片机内部程序可使得密码锁输入密码正确显示”ON”,输入错误显示”OFF”;开辟4个存储单元用于存储4位密码,通过2×4的矩阵式按键键盘和相关程序可实现密码锁密码初始值为“8888”,并且输入原密码正确可以修改密码的功能。1.2系统构成框图按照系统设计的要求和功能,可以将系统分为主控模块、按键扫描模块、蜂鸣器及LED灯、电源电路、复位电路、晶振电路、驱动电路几个模块。如图1.1所示,主控模块采用89C52单片机。1图1.1基于89C52单片机的密码锁组成模块图一.数字密码锁的硬件设计2.1电路原理图系统硬件电路图如图2.1所示,P3口接密码按键,提示音由P3.7输出,晶振频率为12MHz,Q1~Q4控制4位数码显示器。限于篇幅,电路原理图中多出采用网络标号表示元件之间的连接。电源电路主控模块89C52复位电路晶振电路按键扫描模块驱动电路蜂鸣器和LED灯2C3C4EA/VPP31XTAL119XTAL218RST9P3.7(RD)17P3.6(WR)16P3.2(INT0)12P3.3(INT1)13P3.4(T0)14P3.5(T1)15P1.0(T2)1P1.1(T2EX)2P1.23P1.34P1.45P1.56P1.67P1.78(AD0)P0.039(AD1)P0.138(AD2)P0.237(AD3)P0.336(AD4)P0.435(AD5)P0.534(AD6)P0.633(AD7)P0.732(A8)P2.021(A9)P.2122(A10)P2.223(A11)P2.324(A12)P2.425(A13)P2.526(A14)P2.627(A15)P2.728PSEN29ALE/PROG30(TXD)P3.111(RXD)P3.010GND20VCC40U1R3Q9VCCD1R2C11VCCC2123456789101112DIGILED1C1+1V+2C1-3C2+4C2-5V-6T2OUT7R2IN8R2OUT9T2IN10T1IN11R1OUT12R1IN13T1OUT14GND15VCC16U2MAX2321234USB1234CONN1Q3Q4Q2Q1VCCDIG1DIG2DIG3DIG4DIG11DIG12DIG13DIG14DIG4DIG3DIG2DIG1123SWITCH1R6R7R8R9R10R11R12R13R18R19R20R2112Y11234SW-RSTR1C6C7C8C912KEY112KEY212KEY312KEY412KEY512KEY612KEY712KEY8DS1DS2DS3DS4DS5DS6DS7DS8DIG11DIG12DIG13DIG14P37PS37DS2VCCP30P31P32P33P34P35P36P37RSTX1X2EAVCCGNDPSENALE12345UARTDS6DS1DS3DS4DS5DS7DS8GNDPCPCRxDTxDGNDPS37PS37PS37PS37P36P36P36P36P30P31P32P33P30P31P32P33R14R15R16R17LS1图2.1数字密码锁原理图2.2电子线路CAD软件生成的PCB图如图2.2所示,考虑到打印的示图效果,印制电路板未经过覆铜处理。31212211212121221123421122121212121212112321123123123123211212121212121212121212121212121212124321123212223242526272829303132333435363738394020191817161514131211109876543219101112131415168765432112345432121123456789101112图2.2电路原理图生成印制电路板图2.3元器件列表序号器件名称参数数量1USB座12USB线13双排针214跳帽25电容0.1uF66LED灯17电阻2K1840针座19STC89C52110晶振12MHz111电容20pF212复位键113电阻10K114蜂鸣器115三极管9015516电阻33014716针座118MAX232119单排针5120按键821单排针3122跳帽1234位LED124电阻4.7K825电阻3308二.数字密码锁的软件设计3.1程序基本流程图图3.1数字密码锁程序流程图3.2源程序开始结束N初始化有键按下?调用显示和扫描比较键值是否正确?YNNYY显示on显示offY是否够4位?存储键值Y调用显示和扫描有键按下?是否够4位?N存储并覆盖原键值N5/*原始密码8888*/#includereg52.h#includeintrins.h//voiddelay(void);//按键销抖延时//voidkeyscan(void);//键盘扫描//bitpwcmp(void);//密码比较/*数码管表格*/unsignedcharcodedis_code[14]={0xc0,0xf9,0xa4,0xb0,//0,1,2,30x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xc8,0x8e,0xff};//4,5,6,7,8,9,-,on,offunsignedchardatadis_index;unsignedchardatadis_digit;//字位unsignedchardatadis_buf[4];//字形码缓冲区unsignedchardatacount;//密码位计数unsignedchardatapw[4];//密码存储区unsignedchardatapwin[4];//输入密码存储区bitshowflag;//数码管显示bitupdataflag;//更改密码标志,updataflag=1时,输入密码存入pw[]bitpwflag;//密码正确voiddisplay(unsignedchari){P2=0xfe;6P0=dis_code[i];}/*功能:延时子程序*/voiddelay(void){unsignedchari,j;for(i=0;i200;i++)for(j=0;j250;j++);}/*函数功能:密码比较子程序*/voidpwcmp(void){unsignedcharj;for(j=0;j4;j++){if(pw[j]==pwin[j])pwflag=1;else{pwflag=0;j=4;}}if(count4)//密码小于4位,直接显示OFF{pwflag=0;count=4;}7if(pwflag==1){dis_buf[0]=dis_code[11];dis_buf[1]=dis_code[0];dis_buf[2]=dis_code[13];dis_buf[3]=dis_code[13];}else{dis_buf[0]=dis_code[12];dis_buf[1]=dis_code[12];dis_buf[2]=dis_code[0];dis_buf[3]=dis_code[13];}}/*函数功能:键盘扫描子程序*/voidkeyscan(void){unsignedcharn,j;//扫描第一行P3=0xfe;n=P3;n&=0xf0;if(n!=0xf0)8{delay();P3=0xfe;n=P3;n&=0xf0;if(n!=0xf0){switch(n){case(0xb0):if(count4){dis_buf[count]=dis_code[8];if(updataflag==1)//按下修改密码键pw[count]=0;elsepwin[count]=0;count++;delay();}break;case(0x70):9if(count4){dis_buf[count]=dis_code[8];if(updataflag==1)//按下修改密码键pw[count]=3;elsepwin[count]=3;count++;delay();}break;}}}//扫描第二行P3=0xfd;n=P3;n&=0xf0;if(n!=0xf0){delay();P3=0xfd;10n=P3;n&=0xf0;if(n!=0xf0){switch(n){case(0xb0):{updataflag=1;for(j=0;j4;j++)dis_buf[j]=dis_code[10];count=0;pwin[0]=0;pwin[1]=0;pwin[2]=0;pwin[3]=0;delay();}break;case(0x70):if(count4){dis_buf[count]=dis_code[8];11if(updataflag==1)//按下修改密码键pw[count]=2;elsepwin[count]=2;count++;delay();}break;}}}/*函数功能:主程序*/voidmain(void){unsignedcharj;P2=0x0;TMOD=0x11;TH0=0xFC;TL0=0x17;TR0=1;ET0=1;EA=1;12count=0;//初始没有输入密码updataflag=0;pwflag=0;dis_digit=0xfe;dis_index=0;pw[0]=8;//初始密码8888pw[1]=8;pw[2]=8;pw[3]=8;showflag=1;//打开数码管显示for(j=0;j4;j++)dis_buf[j]=dis_code[10];while(1){keyscan();}}voidtimer0()interrupt1//定时器0中断服务程序,用于数码管的动态扫描//dis_index---显示索引,用于标识当前显示的数码管和缓冲区的偏移量//dis_digit---位选通值,传送到P2口用于选通当前数码管的数值,13如等于0xfe时,选通P2.0口数码管//dis_buf---显示缓冲区基地址{TH0=-2000/256;TL0=-2000%256;P2=0xff;//先关闭所有数码管P0=dis_buf[dis_index];//显示代码传送到P0口P2=dis_digit;dis_digit=_crol_(dis_digit,1);//位选通值左移,下次中断时选通下一位数码管dis_index++;dis_index&=0x03;//数码管全部扫描一遍,回到第一个开始下次扫描if(dis_digit==0xef){dis_digit=0xfe;}}