八(5)单片机独立按键的扫描

  原理搞清楚了,那么下面我们就先编写一个独立按键的程序,把最基本的功能验证一下。

 
  1. #include <reg52.h>  
  2.   
  3. sbit ADDR0 = P1^0;  
  4. sbit ADDR1 = P1^1;  
  5. sbit ADDR2 = P1^2;  
  6. sbit ADDR3 = P1^3;  
  7. sbit ENLED = P1^4;  
  8. sbit LED9 = P0^7;  
  9. sbit LED8 = P0^6;  
  10. sbit LED7 = P0^5;  
  11. sbit LED6 = P0^4;  
  12. sbit KEY1 = P2^4;  
  13. sbit KEY2 = P2^5;  
  14. sbit KEY3 = P2^6;  
  15. sbit KEY4 = P2^7;  
  16.   
  17. void main(){  
  18.     ENLED = 0;  //选择独立 LED 进行显示  
  19.     ADDR3 = 1;  
  20.     ADDR2 = 1;  
  21.     ADDR1 = 1;  
  22.     ADDR0 = 0;  
  23.     P2 = 0xF7;  //P2.3 置 0,即 KeyOut1 输出低电平  
  24.      
  25.     while (1){  
  26.         //将按键扫描引脚的值传递到 LED 上  
  27.         LED9 = KEY1;  //按下时为 0,对应的 LED 点亮  
  28.         LED8 = KEY2;  
  29.         LED7 = KEY3;  
  30.         LED6 = KEY4;  
  31.     }  
  32. }   

  本程序固定在 KeyOut1 上输出低电平,而 KeyOut2~4 保持高电平,就相当于是把矩阵按键的第一行,即 K1~K4 作为 4 个独立按键来处理,然后把这 4 个按键的状态直接送给LED9~6 这 4 个 LED 小灯,那么当按键按下时,对应按键的输入引脚是 0,对应小灯控制信号也是 0,于是灯就亮了,这说明上述关于按键检测的理论都是可实现的。 

  绝大多数情况下,按键是不会一直按住的,所以我们通常检测按键的动作并不是检测一个固定的电平值,而是检测电平值的变化,即按键在按下和弹起这两种状态之间的变化,只要发生了这种变化就说明现在按键产生动作了。

   程序上,我们可以把每次扫描到的按键状态都保存起来,当一次按键状态扫描进来的时候,与前一次的状态做比较,如果发现这两次按键状态不一致,就说明按键产生动作了。当上一次的状态是未按下而现在是按下,此时按键的动作就是“按下”;当上一次的状态是按下而现在是未按下,此时按键的动作就是“弹起”。显然,每次按键动作都会包含一次“按下”和一次“弹起”,我们可以任选其一来执行程序,或者两个都用,以执行不同的程序也是可以的。下面就用程序来实现这个功能,程序只取按键 K4 为例。

 
  1. #include <reg52.h>  
  2. sbit ADDR0 = P1^0;  
  3. sbit ADDR1 = P1^1;  
  4. sbit ADDR2 = P1^2;  
  5. sbit ADDR3 = P1^3;  
  6. sbit ENLED = P1^4;  
  7. sbit KEY1 = P2^4;  
  8. sbit KEY2 = P2^5;  
  9. sbit KEY3 = P2^6;  
  10. sbit KEY4 = P2^7;  
  11.   
  12. unsigned char code LedChar[] = {  //数码管显示字符转换表  
  13.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,  
  14.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E  
  15. };  
  16.   
  17. void main(){  
  18.     bit backup = 1;  //定义一个位变量,保存前一次扫描的按键值  
  19.     unsigned char cnt = 0;  //定义一个计数变量,记录按键按下的次数  
  20.     ENLED = 0;  //选择数码管 DS1 进行显示  
  21.     ADDR3 = 1;  
  22.     ADDR2 = 0;  
  23.     ADDR1 = 0;  
  24.     ADDR0 = 0;  
  25.     P2 = 0xF7;  //P2.3 置 0,即 KeyOut1 输出低电平  
  26.     P0 = LedChar[cnt];  //显示按键次数初值  
  27.   
  28.     while (1){  
  29.         //当前值与前次值不相等说明此时按键有动作  
  30.         if (KEY4 != backup){  
  31.             //如果前次值为 0,则说明当前是由 0 变 1,即按键弹起  
  32.             if (backup == 0){  
  33.                 cnt++;  //按键次数+1  
  34.                 //只用 1 个数码管显示,所以加到 10 就清零重新开始  
  35.                 if (cnt >= 10){  
  36.                    cnt = 0;  
  37.                 }  
  38.                 P0 = LedChar[cnt]; //计数值显示到数码管上  
  39.             }  
  40.             backup = KEY4;  //更新备份为当前值,以备进行下次比较  
  41.         }  
  42.     }  
  43. }   

  先来介绍出现在程序中的一个新知识点,就是变量类型——bit,这个在标准 C 语言里边是没有的。51 单片机有一种特殊的变量类型就是 bit 型。比如 unsigned char 型是定义了一个无符号的 8 位的数据,它占用一个字节(Byte)的内存,而 bit 型是 1 位数据,只占用 1 个位(bit)的内存,用法和标准 C 中其他的基本数据类型是一致的。它的优点就是节省内存空间,8 个bit 型变量才相当于 1 个 char 型变量所占用的空间。虽然它只有 0 和 1 两个值,但也已经可以表示很多东西了,比如:按键的按下和弹起、LED 灯的亮和灭、三极管的导通与关断等等,联想一下已经学过的内容,它是不是能用最小的内存代价来完成很多工作呢? 

  在这个程序中,我们以 K4 为例,按一次按键,就会产生“按下”和“弹起”两个动态的动作,我们选择在“弹起”时对数码管进行加 1 操作。理论是如此,大家可以在板子上用K4 按键做做实验试试,多按几次,是不是会发生这样一种现象:有的时候我明明只按了一下按键,但数字却加了不止 1,而是 2 或者更多?但是我们的程序并没有任何逻辑上的错误,这是怎么回事呢?于是我们就得来说说按键抖动和消抖的问题了。

永不止步步 发表于01-28 10:40 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67417个|学分:363741个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号