单片机:独立按键与矩阵按键的

前言:前面是单片机IO口的输出使用,(比如:IO口控制电平高低来显示LED灯和数码管蜂鸣器等。)本次开始使用IO口的输入。

1.52单片机板载4个黑色的独立按键,其独立应当是因为各自用一个I/O口进行控制。

ps:按键与IO口之间的对应关系是不同于以往的顺序升序是对应关系。

K1->p3.1

k2->p3.0//两个口子的位置是相反的。

k3->p3.2

k4->p3.4

流程:

1)检测是否有按键按下

2)延时消抖

3)再检测

3)根据检测结果显示相应的结果

电路原理:四个按键一端接地,另一端与IO口相连,当按键按下时相当于IO口接地,此时IO口的输入电平即为低电平,这就是通过按键控制改变IO口内的电平状态称之为输入。

伪代码:

宏定义四个按键与端口

定义按键按下状态对应的值

设计检测函数,返回值为按键按下的值或者是无按钮按下,函数的形式参数为mode

当mode为0时,按键按下(包括长按)仅获取一次有效按键操作,当mode为1时,获取多次按键操作(可长按)。

核心程序设计如下:

u8 scan(u8 mode){

static u8 key=1;//这个静态变量设计相当重要,其具有记忆功能,会保存最近更改的值。

if(mode==1)

key==1;//这里就是mode利用key来实现对输入模式的控制。

if(key==1&&(key1==0||key2==0||key3==0||key4==0)){

        delay_10us(1000)//大概是10ms,消抖

        key=0;//这里用掉了key=1的关键钥匙,如果mode为0的话,下一次将不会进入这个输入并赋值的循环之内,如果mode为1的话,那么整scan函数内key始终在执行返回有效值之前都为1,也即一直判断在进行连续输入。

        if(key1==0)

   return key1_press.

         }

     ..........

else if(key1,2,3,4==1)//为了节省时间使用了伪代码

      return nokey_press.

}

void main(){

u8 key=0;

while(1){

key=scan_(0);

if (key==key1_press);

led=!led//灯只有两种状态(亮/灭)所以翻转秩序只需取反,同时也可以直接使用~符号
}

}

2.矩阵按键:

矩阵按键不同于独立按键(独立按键一端接地,恒为低电平),其两端均是IO口,因此,想判断那个键按下,需要用到行列扫描和线翻转法。

行列扫描:将某一列的一端全部置为低电平,然后遍历该列里面所有行,如果出现低电平 ,即可确定案件的行列位置。随即以同样的方式遍历所有列,找到低电平就能确定按下键位的位置。

线翻转法:首先使得所有行线为低电平,(也即一端先给所有的按键通上低电平,接入低电平的IO口记为行线),随即按列遍历检测是否存在低电平,若存在,则记下列数;

随即翻转----将通入低电平的端口记为列线端(由于按键位置不同,在通入低电平时会组合成真正意义上的行和列,这是有硬件快决定的,应当会使用 位 操作),当行检测出现低电平时,记录行数。

至此,行列均已确定,按键位置也就确定了。

根据矩阵键盘的电路图可知,8根行列线(4根行线,4根列线)分别对应单片机的p1口的8个IO口,其中,

第一行----->p1.7

第二行----->p1.6

第三行----->p1.5

第四行----->p1.4

第一列----->p1.3

第二列----->p1.2

第三列----->p1.1

第四列----->p1.0

行列扫描程序讲解:

11110111也即0xf7;如果按键按下,端口就不是这个值--》延时消抖,随即 ,switch case,可能出现的值:

01110111是为第一行第一列,记为key=1;

10110111是为第二行第一列,记为key=5;

11010111是为第三行第一列,记为key=9;

11100111是为第三行第一列,记为key=13.

再来一个松开按键等待
while(port!=0xf7);

这个无花括号的为了语句起到了过程保护作用,当括号内为真(按键出于按下状态),就不会执行后面的语句;当松开按键时,port=初始赋值也即0xf7,退出while的循环,执行后面的语句.......

后面再对第二列执行类似的操作,将11111011也即0xfb作为初始值。

线翻转法程序讲解:

初始值因为列线全部赋值为0,得到11110000,此初始值为0xf0;当有按键按下时,会有如下情况:switch case:

01110000==0x70,第一行按下,记录key=0;

10110000==0xb0,第二行按下,记录key=4;

11010000==0xd0;第三 行按下,记录key=8;

11100000==0xe0;第四行按下,记录key=12;

此就是记录了行数;

随即以类似的方式换成给行全部赋值为0,以列的低电平来判断按键的位置:

switch case:

00000111==07;第一列按下,key值+1;

00001011==0b;第二列按下,key值+2;

00001101==0d;第三列按下,key值+3;

00001110==0e;第四列按下,key值+4;

ps:线翻转法中的key变量最好是设置成为static静态变量,具有储存记忆功能,这样在行和列变换以及下一次没按之前可以更好地保存之前的数值。

这是先判定行后判定列,同样可以先判定列再判定行;

不过关于key的值就应该重新安排,起先赋值为1234;随即加0,4,8,12;

 然后跟据对应的返回值,结合 数码管的控制基础, 实现按键对数码管的控制。

C语言程序的优先级问题,由于C语言接近底层语言,其赋值一般具有实际上的物理意义,比如给某个端口输入高低电平,此时,控制的

转载于:普中51单片机开发攻略

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值