模块化编程

  • 传统方式编程:所有的函数均放在main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路
  • 模块化编程:把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include "XXX.h"文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等

模块化编程框图

模块化编程注意事项

  • .c文件:函数、变量的定义
  • .h文件:可被外部调用的函数、变量的声明
  • 任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)
  • 使用到的自定义函数的.c文件必须添加到工程参与编译
  • 使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)

C预编译

  • C语言的预编译以#开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)

  • 此外还有#ifdef,#if,#else,#elif,#undef等

LCD1602调试工具

  • 使用LCD1602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。
  • 使用者只需要知道所提供函数的作用和使用方法就可以很容易的使用LCD1602。

矩阵键盘

介绍

  • 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式
  • 采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态

扫描的概念

  • 数码管扫描(输出扫描)
    原理:显示第1位→显示第2位→显示第3位→……,然后快速循环这个过程,最终实现所有数码管同时显示的效果
  • 矩阵键盘扫描(输入扫描)
    原理:读取第1行(列)→读取第2行(列) →读取第3行(列) → ……,然后快速循环这个过程,最终实现所有按键同时检测的效果
  • 以上两种扫描方式的共性:节省I/O口

原理

无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的I/O口是否为低电平。独立键盘有一端固定为低电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机I/O口相连,因此在检测时需人为通过单片机I/O口送出低电平。检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。当然我们也可以将行线置低电平,扫描列是否有低电平。这就是矩阵键盘检测的原理和方法。

程序

Matrixkey.c文件

#include <REGX52.H>
#include"Delay.h"

/**
  * @brief (介绍)矩阵键盘读取按键键码
  * @param (参数)无
  * @retval (返回值)KeyNumber  按下按键的键码值
        如果按键按下不放,程序会停留在此函数,松手一瞬间返回按键码,没有按键按下时返回0。
  */

unsigned char MatrixKey()
{
    unsigned char KeyNumber =0;
    //按列扫描
    P1=0xFF;//全部给高电平
    P1_3=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
     
    P1=0xFF;
    P1_2=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}

    P1=0xFF;
    P1_1=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}

    P1=0xFF;
    P1_0=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}

    return KeyNumber;

}

main.c文件

#include <REGX52.H>
#include"Delay.h"
#include"LCD1602.h"
#include"MatrixKey.h"

unsigned char KeyNum;
void main()
{
    LCD_Init();
    LCD_ShowString(1,1,"MatrixKey");//LCD显示
    while(1)
    {
        KeyNum = MatrixKey();
        if(KeyNum)//相当于KeyNum!=0
        {
                LCD_ShowNum(2,1,KeyNum,2);//LCD第2行第1例显示KeyNum范围两位数

        }
    }

}

矩阵键盘密码锁

main.c文件

#include <REGX52.H>
#include"Delay.h"
#include"LCD1602.h"
#include"MatrixKey.h"

unsigned char KeyNum;
unsigned int PassWord,count;
void main()
{
    LCD_Init();
    LCD_ShowString(1,1,"PassWord:");
    while(1)
    {
        KeyNum = MatrixKey();
        if(KeyNum)
        {        if(KeyNum<=10)             //如果S1~S10按键按下,输入密码
                {
                    if(count<4)              //如果输入次数小于四
                    {
                            PassWord*=10;            //密码左移一位
                            PassWord+=KeyNum%10;     //10%10=0,获取一位密码
                                count++;    //计次加一
                    }
                    LCD_ShowNum(2,1,PassWord,4);//更新显示
                }
                if(KeyNum==11)                //如果S11按下,确认
                {
                    if(PassWord==2345)    //如果密码等于正确密码
                    {
                        LCD_ShowString(1,14,"OK ");//显示OK
                        PassWord=0;//密码清零
                        count=0;//计次清零
                        LCD_ShowNum(2,1,PassWord,4);//更新显示

                    }else
                        {
                            LCD_ShowString(1,14,"ERR");//否则显示ERR
                            PassWord=0;//密码清零
                          count=0;//计次清零
                            LCD_ShowNum(2,1,PassWord,4);//更新显示
                         }

                }
            if(KeyNum==12)  //如果S12按键按下,取消
            {
                 PassWord=0;//密码清零
                 count=0;//计次清零
                 LCD_ShowNum(2,1,PassWord,4);//更新显示
            }
        }
    }

}

参考资料

51单片机入门教程-2020版 程序全程纯手打 从零开始入门\_哔哩哔哩\_bilibili

最后修改:2023 年 10 月 21 日
如果觉得我的文章对你有用,请随意赞赏