从单片机基础到程序框架(全集 2019pdf版).pdf - 第500页

上图 10 3.1.3 3*3 矩阵按键的 电路 “无序” 是指两个组合按键 不分先后顺序 , 都能 构成组合 触发。 比如, 要触 发组合键 (S1+S2) , 先按 S1 再按 S2,或者先按 S2 再按 S1,功能都是 一样的 。 本节程序 功能如下: (1)S1 每单击一次,P1.4 所在 的 L ED 要么 从“灭” 变成“亮” ,要么从“亮” 变成 “灭” ,在两种状态之间 切换。 (2 )S2 每单 击一次,P1.5 所在…

100%1 / 836
第一百零三节: 两个“任意行输入”矩阵按键的“无序”组合触发。
【103.1 “无序”组合触发。
上图 103.1.1 有源蜂鸣器电路
上图 103.1.2 LED 电路
上图 103.1.3 3*3 矩阵按键的电路
“无序”是指两个组合按键不分先后顺序都能构成组合触发。比如,要触发组合键(S1+S2)先按 S1
再按 S2,或者先按 S2 再按 S1,功能都是一样的
本节程序功能如下:(1)S1 每单击一次,P1.4 所在 LED 要么从“灭”变成“亮”,要么从“亮”变成
“灭”,在两种状态之间切换。(2)S2 每单击一次,P1.5 所在的 LED 要么从“灭”变成“亮,要么从“亮”
变成“灭”,在两种状态之间切换。(3)如果先按住 S1 再按 S2,或者先按住 S2 再按 S1,都认为构造了“无
序”组合键,蜂鸣器发出“嘀”的一声。
#include "REG52.H"
#define KEY_VOICE_TIME 50
#define KEY_SHORT_TIME 20
void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
void BeepOpen(void);
void BeepClose(void);
void LedOpen_P1_4(void);
void LedClose_P1_4(void);
void LedOpen_P1_5(void);
void LedClose_P1_5(void);
void VoiceScan(void);
void KeyScan(void);
void SingleKeyTask(void);
void DoubleKeyTask(void);
sbit P3_4=P3^4;
sbit P1_4=P1^4; //P1.4 所在的 LED
sbit P1_5=P1^5; //P1.5 所在的 LED
sbit ROW_INPUT1=P2^2; //第 1 行输入口。
sbit ROW_INPUT2=P2^1; //第 2 行输入口。
sbit ROW_INPUT3=P2^0; //第 3 行输入口。
sbit COLUMN_OUTPUT1=P2^5; //第 1 列输出口。
sbit COLUMN_OUTPUT2=P2^4; //第 2 列输出口。
sbit COLUMN_OUTPUT3=P2^3; //第 3 列输出口。
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus_P1_4=0; //P1.4 所在的 LED 的状态
unsigned char Gu8LedStatus_P1_5=0; //P1.5 所在的 LED 的状态
volatile unsigned char vGu8SingleKeySec=0;
volatile unsigned char vGu8DoubleKeySec=0;
void main()
{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
SingleKeyTask();
DoubleKeyTask();
}
}
/* 注释一:
* 矩阵按键“无序”触发的两个最关键地方:
* (1)如果是 S1 按键先被按下并且单击触发之后,“马上更新输出列的信号状态”,然后切换
* “S1 后面所在的步骤里”,进入 S1 S2 两个按键的轮番循环监控之中,如果发现 S1 按键率先
* 被松开了,就把步骤切换到开始的第一步,重新开始新一轮的按键扫描。
* (2)如果是 S2 按键先被按下并且单击触发之后,“马上更新输出列的信号状态”,然后切换
* “S2 后面所在的步骤里”,进入 S1 S2 两个按键的轮番循环监控之中,如果发现 S2 按键率先
* 被松开了,就把步骤切换到开始的第一步,重新开始新一轮的按键扫描。
* (3)上面两个描述中的两种步骤,“S1 后面所在的步骤里”和“S2 后面所在的步骤里”是分开的,
* 不共用的,这是本节破题的关键
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock=0;
static unsigned int Su16KeyCnt=0;
static unsigned char Su8KeyStep=1;
static unsigned char Su8ColumnRecord=0;
switch(Su8KeyStep)
{
case 1:
if(0==Su8ColumnRecord)
{