前言:前面是单片机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单片机开发攻略