STC8H系列单片机轻触按键基础知识入门教程(三)
一、轻触按键工作原理
当我们按下轻触开关的按钮时,其弹片受到弹力作用发生形变向下接触到焊片,使得开关的两组引脚相导通,从而使得电路呈现导通状态;而当我们撤离外力时,弹片形变恢复原始状态,脱离焊片,开关的两组引脚也不再导通,从而使得电路呈现截止状态。
二、按键抖动
对于机械按键,当机械触点断开或者闭合的时候,由于机械触点的弹性作用,一个按键在闭合时不会马上稳定的接通,在断开时也不会一下子断开,所以在按键闭合及断开瞬间会伴随一连串的抖动,如下图所示:
三、软件消抖
先判断一个按键是否按下,如按键按下波形可知,按键抖动在按下瞬间和按键松开瞬间发生的,抖动时长大概5-10ms。那么,延时对应的时长既可解决此问题。一般可以通过软件延时,但是实际产品一般采用硬件定时器延时判断,增加程序执行的实时性;如图是一段简单的软件延时判断按键按下代码:
四、硬件消抖
按键硬件消抖利用电容的放电延时,采用并联电容法,也可以实现硬件消抖。如图所示,由于电容两端电压不能突变,使得按键两端的电压平缓变化,直至电容充放电到达一定电压阈值时,单片机才读取到电平变化。一般最佳的设计是硬件消抖配合程序软件去抖。
五、独立按键检测示例代码
#include "STC8H.h" //头文件
#define LED1 P41
#define LED2 P73
#define LED3 P72
#define LED4 P71
#define KEY1 P05
#define KEY2 P06
#define KEY3 P07
void soft_delay(unsigned int num)
{
unsigned int i,j;
for(i = 0;i < num;i++)
for(j = 0;j < 200;j++);
}
void main(void)
{
P0M1 = 0X00; P0M0 = 0X00; //设置P05/P06/P07为准双向口
P4M1 = 0X00; P4M0 = 0X02; //设置P41为推挽输出口
P7M1 = 0X00; P7M0 = 0X0E; //设置P73/P72/P71为推挽输出口
LED1 = 0;LED2 = 0;LED3 = 0;LED4 = 0; //关闭LED
KEY1 = 1;KEY2 = 1;KEY3 = 1; //读取端口前先使能内部弱上拉电阻
while(1)
{
if(KEY1 == 0) //按键按下
{
soft_delay(100); //延时消抖
if(KEY1 == 0) //再次判断按键是否按下
{
LED1 = ~LED1; //发光二极管点亮--熄灭,循环控制
}
while(!KEY1); //等待按键松开
}
if(KEY2 == 0)
{
soft_delay(100);
if(KEY2 == 0)
{
LED2 = ~LED2;
}
while(!KEY2);
}
if(KEY3 == 0)
{
soft_delay(100);
if(KEY3 == 0)
{
LED3 = ~LED3;
}
while(!KEY3);
}
}
}
六、矩阵按键检测示例代码
#include "STC8H.h" //头文件
/*宏定义矩阵按键控制IO*/
#define ROW1 P36
#define ROW2 P35
#define ROW3 P51
#define ROW4 P50
#define COL1 P65
#define COL2 P66
#define COL3 P67
#define COL4 P34
/*宏定义数码管显示控制IO*/
#define LED_A P77
#define LED_B P26
#define LED_C P46
#define LED_D P01
#define LED_E P02
#define LED_F P27
#define LED_G P45
#define LED_DP P00
#define LED_DIG1 P53
#define LED_DIG2 P52
#define LED_DIG3 P04
#define LED_DIG4 P03
#define LED_DIG5 P20
#define LED_DIG6 P21
#define LED_DIG7 P22
#define LED_DIG8 P23
unsigned char scan_step = 0; //扫描步骤
unsigned char key_value = 0; //键值
/*共阳数码管段码表*/
unsigned char const display_ca_table[16] =
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e
}; //0-F
/*延时子函数*/
void soft_delay(unsigned int num)
{
unsigned int i,j;
for(i = 0;i < num;i++)
for(j = 0;j < 200;j++);
}
/*主函数*/
void main(void)
{
P0M1 = 0X00; P0M0 = 0X1F; //设置P00/P01/P02/P03/P04为推挽输出口
P2M1 = 0X00; P2M0 = 0XCF; //设置P20/P21/P22/P23/P26/P27为推挽输出口
P3M1 = 0X00; P3M0 = 0X00; //设置P33/P34/P35/P36为准双向口
P4M1 = 0X00; P4M0 = 0X60; //设置P45/P46为推挽输出口
P5M1 = 0X00; P5M0 = 0X0C; //设置P52/P53为推挽输出口、设置P50/P51为准双向口
P6M1 = 0X00; P6M0 = 0X00; //设置P65/P66/P67为准双向口
P7M1 = 0X00; P7M0 = 0X80; //设置P77为推挽输出口
ROW1 = 1;ROW2 = 1;ROW3 = 1;ROW4 = 1; //读取端口前先使能内部弱上拉电阻
while(1) //死循环
{
switch(scan_step)
{
case 0:
COL1 = 0;COL2 = 1;COL3 = 1;COL4 = 1; //扫描第一列
scan_step = 1;
break;
case 1:
COL1 = 1;COL2 = 0;COL3 = 1;COL4 = 1; //扫描第二列
scan_step = 2;
break;
case 2:
COL1 = 1;COL2 = 1;COL3 = 0;COL4 = 1; //扫描第三列
scan_step = 3;
break;
case 3:
COL1 = 1;COL2 = 1;COL3 = 1;COL4 = 0; //扫描第四列
scan_step = 4;
break;
default:
COL1 = 1;COL2 = 1;COL3 = 1;COL4 = 1;
scan_step = 0;
break;
}
/*假如有按键按下*/
if( (ROW1 == 0) || (ROW2 == 0) || (ROW3 == 0) || (ROW4 == 0) )
{
soft_delay(10);
if( (ROW1 == 0) || (ROW2 == 0) || (ROW3 == 0) || (ROW4 == 0) )
{
if(ROW1 == 0) //第一行有按键按下
{
key_value = 0 + (scan_step-1)*4; //获取键值
}
else if(ROW2 == 0) //第二行有按键按下
{
key_value = 1 + (scan_step-1)*4; //获取键值
}
else if(ROW3 == 0) //第三行有按键按下
{
key_value = 2 + (scan_step-1)*4; //获取键值
}
else if(ROW4 == 0) //第四行有按键按下
{
key_value = 3 + (scan_step-1)*4; //获取键值
}
}
}
soft_delay(10);
/*数码管显示*/
LED_A = (display_ca_table[key_value]>>0) & 0x01;
LED_B = (display_ca_table[key_value]>>1) & 0x01;
LED_C = (display_ca_table[key_value]>>2) & 0x01;
LED_D = (display_ca_table[key_value]>>3) & 0x01;
LED_E = (display_ca_table[key_value]>>4) & 0x01;
LED_F = (display_ca_table[key_value]>>5) & 0x01;
LED_G = (display_ca_table[key_value]>>6) & 0x01;
LED_DP = (display_ca_table[key_value]>>7) & 0x01;
LED_DIG1 = 1;
LED_DIG2 = 1;
LED_DIG3 = 1;
LED_DIG4 = 1;
LED_DIG5 = 1;
LED_DIG6 = 1;
LED_DIG7 = 1;
LED_DIG8 = 0;
}
}
七、基于状态机的按键检测方法
采用状态机方式处理点触按键,根据不同按键状态执行不同操作,实现更灵活高效的控制方式。状态机设计可精确处理每个按键动作,确保操作准确可靠。
状态机的四要素
现态:状态机当前状态。
触发条件:改变当前状态的发生条件。
动作:状态改变产生相应的动作。
次态:状态机激活触发条件后跳转到的下一状态。
作者:芯航路IOT