【AT89C52单片机项目】数字密码锁设计

  • 实验目的

使用单片机设计数字密码锁。

  • 实验仪器

一套STC89C52RC开发板套件,包括STC89C52RC开发板,以及USB烧录线。

  • 设计要求

1、有设置密码、开锁工作模式;

2、可以每次都设置密码,也可以设置一次密码多次使用。

  • 实验原理

本实验所需要的主要硬件电路介绍

1)、矩阵按键

矩阵键盘扫描原理:

1、行线输出全为0;

2、读入列线值;

3、列线输出上次读入的值

4、读入行线值

5、组合2种读入值

优点:m*n个按键值需要一次反转(2次输入输出)就可以检测到结果,比行列扫面简单。

  • 实验流程
  1. 根据教材进行学习数码管显示控制,本项目单片机为八段共阴数码管,段码为{ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f},分别表示0~9
  2. 根据教材进行学习矩形键盘、矩形键盘的反转扫描、矩形键盘密码锁的样例,根据矩形键盘密码锁样例改写代码。
  3. 将程序烧录进入单片机,并且把单片机中USB232连接OFF。
  • 实验结果

输入密码"12345678"后,数码管显示open。

|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| | |

输入其他密码后,数码管显示Err。

|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| | |

  • 代码
cpp 复制代码
#include <reg52.h>

#define DataPort P0   //定义数码管显示数据端口
#define KeyPort P3    //定义矩阵按键的数据端口
sbit LATCH1 = P2 ^ 6;  //定义锁存使能端口  段锁存
sbit LATCH2 = P2 ^ 7;  //定义锁存使能端口  位锁存

unsigned char code DuanMa[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极数码管段码表,包含字母abcdef

unsigned char code WeiMa[] = { 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};  //位码表

unsigned char TempData[8];   //用来存放数码管数据
unsigned char Data[8];
unsigned char password[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };  //设置密码
void DelayUs2x(unsigned char t);  //延迟函数
void DelayMs(unsigned char t);  //毫秒延迟函数
void Display(unsigned char FirstBit, unsigned char Num);  //数码管显示函数
unsigned char KeyScan(void);  //键盘扫描函数,使用行列逐级扫描法
unsigned char KeyPro(void);  //把键盘扫描结果转换为数字的函数
main()
{
    unsigned char num = 0, i = 0, j; //定义并初始化变量
    unsigned char Flag = 0;
    while (1)
    {
        num = KeyPro();  //获取按键数字
        if (num != 0xff) //如果按键状态发生变化
        {
            if (i == 0)
            {
                for (j = 0; j < 8; j++) //初始化数码管数据,清屏
                {
                    TempData[j] = 0xff; 
                }
            }

            if (i < 8)
            {
                Data[i] = DuanMa[num]; //把按键值输入到临时数组中
                for (j = 0; j <= i; j++)   //通过一定顺序把临时数组中
                {                       //的值赋值到显示缓冲区,从右往左输入
                    TempData[7 - i + j] = Data[j]; //数字从数码管右侧逐渐出现
                }
            }

            i++;   //输入数值累加
            if (i == 9) //如果密码输入完毕
            {
                i = 0; //初始化变量i,以便之后可以重新输入密码
                Flag = 1;  //先把比较位置1
                for (j = 0; j < 8; j++)  //循环比较8个数值
                {                       //如果有一个不等 则最终Flag值为0
                    Flag = Flag && (Data[j] == DuanMa[password[j]]);
                }    //比较输入值和已有密码

                for (j = 0; j < 8; j++) // 清屏
                {
                    TempData[j] = 0xff;
                }

                if (Flag)
                {
                    TempData[0] = 0x3f;//O
                    TempData[1] = 0x73;//P
                    TempData[2] = 0x79;//E
                    TempData[3] = 0x54;//n
                    for (j = 4; j < 8; j++)
                    {
                        TempData[j] = 0x00; //除了open后面不显示
                    }
                }

                else
                {
                    TempData[0] = 0x79;//E
                    TempData[1] = 0x50;//r
                    TempData[2] = 0x50;//r
                    for (j = 3; j < 8; j++)
                    {
                        TempData[j] = 0x00;
                    }
                }
            }
        }

        Display(0, 8);
        //DelayMs(1000);
    }
}

void DelayUs2x(unsigned char t)
{
    while (--t)
    {

    }
}
void DelayMs(unsigned char t)
{
    while (--t)
    {
        DelayUs2x(245);
        DelayUs2x(245);
    }
}
void Display(unsigned char FirstBit, unsigned char Num)
{
    unsigned char i;
    for (i = 0; i < Num; i++)
    {
        DataPort = 0;  //清空数据,防止有交替重影
        LATCH1 = 1;
        LATCH1 = 0;

        DataPort = WeiMa[i + FirstBit]; //取位码
        LATCH2 = 1;  //位锁存
        LATCH2 = 0;

        DataPort = TempData[i];  //取显示数据,段码
        LATCH1 = 1;  //段锁存
        LATCH1 = 0;

        DelayUs2x(200);  //扫描间隙延时,时间太长会闪烁
    }                   //太短会造成重影
}

unsigned char KeyScan(void)  //键盘扫描函数,使用行列逐级扫描法
{
    unsigned char Val;
    KeyPort = 0xf0;  //高四位 置高电平,低四位 置低电平
    if (KeyPort != 0xf0)  //如果有按键按下
    {
        DelayMs(10);  //去抖

        if (KeyPort != 0xf0)
        {  //如果有按键按下
            KeyPort = 0xfe; //检测第一行
            if (KeyPort != 0xfe)
            {
                Val = KeyPort & 0xf0;
                Val += 0x0e;
                while (KeyPort != 0xfe) ;
                DelayMs(10); //去抖
                while (KeyPort != 0xfe) ;
                return Val;
            }

            KeyPort = 0xfd; //检测第二行
            if (KeyPort != 0xfd)
            {
                Val = KeyPort & 0xf0;
                Val += 0x0d;
                while (KeyPort != 0xfd) ;
                DelayMs(10);  //去抖
                while (KeyPort != 0xfd) ;
                return Val;
            }

            KeyPort = 0xfb;  //检测第三行
            if (KeyPort != 0xfb)
            {
                Val = KeyPort & 0xf0;
                Val += 0x0b;
                while (KeyPort != 0xfb) ;
                DelayMs(10); //去抖
                while (KeyPort != 0xfb) ;
                return Val;
            }

            KeyPort = 0xf7; //检测第四行
            if (KeyPort != 0xf7)
            {
                Val = KeyPort & 0xf0;
                Val += 0x07;
                while (KeyPort != 0xf7) ;
                DelayMs(10); //去抖
                while (KeyPort != 0xf7) ;
                return Val;
            }
        }
    }
    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;
    }
}
相关推荐
honey ball1 小时前
仪表放大器AD620
运维·单片机·嵌入式硬件·物联网·学习
luckyluckypolar1 小时前
STM32 -中断
stm32·单片机·嵌入式硬件·物联网
启明云端wireless-tag6 小时前
ESP32无线WiFi蓝牙SOC,设备物联网通信方案,启明云端乐鑫代理商
嵌入式硬件·物联网·wifi·esp32·乐鑫·wifi模组
@@庆7 小时前
stm32 PWR电源控制(修改主频&睡眠模式&停机模式&待机模式)
stm32·单片机·嵌入式硬件
JT灬新一7 小时前
STM32巡回研讨会总结(2024)
stm32·单片机·嵌入式硬件
爱桥代码的程序媛7 小时前
鸿蒙OpenHarmony【轻量系统芯片移植案例】标准系统方案之瑞芯微RK3568移植案例
嵌入式硬件·harmonyos·鸿蒙·鸿蒙系统·移植·openharmony·鸿蒙开发
Whappy0018 小时前
51单片机-DA(数字转模拟)
单片机·嵌入式硬件·51单片机
鸽子汤1978 小时前
想高效开发?从文件系统开始着手。。。
嵌入式硬件·物联网·硬件工程
Whappy0018 小时前
51单片机-AD(模拟信号转数字信号)-实验()
单片机·嵌入式硬件·51单片机
redcocal18 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘