按6也是正常的
课后小练:
这个难度有点大大大.........
第十课到此结束
今天我们继续学习第十一集 矩阵按键
先回忆最简单的独立按键:
矩阵按键接法不同,IO口少
8个按键,只需要6个I/O口
如果是16个按键,只需要4列4行
4+4=8个按键!
当然,软件就复杂点,要2个方向扫描
矩阵按键的一个原理就是用按键2中状态高低电平的一个基础知识
P06P07是不是先给他输出高电平,P00P01P02P03是不是先给他输出低电平
假设K01按下,P06j就变成低电平 ,1端点就变成低电平,确定是P06这行有按键按下
然后4列输出高电平,2行输出低电平
由于 是K1按下,自然是P01对应的1端点是低电平,这样我们就知道是第一行,第二列被按下
按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
①第一步:现将PO.0-PO.3输出低电平,PO.6-P0.7输出高电平,如果有按键按下,按下的那一行的10就会变成低电平,就可以判断出哪一行按下了。
②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的10就会变成低电平,就可以判断出哪一列按下了。
③第三步:行列组合一下就可以判断出是哪个按键按下了。
任务1:数码管显示当前的按键号
u8 key_num = 0xff;
//任务1:数码管显示当前的按键号
void Task_1(void)
{
//①第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
COL1 = 0;
COL2 = 0;
COL3 = 0;
COL4 = 0;
ROW1 = 1;
ROW2 = 1;
if(( ROW1 == 0 ) || ( ROW2 == 0 )) //如果行按键有按下
{
if(( ROW1 ==0 ) && ( ROW2 ==0 )) //如果两行都有按键按下,不处理
{
}
else if((( ROW1 ==1 )&&( ROW2 ==0 )) || (( ROW1 ==0 )&&( ROW2 ==1 ))) //如果有按键按下,而且只有一颗
{
if( ROW1 ==0 ) //判断哪一行,输出行开始的序号
key_num = 0;
else if( ROW2 ==0 )
key_num = 4;
//②第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
COL1 = 1;
COL2 = 1;
COL3 = 1;
COL4 = 1;
ROW1 = 0;
ROW2 = 0;
if( COL1 ==0 ) //判断哪一列,叠加按键的序号
{
// key_num = key_num ;
}
else if( COL2 ==0 )
{
key_num = key_num + 1;
}
else if( COL3 ==0 )
{
key_num = key_num + 2;
}
else if( COL4 ==0 )
{
key_num = key_num + 3;
}
}
COL1 = 0;
COL2 = 0;
COL3 = 0;
COL4 = 0;
ROW1 = 1;
ROW2 = 1;
}
else
{
key_num = 0xff;
}
//③第三步:行列组合一下就可以判断出是哪个按键按下了。
}
为甚可以这样写?
COL1 = 0;
COL2 = 0;
COL3 = 0;
COL4 = 0;
ROW1 = 1;
ROW2 = 1;
是因为在io.h里宏定义了:
#ifndef __IO_H
#define __IO_H
#include "config.h" //调用头文件
#define ROW1 P06 //端口定义
#define ROW2 P07
#define COL1 P00
#define COL2 P01
#define COL3 P02
#define COL4 P03
#define HC595_SER P34
#define HC595_RCK P35
#define HC595_SCK P32
extern u8 key_num ;
void LED0_Blink(void);
void LED1_Blink(void);
void LED2_Blink(void);
void KEY_Task(void);
void Task_1(void);
void SEG_Task(void);
void Init_595(void);
//void PW_write_Task(void);
#endif
这里明显是2行4列
这样写就清晰明了
先在程序里这样:
/*
#define ROW1 P06 //端口定义
#define ROW2 P07
#define COL1 P00
#define COL2 P01
#define COL3 P02
#define COL4 P03
*/
因为画PCB板的人会自己方便,IO口顺序是很混乱的
我们这样宏定义(建议直接把注释copy到程序中,对着写)
就不会出错,也不用反复打开io.h来看
if(( ROW1 == 0 ) || ( ROW2 == 0 )) //如果行按键有按下
C语音中“或”分为两种:逻辑或(||)和按位或(|):
逻辑或(||):用于条件判断,当两个操作数中至少有一个为真时,结果为真。常用于if等条件语句中。例如:if (a > 0 || b < 10)
按位或(|):用于二进制位操作,对两个数的每一位进行或运算。例如:int c = a | b;
就是说这2个条件有1个条件成立,这个条件语句就开始执行
说人话就是2行中有任意一行按钮按下就执行