微机课设 | 基于STC15单片机的简易数字密码锁设计

这篇具有很好参考价值的文章主要介绍了微机课设 | 基于STC15单片机的简易数字密码锁设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣。在安全技术防范领域,具有防盗报警功能的电子密码锁逐渐代替了传统的机械式密码锁,电子密码锁具有安全性高、成本低、功耗低、易操作等优点。本文主要介绍运用51单片机设计数字密码锁的方法。本设计采用自上而下的数字系统设计方法,将数字密码锁系统分解为若干子系统,并且进一步细划为若干模块,然后用C语言来设计这些模块,通过KEIL软件编译,并且进行实机调试。调试结果表明:该数字密码锁能够效验4位十进制数密码,且有显示实时时间,修改时间,显示输入密码,设置密码,修改密码,输入错误回删,重置密码,密码输入超时报警,输入次数过多报警等功能。该密码锁体积小,功耗低,操作简单,不怕掉电,维护和升级都十分方便,应用日益广泛。

  • 一、绪论

1.1 项目内容

利用FD51F_DB开发板设计数字密码锁。FD51F_DB开发板采用的是新一代增强型8051单片机IAP15F2K61S2芯片。该芯片具有STC15F2K60S2单片机的所有性能:不需要外部晶振和复位电路、可在线编程、大容量2K字节的SRAM、两个独立串口、8通道高速A/D转换器、1个时钟/机器周期8051等。同时IAP15具有自己的特色:可支持Keil中设置断点,在线单步调试等。

 项目的主要内容为利用单片机设计实现一个多位电子密码锁,该密码锁具有开锁和修改密码、输错密码超过三次会蜂鸣器报警等功能。除此之外它还具有简单电子表功能,可显示年、月、日、星期、时、分、秒。

1.2实现功能

  1. 设计一多位电子密码锁;
  2. 具有确定键和取消键,在未确定之前可以取消,重新输入;
  3. 连续输入三次错误密码,会产生报警电路动作,启动蜂鸣器,并返回初始界面;
  4. 具有密码重置、修改功能,密码输入等待操作时间限制功能,超过限定时间报警;
  5. 具有简单电子表功能,可显示年、月、日、星期、时、分、秒等;
  • 二、数字密码锁系统设计及实现

2.1设计方案

2.1.1程序流程图设计

此次课程设计使用keil5软件进行程序的编写与编译,编译无误后将程序烧录到开发板1上进行调试,进行数字密码锁各项功能的检验并观察结果。

项目完成的目标是设计实现一个多位电子密码锁,同时具有确定键和取消键,在未确定之前可以取消,重新输入;连续输入三次错误密码,会产生报警电路动作,启动蜂鸣器,并返回初始界面,无法继续进行密码输入;具有密码重置、修改功能,密码输入等待操作时间限制功能,超过限定的时间也将出发报警功能,此时蜂鸣器鸣叫;除此之外还具有简单电子表功能,可显示年、月、日、星期、时、分、秒。

程序流程框图如下图所示:

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

2.1.2程序模块功能描述及作用

主函数程序说明:

Step0_welcome:显示欢迎(待机画面),屏幕上方显示当前时间(年-月-日-时-分-秒 星期x)。显示过后跳转步骤1。

Step1_ask_changePassword:询问是否修改密码(原始密码为6666),显示选择菜单,有按键按下时跳转步骤2。

Step2_judge_changePassword:判断是否修改密码,若按键4按下,则跳转步骤3直接开锁,若按键6按下,则跳转步骤6修改密码。

Step3_tips:提示输入密码,跳转步骤4。

Step4_inputPassword:输入密码以*显示,若按键delete按下,则可以删除输入的密码值。

Step5_PasswordComparison:密码比对,正确就开锁,错误次数小于3时返回步骤3,错误次数超过3时返回步骤0,蜂鸣器报警标志置位。

Step6_changePassword():修改密码,调用修改密码分函数,实现修改密码完整功能。

Step6_0:提示输入原密码,跳转至步骤6_1                           

Step6_1:输入密码以*显示,同Step4_inputPassword。

Step6_2():密码比对,Step5_PasswordComparison。

Step6_3():判断输入密码错误次数是否小于3

Step6_4():输入新密码。

void Step6_5:保存新密码。

按键模块:扫描行列按键及独立按键,得出按下的按键位置及其代表值。为主函数提供按键扫描等函数。

存储模块:首先存储原始密码。在修改密码的步骤中,存储输入的新密码。在密码比对步骤中,提供正确密码值与输入的值比对。

12864显示模块:提供主函数中清屏、显示字符、显示汉字等函数。

时钟模块:计时,为主函数提供时钟信息。

蜂鸣器模块:当密码输入错误次数超过3或者输入密码时长超过25s时蜂鸣器报警。

2.1.3系统硬件框图

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

2.2硬件设计

2.2.1开发板

微机课设 | 基于STC15单片机的简易数字密码锁设计

管脚说明:

P0         LCD12864_DATAPINS

P3^7      LCD12864_EN

P4^1        LCD12864_RW

P4^2        LCD12864_D/I


p2^1    DS1302模块  SCLK

p2^2    DS1302模块  I/O

p4^4    DS1302模块  CE


P1^6    蜂鸣器


P3      矩阵键盘


P5^5    存储模块  24C02 SCL

P5^4    存储模块  24C02 SDA

2.2.2元器件清单

模块

个数

IAP15F2K61S2芯片

1

AT24C02

1

LCD12864

1

3x3按键模块

1

DS1302

1

蜂鸣器

1

2.3操作指南

单片机上电后lcd12864屏显示初始界面,第一排显示当时的年、月、日、星期,第二排显示当时的时、分、秒,第三排显示“welcome”。此时可以按下任意键继续,此时lcd12864屏显示菜单栏中开锁和修改密码两个选项。在这里我们可以“4”或“6”选择开锁(unlock)或者是修改密码(New  password)。如果这里选择的开锁,按下确定键,此时会提示输入密码(初始密码默认为6666)。输入密码后按下确定键,如果密码正确则会显示“欢迎小仙女”,如果输入密码错误则会提示“Error 密码错误”。如果输入密码时间超过规定时间(25s)则会显示“Error 已超时”,且启动蜂鸣器;如果输入密码错误超过三次,则会提示启动蜂鸣器,并且返回到初始界面。如果需要修改密码,则在菜单页面选择“New  password”。这里会提示输入原始密码。输入原始密码后按下确认键,如果密码正确会提示输入新密码。输入密码后按下确认键,会提示“OK”并返回到待机画面;如果输入密码错误超过三次,则会提示启动蜂鸣器,并且返回到初始界面。

main
/**************************************************************************************
*         电子密码锁           *

实现现象:下载程序输入正确密码,会开启数字密码锁
硬件连接:
                     矩阵键盘:
                     4      5      6

                     1      2      3

                    删除    0     确认

注意事项:无
***************************************************************************************/

#include "stc15f2k60s2.h"              //此文件中定义了单片机的一些特殊功能寄存器
#include "key.h"
#include "lcd12864.h"
#include "hc595.h"
#include "eeprom.h"
#include "ds1302.h"

#define u16 unsigned int      //对数据类型进行声明定义
#define u8 unsigned char
///*****************************************************************************/
u8 pw_num, Error_Num,Error_Num1;
u8 PassWord_Length = 4;
u8 PASSWORD[] = {6, 6, 6, 6};
u8 INPUT_PW_Tab[] = {6, 6, 6, 6};
u8 KeyValue, Step, Step6, Load_first_flag = 0, menu_flag = 0, fengming_flag = 0;
//     秒    分    时    日    月   星期   年
unsigned char code Init[7] = {0x00, 0x00, 0x12, 0x25, 0x05, 0x01, 0x22};
uchar *pBuf = 0;
//存放当前时间
unsigned char Now[7];
//保存RAM数据
unsigned char RAMData[7];
unsigned char T1_Cnt = 0;
//时间更新标记
bit UpdateTimeFlag;
///*****************************************************************************/
bit result_flag, Input_suc_flag, unlock_flag,chaoshi_flag;
bit List1 = 0;
///*****************************************************************************/
///*定义数字密码锁输入密码判断密码过程中的一些函数模块
///*******************************************************************************/
void Step0_welcome();//欢迎(待机画面)
void Step1_ask_changePassword();//询问是否修改密码(原始密码为6666)
void Step2_judge_changePassword();//判断是否修改密码
void Step3_tips();//提示输入密码
void Step4_inputPassword();//输入密码以*显示
void Step5_PasswordComparison();//密码比对,正确就开锁
void Step6_changePassword();//修改密码
void Step6_0();//提示输入原密码
void Step6_1();//输入密码以*显示
void Step6_2();//密码比对
void Step6_3();//判断输入的密码是否正确
void Step6_4();//输入新密码
void Step6_5();//保存新密码
///********************************************************************************/
///*定义一些上述函数中用到的函数模块
///*******************************************************************************/
void CipherComparison();
void input_password(bit m);
void Read_Password();
void delaya_ms(unsigned int ms)
{   unsigned int i;
    while ((ms--) != 0)
    {  for (i = 0; i < 600; i++);
    }
}
void Timer_Init(void);
uchar HEX2ASCII(uchar dat);
// void LCD1602_Display_Str(uchar* str);
void LCD12864_Display_Date(uchar *pointer);
/*******************************************************************************
* 函 数 名       : main
* 函数功能       : 主函数
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/
void main()
{    LCD12864_Init() ;
    AT24C02_Init();
    Timer_Init();
    IO2_Init();
    DS1302_Init();
    //HC595_Init();
    delaya_ms(1000);
    Step = 0;
    Step6 = 0;
    Error_Num = 0x00;
	  Error_Num1 =0x00;
    unlock_flag = 0;
    Read_Password();
    while (1)
    {  KeyValue = Key_Scan();
        switch (Step)
        { case 0:
        {   if (UpdateTimeFlag == 1)     //定时1s更新时间
            { UpdateTimeFlag = 0;
                DS1302_GetTime(Now);        //读取DS1302时间
                LCD12864_Display_Date(Now);
            }
            Step0_welcome();//欢迎(待机画面)
            break;
        }
        case 1:
        { Step1_ask_changePassword();//询问是否修改密码(原始密码为6666)
            break;
        }
        case 2:
        {   Step2_judge_changePassword();//判断是否修改密码
            break;
        }
        case 3:
        {   Step3_tips();//提示输入密码
            break;
        }
        case 4:
        {   Step4_inputPassword();//输入密码以*显示
            break;
        }
        case 5:
        { Step5_PasswordComparison();//密码比对,正确就开锁

            break;
        }
        case 6:
        {   Step6_changePassword();//修改密码
            break;
        }
        }
				 if (chaoshi_flag == 1)
        {  LCD12864_WriteCMD(0x01);//清屏
          LCD12864_Display(0x98, "Error 已超时");
          delaya_ms(5000);
		  LCD12864_WriteCMD(0x01);//清屏
		  chaoshi_flag=0;
		  fengming_flag = 1;
        }
				if (fengming_flag == 1)
        {
            u8 i=0;
  			ALARM_ON();         //蜂鸣器响
            Delay_ms(50);  //延时500ms
            ALARM_OFF();        //蜂鸣器灭
            Delay_ms(50);  //延时500ms
		    i++;
		    fengming_flag=0;
        }
    }
}
void Step0_welcome()//欢迎(待机画面)
{    LCD12864_Display(0x8A, "welcome");
      if (KeyValue != 0)    Step = 1;                         //  有按键按下进入下一步
}
void Step1_ask_changePassword()//询问是否修改密码(原始密码为6666)
{   delaya_ms(1000);
    LCD12864_WriteCMD(0x01);//清屏
    LCD12864_Display(0x87, "<");
    LCD12864_Display(0x80, "menu");
    LCD12864_Display(0x90, "Unlock");
    LCD12864_Display(0x98, "New Password");
Step = 2;
}
void Step2_judge_changePassword()   //判断是否修改密码
{  if (KeyValue != 0) //检测是否有键按下
    {if (KeyValue == 5 || KeyValue == 7) //4键或6键按下    4键是开锁,6键是修改密码
        {     if (KeyValue == 5) //确认开锁
            { List1 = 0;
                LCD12864_WriteCMD(0x01);//清屏
                LCD12864_Display(0x90, "Unlock");
                LCD12864_Display(0x97, "<");
                LCD12864_Display(0x98, "New Password");
            }
            Else               //确认修改密码·
            {   List1 = 1;
                LCD12864_WriteCMD(0x01);//清屏
                LCD12864_Display(0x90, "Unlock");
                LCD12864_Display(0x98, "New Password");
                LCD12864_Display(0x9F, "<");
            }
        }
        else
        {   if (List1 == 0) Step = 3;
            else
            {
 Step = 6;
            }
        }
    }
}
void Step3_tips()                 //提示输入密码
{    LCD12864_WriteCMD(0x01);//清屏
	 LCD12864_WriteCMD(0x01);//清屏
     LCD12864_Display(0x90, "Password: ");
     Step = 4;
}
void input_password(bit m)
{   unsigned char t = 0;
	TR1 = 1;      //运行T1
    if (KeyValue != 0)                                   //ok键没有按下
    { if (KeyValue < 8 && pw_num < PassWord_Length)      //1-7按下
        {   INPUT_PW_Tab[pw_num] = KeyValue - 1;       //保存至输入密码数组
            pw_num = pw_num + 1;                       //密码长度+1
  for (t = 0; t < pw_num; t++)    //未到字符串末尾
                if (m == 0)
                { LCD12864_WriteCMD(0x98 + t);    //设定DDRAM地址
                    LCD12864_WriteDAT('*');       //密码隐藏
                }
                else
                {   LCD12864_WriteCMD(0x98 + t);
                    LCD12864_WriteDAT(INPUT_PW_Tab[t] + 0x30);   //显示密码
                }
        }
        else if (KeyValue == 8)                            //删除键按下
        {   LCD12864_WriteCMD(0x01);//清屏
            LCD12864_Display(0x90, "Password: ");
            if (pw_num != 0)
            {   pw_num = pw_num - 1;
                for (t = 0; t < pw_num; t++)    //未到字符串末尾
                    if (m == 0)
                    {   LCD12864_WriteCMD(0x98 + t);    //设定DDRAM地址
                        LCD12864_WriteDAT('*');       //密码隐藏
                    }
                    else
                    {   LCD12864_WriteCMD(0x98 + t);
                        LCD12864_WriteDAT(INPUT_PW_Tab[t] + 0x30);   //显示密码
                    }
            }
            else
            {
                 Step = 0;
            }
        }
        else                          //ok键按下
        {
            if (pw_num == 0)
            {
                Step = 0;
TR1 = 0;      //关闭T1
		        T1_Cnt = 0;
                unlock_flag = 1;
                LCD12864_WriteCMD(0x01);//清屏
                LCD12864_Display(0x98, "Error 未输入密码");
                delaya_ms(5000);
							  LCD12864_WriteCMD(0x01);//清屏
            }
            else
            {
              Input_suc_flag = 1;
                         }
        }
    }
			  TR1 = 0;      //关闭T1
		      T1_Cnt = 0;

}

void Step4_inputPassword()//输入密码以*显示
{
    input_password(0);  //输入密码并以*显示
    if (Input_suc_flag == 1)
    {
        Step = 5;   //密码输入完成进入下一步
        Input_suc_flag = 0;
    }
    Input_suc_flag = 0;                                //清除密码输入完成标志
}
void CipherComparison()
{
    u8 i, j = 0;
    LCD12864_WriteCMD(0x01);//清屏
);
    if (pw_num == PassWord_Length)                    //密码长度比对
    {
        for (i = 0; i < PassWord_Length; i++)           //密码比对
        {
            if (PASSWORD[i] != INPUT_PW_Tab[i])
            { result_flag = 0;				  
                break;                     //密码错误
            }
            else
            {result_flag = 1;                        //密码正确
                pw_num = 0;
            }
            INPUT_PW_Tab[i] = 0XFF;                 //清除密码缓存数组
        }
    }
    else
    { result_flag = 0;
    }
}
void Step5_PasswordComparison()//密码比对
{
    CipherComparison();                                //密码比对
    if (result_flag == 1)                              //密码正确
    {
        LCD12864_WriteCMD(0x01) ;                 //清屏
        LCD12864_Display(0x91, "欢迎小仙女");
        delaya_ms(5000);
  		LCD12864_WriteCMD(0x01);//清屏
        result_flag = 0;
	    Step = 0;
    }
    else                                                //密码错误
    {   LCD12864_WriteCMD(0x01);//清屏
        LCD12864_Display(0x98, "Error 密码错误");
        delaya_ms(2000);
		LCD12864_WriteCMD(0x01);//清屏
	    Error_Num1++;
		if(Error_Num1<3)
				{
					pw_num = 0;
					Step=3;
				}
				else
				{
					Error_Num1=0;
					fengming_flag = 1;
					pw_num = 0;
					Step=0;
				}
    }
}
void Step6_0()
{
    Error_Num1=0;
LCD12864_WriteCMD(0x01);//清屏
    LCD12864_Display(0x90, "Input PassWord:");    //12864显示:输入密码
    Step6 = 1;
    pw_num = 0;
}
void Step6_1()
{
    input_password(0);                  //   输入密码并以*显示
    if (Input_suc_flag == 1)            //密码输入完成
    {
        Step6 = 2;                //
        Input_suc_flag = 0;       //清除密码输入完成标志
    }
}
void Step6_2()                //
{
    CipherComparison();                //密码比对
    Step6 = 3;
}
void Step6_3()                //
{
    if (result_flag == 0)      //        密码错误
    {
        if (Error_Num < 2)          //输出错误次数小于3
        {   pw_num = 0;
            Error_Num++;
            LCD12864_WriteCMD(0x01);//清屏
            LCD12864_Display(0x90, "请重新输入");
            delaya_ms(2000);
            Step6 = 0;
        }
        else                          //密码错误次数大于3
        {
            Error_Num = 0;
            LCD12864_Display(0x90, "解锁失败");
            delaya_ms(2000);
            Step = 0;
            fengming_flag = 1;
        }
    }
    else                                                       //密码正确
    {
        LCD12864_WriteCMD(0x01);//清屏
        LCD12864_Display(0x90, "New PassWord:");
        pw_num = 0;
Error_Num=0;
        Step6 = 4;
    }
}
void Step6_4()
{
    input_password(1);                             //输入密码并显示
    if (Input_suc_flag == 1)               //输入完成
    {
        Input_suc_flag = 0;
        LCD12864_WriteCMD(0x01);//清屏
        LCD12864_Display(0x90, "OK!");
        pw_num = 0;
        Step6 = 5;
    }
}
void Step6_5()//保存新密码
{
    unsigned char j;
    delaya_ms(100);
    for (j = 0; j < PassWord_Length; j++)
    {
        PASSWORD[j] = INPUT_PW_Tab[j];                       //读取密码
        AT24C02_WriteByte(j, INPUT_PW_Tab[j]);                //保存密码至EEPROM
        delaya_ms(100);
    }
    Step6 = 0;
    Step = 0;
}
void Step6_changePassword()//修改密码
{
    switch (Step6)
    {
    case 0:
    {
        Step6_0();
        break;
    }
    case 1:
    {
        Step6_1();
        break;
    }
    case 2:
    {
        Step6_2();
        break;
    }
    case 3:
    {
        Step6_3();
        break;
    }
    case 4:
    {
        Step6_4();
        break;
    }
    case 5:
    {
        Step6_5();
        break;
    }
    }
}
void Read_Password()
{   unsigned char j;
    if (Load_first_flag == 0)            //初次运行
    {
        Load_first_flag = 1;
        for (j = 0; j < PassWord_Length; j++)
        {
            AT24C02_WriteByte(j, 6);             //写默认密码6666至EEPROM
            delaya_ms(100);
        }
    }
    else
    {
        for (j = 0; j < PassWord_Length; j++) //读取密码
        {
            PASSWORD[j] = AT24C02_ReadByte(j);
        }
    }
}
/***********************************************
函数名称:LCD1602_Display_Date
功    能:lcd1602显示时钟
入口参数:pointer指针地址
返 回 值:无
备    注:1602LCD显示的为字符,必须将整数转换成
          相应的字符,否则显示乱码。
************************************************/
void LCD12864_Display_Date(uchar *pBuf)
{
    LCD12864_CheckBusy();                //检测忙信号
    LCD12864_WriteCMD(0x80);   //写入地址
    LCD12864_Display_Str("20");

    LCD12864_WriteDAT(HEX2ASCII((*(pBuf + 6) & 0xf0) >> 4)); //年高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 6) & 0x0f));     //年低位

    LCD12864_CheckBusy();
    LCD12864_WriteDAT('-');                             //“-”

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII((*(pBuf + 4) & 0xf0) >> 4)); //月高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 4) & 0x0f));     //月低位

    LCD12864_CheckBusy();
    LCD12864_WriteDAT('-');                             //“-”

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII((*(pBuf + 3) & 0xf0) >> 4)); //日高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 3) & 0x0f));     //日低位


    LCD12864_CheckBusy();
    LCD12864_WriteCMD(0x85);
    LCD12864_CheckBusy();
    LCD12864_Display_Str("星期");                             //“-”
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 5) & 0x0f));     //星期

    LCD12864_CheckBusy();
    LCD12864_WriteCMD(0x90);
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII((*(pBuf + 2) & 0xf0) >> 4)); //时高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 2) & 0x0f));     //时低位

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(':');                             //“:”

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII((*(pBuf + 1) & 0xf0) >> 4)); //分高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(*(pBuf + 1) & 0x0f));     //分低位

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(':');                             //“:”

    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII(((*pBuf) & 0xf0) >> 4)); //秒高位
    LCD12864_CheckBusy();
    LCD12864_WriteDAT(HEX2ASCII((*pBuf) & 0x0f));       //秒低位
}
/***********************************************
函数名称:HEX2ASCII
功    能:十六进制转ASCII函数
入口参数:dat:十六进制数
返 回 值:转换成的ASCII值。
备    注:无
************************************************/
uchar HEX2ASCII(uchar dat)
{
    dat &= 0x0f;
    if (dat <= 9)    return (dat + '0'); //数字0~9
    return (dat - 10 + 'A');                    //字母A~F
}
/***********************************************
函数名称:Timer0_Init
功    能:定时器0初始化函数
入口参数:无
返 回 值:无
备    注:定时初值可以使用stc下载软件中的
               定时初值自动生成功能。
************************************************/
void Timer_Init(void)
{
    AUXR &= 0x3f; //T0时钟12T模式
    TMOD &= 0x11; //T0,1工作于十六位定时方式

    //使用位操作,避免对其他定时器产生影响
    TL0 = 0x00;         //定时初值50ms   11.0592MHz
    TH0 = 0x4c;
    TL1 = 0x00;         //定时初值50ms   11.0592MHz
    TH1 = 0x4c;	
    TF0 = 0;            //清除TF0标记
    ET0 = 1;          //使能T0中断
    TF1 = 0;            //清除TF1标记
    ET1 = 1;          //使能T1中断	
    EA = 1;             //使能总中断
    TR0 = 1;      //运行T0
  	TR1 = 0;      //关闭T1
}
/***********************************************
函数名称:Timer0_ISR
功    能:定时器0中断服务函数
入口参数:无
返 回 值:无
备    注:无
************************************************/
void Timer0_ISR(void) interrupt 1
{
    //static unsigned char T0_Cnt = 0;
    //使用静态计数器,每次调用该中断函数时,
    //静态计数器都能保持上一次的计数值。
    //如果不使用静态计数器,每次调用该中断函数时
    //该计数器初值都是0,计数值就无法累加。
    TL0 = 0x00;         //定时初值50ms   11.0592MHz
    TH0 = 0x4c;
    T0_Cnt++;
    if (T0_Cnt == 20)       //定时1000ms
    {
        T0_Cnt = 0;
        UpdateTimeFlag = 1; //更新时间标记有效
    }
}
/***********************************************
函数名称:Timer1_ISR
功    能:定时器0中断服务函数
入口参数:无
返 回 值:无
备    注:无
************************************************/
void Timer1_ISR(void) interrupt 3
{
    static unsigned char T1_Cnt = 0;
    //使用静态计数器,每次调用该中断函数时,
    //静态计数器都能保持上一次的计数值。
    //如果不使用静态计数器,每次调用该中断函数时
    //该计数器初值都是0,计数值就无法累加。
    TL1 = 0x00;         //定时初值50ms   11.0592MHz
    TH1 = 0x4c;
    T1_Cnt++;
    if (T1_Cnt == 50)       //定时
    {
      T1_Cnt = 0;
			chaoshi_flag=1;
			Step=0;
			TR1=0;
    }
}

2.4实验现象

  1. 将线连接好并将程序下载后,可以看到lcd12864上第一排显示当时的年、月、日、星期,第二排显示当时的时、分、秒,第三排显示welcome

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

2.此时可以按下任意键继续,lcd12864屏显示菜单栏中开锁和修改密码两个选项

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

3.在这里我们可以“4”或“6”选择开锁或者是修改密码。如果这里选择的开锁,按下确定键,此时会提示输入密码,初始密码默认为6666。

微机课设 | 基于STC15单片机的简易数字密码锁设计

 微机课设 | 基于STC15单片机的简易数字密码锁设计

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

4.然后按下确定键,如果密码正确则会显示欢迎小仙女

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

5.如果输入密码错误则会提示Error 密码错误

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

 6.如果输入密码时间超过规定时间(25s)则会显示Error 已超时,并且会启动蜂鸣器

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

7.如果输入密码错误超过三次,则会启动蜂鸣器,并且返回到待机画面

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

8..如果需要修改密码,则在菜单页面选择New  password

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

9.这里会提示输入原始密码

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

10.输入原始密码后按下确认键,如果密码正确会提示输入新密码

微机课设 | 基于STC15单片机的简易数字密码锁设计

 

11.输入密码后按下确认键,会提示OK并返回到待机画面

微机课设 | 基于STC15单片机的简易数字密码锁设计

//—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— // 

一些心得:

写程序之前我花了一个多小时的时间理清密码锁所需功能、即将用到的模块、各个步骤之间的关系,画出来可执行性强的程序框图,定义了即将用到的步骤函数。在做设计的过程中,我每一步要做什么,每一步要完成什么任务都有着清晰的思路及逻辑块,在程序测试的过程中分模块debug,使得整体程序的编写及查错简单清晰了许多。

程序的编写并不是特别容易,虽然上学期学了微机课程,但是实际操作起来比理论学习复杂了很多。由于模块庞大,密码锁的程序我是先写出了主要流程:开屏欢迎-菜单选择开锁或者修改密码-输入密码-密码比对-开锁,然后添加了修改密码(输入旧密码-密码对比-正确则输入新密码-存储密码-返回)、密码输入错误超过三次报警提示、密码输入时间超过指定限制报警提示、开屏显示日期(年、月、日、时、分、秒)等功能。分模块、分层次编写使得我的整体编写思路清晰、代码简单、逻辑性强、出错较少。

因为我之前对KEIL5的编程环境有过一些学习,所以对分模块编程、.H文件函数编写及调用、芯片引脚规划有一定的了解及运用能力,这给我的课程设计减小了一点压力。但是我较少使用KEIL5,对程序的实际编写还不够熟悉,编程过程中遇到了很多ERROR及WARNING,例如重复调用、重复编写、中断函数和主函数调用函数冲突、逻辑错误、缺少清屏步骤等,好在通过一次次的逻辑检查及查询CSDN上优秀博主的例程和错误分析,我学会了很多debug技巧,也解决了一些常见错误如逻辑值定义、flag设置及清零等问题。

答辩之后:

答辩的时候,老师说数字密码锁比较简单,只是一些按键逻辑,确实如此,多花些功夫,是能够将密码锁做的更加完善、功能更加复杂的。

我用的这个板子只有3个独立按键和6个行列按键,所以数字我只设置到了0-6,答辩的时候,老师提示我们不能被按键数量限制,比如可以利用加减运算将6个按键扩展成更多的按键。

我暂时没能够想出如何判断按下一个键是要输入还是要做加减运算,我想的是通过长按和短按代表不同的数值,可以将数字范围扩展为两倍,程序里面只需要加一个延时再读案件返回数值的判断函数就行了。(或许加减运算那里也可以通过长按和短按来区分?)

密码锁其实还存在一些问题:

1.密码输入时间超过25s则警告,按照设想,是每次输入时间都控制在25s内,但是运行时是每次输入密码时间累加至25s时都会跳出,导致有时候刚要输密码就跳出了。应该是定时器中断里面那个静态计数值没有清零,我之前设置了清零标志但是程序跑不动,我还没有进一步找到问题。

2.有时候用着用着乱码,应该是有些按键我没有考虑到,按键太多了如果不按照上面规定的每个步骤按规定的键就会乱码。文章来源地址https://www.toymoban.com/news/detail-441991.html

到了这里,关于微机课设 | 基于STC15单片机的简易数字密码锁设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STC15单片机-低功耗设计

    STC15省电模式(数据手册有介绍) STC15系列单片机可以运行3种省电模式以降低功耗,它们分别是: 低速模式 , 空闲模式 和 掉电模式 。 正常工作模式下,STC15系列单片机的典型功耗是2.7mA ~7mA,而掉电模式下的典型功耗是0.1uA,空闲模式下的典型功耗是1.8mA 低速模式由时钟分

    2024年02月05日
    浏览(79)
  • 【STC15单片机】动态数码管

    目录 点亮一位数码管 动态数码管 100s倒计时 动态数码管封装代码 段选:选中哪一位数码管 位选:选中的数码管要显示的内容 这是我对段选位选的理解,就是选中某个位置,赋值字形码,显示想要的图形 如果只想让第一个数码管显示,就只需要让com1 = 1即可,其他comx都=0 如

    2024年02月13日
    浏览(38)
  • STC15系列单片机学习6:外部中断

    外部中断,就是通过单片机IO引脚电平的变化触发的中断。 STC15系列单片机的外部中断源一共有5个,分别是外部中断0(INT0)、外部中断1(INT1)、外部中断2(INT2)、外部中断3(INT3)、外部中断4(INT4);当然不是所有的STC15系列单片机都有着5个外部中断。 中断源 触发行为

    2024年03月12日
    浏览(146)
  • 【STC15单片机】简单的矩阵键盘代码

    单片机型号说明:IAP15F2K61S2 新建工程时单片机型号选择 STC15F2K60S2 51单片机矩阵键盘代码 本程序烧写到51单片机应该是正常使用的,手头没有51开发板了,暂时没测试 这个程序烧写到15单片机,前两列按键不能正常使用 只需要在判断第一列按键那部分程序,前面加上P42 = 0;

    2024年02月05日
    浏览(74)
  • STC15系列单片机学习4:串口通讯

    在使用单片机的串口前,得先知道所使用的单片机有几个串口,再结合你的硬件电路图来使用哪个串口。 以下是STC15各系列单片机的串口数量,STC15W4K32S4系列有4个串口 工作模式0:同步移位寄存器(官方建议初学者不学) 工作模式1:8位串口,波特率可变 工作模式2:9位串口

    2024年04月13日
    浏览(39)
  • STC15F100E单片机模拟串口

    STC15F100系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,新一代8051单片机,指令代码完全兼容传统8051,但是速度快6-12倍。 内部集成R/C时钟,5MHz~35MHz宽范围可设置,可以省掉外部晶振。 内部集成复位电路,可省掉外部复位电路。 6个通用I/O口,支持四种模式:准双

    2024年02月20日
    浏览(41)
  • STC15W104 8脚单片机串口下载程序

    单片机串口下载是一种常见的单片机程序下载方式,它通过串口线连接单片机的串口引脚和电脑的串口接口实现。下面是单片机串口下载的基本原理和操作方法: 确定下载模式:大多数单片机芯片都支持串口下载模式,需要在程序中设置下载模式。 连接串口:使用串口线连

    2024年02月13日
    浏览(40)
  • STC15系列单片机:定时器/计数器16位自动重装载模式

    STC15系列单片机内部有5个16位定时器/计数器,分别是T0、T1、T2、T3、T4。 定时器与计数器,东西还是同一个东西,只是用法和功效不一样,就好比黄瓜,既可以内服也可以外敷,黄瓜还是那个黄瓜,作用就不一样了。 就拿T0来说,T0用于定时,那T0就是定时器,如果T0用于计数

    2024年01月25日
    浏览(49)
  • 学习笔记|ADC反推电源电压|扫描按键(长按循环触发)|课设级实战练习|STC32G单片机视频开发教程(冲哥)|第十八集:ADC实战

    19.5.4 利用ADC第15通道(内部1.19V参考信号源)测量外部电压或电池电压 注意:这里的1.19V不是ADC 的基准电压ADC-Vref+,而是ADC15通道的固定输入信号源,1.19V STC32G系列ADC的第15通道用于测量内部参考信号源,由于内部参考信号源很稳定,约为1.19V,且不会随芯片的工作电压的改变而变化

    2024年02月07日
    浏览(47)
  • 单片机课设———基于51单片机的智能风扇控制器(汇编语言)

    说明:单片机芯片为AT89C52,使用普中开发板,用汇编语言编程。 系统实现了对风扇的控制: (1)控制器面板包括:启/停键、模式选择键、风速键和类型选择键。 (2)模式分为:手动模式和自动温控模式。在温控模式下,风速键和类型选择键无效。 (3)风速分为:强、中

    2024年02月11日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包