单片机学习小组
直播中

小组店小二

9年用户 884经验值
擅长:可编程逻辑 电源/新能源 MEMS/传感技术 测量仪表 嵌入式技术 制造/封装 模拟技术 连接器 EMC/EMI设计 光电显示 存储技术 EDA/IC设计 处理器/DSP 接口/总线/驱动 控制/MCU RF/无线
私信 关注

矩阵按键是怎样控制数码管显示的

矩阵按键的原理是什么?
矩阵按键是怎样控制数码管显示的?

回帖(1)

杨勇

2022-2-23 14:16:56
矩阵按键控制数码管显示


矩阵按键和独立按键很不一样,独立按键一段直接与I/O口连接,因此原本为高电平,另一端接地,因此只要检测I/O口是否为低电平就可以检测按键是否被按下。
但是矩阵按键两端同时连接I/O口,因此检测较为复杂。
原理如下:

图中S16按键同时连接P10和P14,因此检测的时候只要先人为给P10一个高电平,P14一个低电平,之后再重复检测P10是否变为低电平就可以检测到S16是否被按下。其他按键原理相同,I/O口高低电平位置可以互换,但是要保证一个是高一个是低。

实验源代码:



晶振11.0592
矩阵键盘为4x4
肉眼的视觉暂留效果捕捉时间为1000ms~2000ms,这个大家可以直接用数码管做实验得出


#include
#define uchar unsigned char
#define uint unsigned int

***it jz_key1 = P1^0;        //矩阵按键位定义
***it jz_key2 = P1^1;
***it jz_key3 = P1^2;
***it jz_key4 = P1^3;
***it jz_key5 = P1^4;
***it jz_key6 = P1^5;
***it jz_key7 = P1^6;
***it jz_key8 = P1^7;
***it led2 = P2^2;                //数码管显示位选控制
***it led3 = P2^3;
***it led4 = P2^4;
uchar code duanxuan[] = {0x3f,0x06,0x5b,0x4f,          //0,1,2,3
                                                 0x66,0x6d,0x7d,0x07,          //4,5,6,7
                                                  0x7f,0x6f,0x77,0x7c,          //8,9,A,B
                                                 0x39,0x5e,0x79,0x71};          //C,D,E,F                段选
                                                
uchar code juzhen[] = {0xf7,0xfb,0xfd,0xfe};          //矩阵按键检测时,一列输入低电平

void delay_xms(uint m)          //延时操作
{
        int i;
        for(;m>0;m--)
                for(i=110;i>0;i--);
}

void display(int i)         //数码管显示函数
{
        switch(i)
        {
                case(0):led2=1,led3=1,led4=1;break;
                case(1):led2=0,led3=1,led4=1;break;
                case(2):led2=1,led3=0,led4=1;break;
                case(3):led2=0,led3=0,led4=1;break;
                case(4):led2=1,led3=1,led4=0;break;                        
                case(5):led2=0,led3=1,led4=0;break;
                case(6):led2=1,led3=0,led4=0;break;
                case(7):led2=0,led3=0,led4=0;break;
        }
}

void keyscan(int n)                  //按键检测
{
        int m;                                  //用于计算P0段选
        while(n<4)                          //n小于4,重复四次检测(共4列)
        {
                m = n;                          //m与n相等,可以调整P0段选随着n的变化而变化,m作为间接变量
                P1 = juzhen[n];          //给矩阵键盘的一列输入低电平,不同的n对应不同的低电平列
                if(jz_key5==0)          //行检测
                {
                        delay_xms(10);        //去除抖动
                        if(jz_key5==0)
                        {
                                P0 = duanxuan[12+m];  //对于不同n情况下,P0段选做出不同反应,m用于调整
                        }
                        while(!jz_key5);
                }
                if(jz_key6==0)
                {
                        delay_xms(10);
                        if(jz_key6==0)
                        {
                                P0 = duanxuan[8+m];
                        }
                        while(!jz_key6);
                }
                if(jz_key7==0)
                {
                        delay_xms(10);
                        if(jz_key7==0)
                        {
                                P0 = duanxuan[4+m];
                        }
                        while(!jz_key7);
                }
                if(jz_key8==0)
                {
                        delay_xms(10);
                        if(jz_key8==0)
                        {
                                P0 = duanxuan[0+m];
                        }
                        while(!jz_key8);
                }
                n++;      
        }      
}

void Init()           //初始化操作
{
        TMOD = 0X01;                   //定时器模式
        TH0 = (65536-1000)/256;//计数器高八位赋初值
        TL0 = (65536-1000)%256;//计数器低八位赋初值
        EA = 1;                                   //中断总开关
        ET0 = 1;                           //T0定时器中断开关
}

int i=0;           //全局变量i,同时在main和中断函数起作用
void main()
{
        P0 = 0X0;  //没按按键前,数码管不显示任何数字
        Init();
        while(1)
        {
                TR0 = 1;
                keyscan(0);
        }
}

void time_T0() interrupt 1
{
        TH0 = (65536-1000)/256;//计数器高八位赋初值
        TL0 = (65536-1000)%256;//计数器低八位赋初值
        display(i);                           //数码管独立开主程序显示
        i = (i+1)%8;                   //数码管显示位置控制
}

这个实验中,采用了数码管显示和主程序独立开来的方式,这样在按键检测时按下按键不会影响到数码管的显示。如果不这样,按下按键时,数码管display(i)中的i在那一瞬间是固定的,因而数码管的动态显示会在那一瞬间卡住,如果将显示独立成很短时间的中断来显示,那样就独立开了显示和按键检测,互不影响。

第二是在keyscan函数中使用了while循环和引入了一个间接变量m,这样不同的P1对应不同列的低电平就可以做出不同的按键检测,同时用m对应不同的n情况,对P0的段选做出不同的反应,大大优化了代码。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分