一、独立按键分析
J5跳线帽接口接到BTN,独立按键模式,当独立按键按下时,P3口获得低电平。注意:进行独立按键模块操作时要注意消抖。
二、示例——状态机法
实现计数S4按下的次数、
1.思路:
①:读取P33状态②:如果不是0,继续读取P33状态;如果不是0,则等待10ms,再读取P33状态。③:如果还是0,则确定有按键按下,执行number++;如果不是0,则说明是抖动,不执行其他程序。④:等待按键弹起后,再等待10ms,再从①开始执行。
编程方法:
2.代码:
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "system.h"
#include "Delay.h"
#include "Device.h"
#define KEY_NO 0 //无按键按下状态,用于判断是否按下
#define KEY_DOWN 1 //有按键按下状态,判断是否为抖动
#define KEY_UP 2 //等待松手状态,判断是否弹起
//数码管显示数字对应的数组
u8 smg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x3e,0x73};
HexToBin led_ctrl,uln_ctrl;
//系统初始化函数
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0);
led_ctrl.hex=0xff;
vDevice_Ctrl(0x80,led_ctrl.hex);
}
void Timer2Init(void) //1ms@12.000MHz
{
AUXR &= 0xFB;
T2L = 0x18;
T2H = 0xFC;
AUXR |= 0x10;
IE2 |= 0x04; //开启定时器2中断
EA = 1; //开启总中断
}
//独立按键状态机法
u8 BTN_Read(void) //10ms执行一次
{
static u8 key_state = 0; //保存按键的状态
u8 key_io =0 ,key_val = 0;
key_io = P3 & 0x0f; //对P3的高4位清0,屏蔽不关心的IO状态
switch(key_state)
{
case KEY_NO:
if(key_io!=0x0f) key_state = KEY_DOWN;
break;
case KEY_DOWN:
if(key_io!=0x0f)
{
if(key_io==0x0e)key_val = 7; //S7
if(key_io==0x0d)key_val = 6; //S6
if(key_io==0x0b)key_val = 5; //S5
if(key_io==0x07)key_val = 4; //S4
key_state = KEY_UP;
}
else
key_state = KEY_NO;
break;
case KEY_UP:
if(key_io==0x0f) key_state = KEY_NO;
break;
}
return key_val;
}
u8 cnt_key;
u8 s4_number;
//按键处理函数
void vBTN_Process(void)
{
u8 key_val;
if(cnt_key>=10)
{
cnt_key=0;
key_val = BTN_Read();
if(key_val==4)
{
s4_number++;
}
}
}
//数码管操作函数
u8 smg_buf[8];
void vSMG_Process()
{
smg_buf[0]=smg_code[s4_number/100];
smg_buf[1]=smg_code[s4_number/10%10];
smg_buf[2]=smg_code[s4_number%10];
smg_buf[3]=0x00;
smg_buf[4]=0x00;
smg_buf[5]=0x00;
smg_buf[6]=0x00;
smg_buf[7]=0x00;
}
void main()
{
vSystem_Init();
Timer2Init();
while(1)
{
vBTN_Process();
vSMG_Process();
}
}
//数码管显示函数
void vSmg_Display()
{
static u8 i=0;
vDevice_Ctrl(0xc0,0); //进行段选前,清除所有位选,消除鬼影
vDevice_Ctrl(0xe0,~smg_buf[i]);
vDevice_Ctrl(0xc0,0x01<<i);
i++;
if(i==8) i=0;
}
void Timer2_Routine(void) interrupt 12
{
cnt_key++;
vSmg_Display();
}
3.现象:
三、示例——三行按键法
1.思路
2.利用三行按键法实现独立按键控制数码管显示的数字大小
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "system.h"
#include "Delay.h"
#include "Device.h"
//数码管显示数字对应的数组
u8 smg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x3e,0x73};
HexToBin led_ctrl,uln_ctrl;
//系统初始化函数
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0);
led_ctrl.hex=0xff;
vDevice_Ctrl(0x80,led_ctrl.hex);
}
void Timer2Init(void) //1ms@12.000MHz
{
AUXR &= 0xFB;
T2L = 0x18;
T2H = 0xFC;
AUXR |= 0x10;
IE2 |= 0x04; //打开定时器2开关
EA = 1; //打开总开关
}
//三行按键法
unsigned char Trg;
unsigned char Cont;
void vBTN_Read_ThreeLine(void)
{
unsigned char ReadData = P3^0xff;
Trg = ReadData & (ReadData ^ Cont);
Cont = ReadData;
}
u8 cnt_key;
u8 number;
//按键处理函数
void vBTN_ThreeLine_Process(void)
{
if(cnt_key>=10)
{
cnt_key=0;
vBTN_Read_ThreeLine();
if(Trg & 0x08) //S4
{
number++;
}
if(Trg & 0x04) //S5
{
number--;
}
if(Trg & 0x02) //S6
{
number += 10;
}
if(Trg & 0x01) //S7
{
number -= 10;
}
}
}
//数码管操作函数
u8 smg_buf[8];
void vSMG_Process()
{
smg_buf[0]=smg_code[number/100];
smg_buf[1]=smg_code[number/10%10];
smg_buf[2]=smg_code[number%10];
smg_buf[3]=0x00;
smg_buf[4]=0x00;
smg_buf[5]=0x00;
smg_buf[6]=0x00;
smg_buf[7]=0x00;
}
void main()
{
vSystem_Init();
Timer2Init();
while(1)
{
vBTN_ThreeLine_Process();
vSMG_Process();
}
}
//数码管显示函数
void vSmg_Display()
{
static u8 i=0;
vDevice_Ctrl(0xc0,0); //段选前,清除位选,消除鬼影
vDevice_Ctrl(0xe0,~smg_buf[i]);
vDevice_Ctrl(0xc0,0x01<<i);
i++;
if(i==8) i=0;
}
void Timer2_Routine(void) interrupt 12
{
cnt_key++;
vSmg_Display();
}