单片机——矩阵按键模块

主要目的
学会按键扫描
1.延时函数
延时函数部分详见链接: 单片机控制一盏灯的亮与灭程序解释

 void delay (uint k)		   //定义延时函数
 {
    
    
 uint i,j;
 for(i<0;i<k;i++)
    {
    
    
	for(j=0;j<113;j++)
	  {
    
    
	   ;
	  }
    }
 }

这个程序里面的延时函数的目的是按键消抖。
2.按键扫描模块
这是本次实验的重点,将详细介绍。
先来观察矩阵按键模块的连接
在这里插入图片描述
总共8个口。
先实现关于列的扫描,设置初始值(0xf0),从高到低为

端口 Value
P3.7 1
P3.6 1
P3.5 1
P3.4 1
P3.3 0
P3.2 0
P3.1 0
P3.0 0

那么当按下按键0,4,8,c时,P3.4变成了0,于是P3就变成了0xe0

端口 Value
P3.7 1
P3.6 1
P3.5 1
P3.4 0
P3.3 0
P3.2 0
P3.1 0
P3.0 0

从而由0xe0我们可以判断是那一列按键按下,但还是不知道具体是哪一个按键按下,于是我们需要继续进行行扫描。
此时初始化P3

端口 Value
P3.7 0
P3.6 0
P3.5 0
P3.4 0
P3.3 1
P3.2 1
P3.1 1
P3.0 1

在这里插入图片描述
同时现在当按键0按下后

端口 Value
P3.7 0
P3.6 0
P3.5 0
P3.4 0
P3.3 1
P3.2 1
P3.1 1
P3.0 0

经过行列扫描之后就可以确定具体是哪个按键按下,有了上面的基础之后,我们来学习按键扫描的程序。

void keyscan()   //这个实验的重点
 {
    
     uchar a; 
   P3=0xf0;
   if(P3!=0xf0)
     {
    
    
	  delay(10);
	  if(P3!=0xf0)
	  {
    
    
	   P3=0xf0;		  //进行列扫描
	   switch(P3)
	   {
    
    
	   case(0xe0):keynumber=0;break;	//11100000
	   case(0xd0):keynumber=1;break;//11010000
	   case(0xb0):keynumber=2;break;//10110000
	   case(0x70):keynumber=3;break;//01110000
	   }
	    P3=0x0f;
	   switch(P3)
	   {
    
    
	   case(0x0e):keynumber=keynumber;break;   //switch case后面是冒号
	   case(0x0d):keynumber=keynumber+4;break;
	   case(0x0b):keynumber=keynumber+8;break;
	   case(0x07):keynumber=keynumber+12;break;
	   }
	   
	  while ((a<50)&&(P3!=0x0f))
	  {
    
    
	  delay(10);
	  a++ ;
	  }	
	  }

	 }
   
  
 }

程序的逻辑是
让P3的高四位为0,进行列检测,为什么是列检测呢,很简单,因为区分不出行。
如果按键按下,延时10ms,判断是不是按键抖动,延时之后继续判断,发现仍然不为0xf0,说明按键确实按下了,然后还是给P3幅初始值0xf0,接下来进行switch,case,不同P3情况下,对设置的keynumber进行赋值,记得每一个case结束要加break。
只有列扫描,无法判断是哪个按键按下,接下来进行行扫描。
基本原理和上面一样,但是注意按键值的变化。
最后当两个情况同时不成立后跳出循环。这两个情况就是a>50和P3=0xf0,具体解释就是a>50,按键还没有松开,就认为松开了,P3=0xf0按键按下之后松开了。
3.数码管显示模块
这一部分也相对简单,我的博客里面也有相应的博文。在这里主要就是P0口接的是数码管。这里进行段选和位选。段选是根据keynumber的值,位选这里选了六个数码管,则对应11000000,再转换为16进制。
在这里插入图片描述

 void display(uchar num)
 {
    
    
   P0=table[num];
   duan=1;
   duan=0;
   P0=0xc0;//11000000
   wei=1;
   wei=0;
 }

4.主函数
主要是设置段和位初始状态,之后调用前面的按键扫描和数码管显示模块。

 void main()
 {
    
    
 duan=0;
 wei=0;
 while(1)
 {
    
    
  keyscan();
  display(keynumber);
 }
 }

完整代码

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int	   //注意宏定义不能加分号


sbit duan = P2^6; 
sbit wei = P2^7;

uchar keynumber; 
uchar code table[]=	{
    
    0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
 
 void delay (uint k)		   //定义延时函数
 {
    
    
 uint i,j;
 for(i<0;i<k;i++)
    {
    
    
	for(j=0;j<113;j++)
	  {
    
    
	   ;
	  }
    }
 }

  void keyscan()   //这个实验的重点
 {
    
     uchar a; 
   P3=0xf0;
   if(P3!=0xf0)
     {
    
    
	  delay(10);
	  if(P3!=0xf0)
	  {
    
    
	   P3=0xf0;		  //进行列扫描
	   switch(P3)
	   {
    
    
	   case(0xe0):keynumber=0;break;	//11100000
	   case(0xd0):keynumber=1;break;//11010000
	   case(0xb0):keynumber=2;break;//10110000
	   case(0x70):keynumber=3;break;//01110000
	   }
	    P3=0x0f;
	   switch(P3)
	   {
    
    
	   case(0x0e):keynumber=keynumber;break;   //switch case后面是冒号
	   case(0x0d):keynumber=keynumber+4;break;
	   case(0x0b):keynumber=keynumber+8;break;
	   case(0x07):keynumber=keynumber+12;break;
	   }
	   
	  while ((a<50)&&(P3!=0x0f))
	  {
    
    
	  delay(10);
	  a++ ;
	  }	
	  }

	 }
   
  
 }

  void display(uchar num)
 {
    
    
   P0=table[num];
   duan=1;
   duan=0;
   P0=0xc0;//11000000
   wei=1;
   wei=0;
 }

 void main()
 {
    
    
 duan=0;
 wei=0;
 while(1)
 {
    
    
  keyscan();
  display(keynumber);
 }
 }

运行结果
无法一一展示,这里只展示一部分。
在这里插入图片描述
好啦,今天矩阵按键模块的学习就到这里啦。你学废了吗?有问题的话,欢迎共同交流。最近在准备研究生复试,内容比较粗糙,但个人比较喜欢有输出的学习。以后有机会的话,会继续更新完善的!!!

猜你喜欢

转载自blog.csdn.net/m0_46155417/article/details/129468248