目录
1.独立按键原理图
STC15F2K60S2中的按键有独立按键和矩阵按键两个模式,J5跳冒控制按键模式。当J5跳冒接在23口时该按键处于独立按键模式(BTN模式),当J5跳冒接在12口时该按键处于矩阵按键模式(KBD模式)。这里,我们需要将J5跳冒接在23口实现独立按键模式。
2.独立按键原理
以S7按下为例。当S7按下时,按键两端导通。由于S7左端接的GND,导通后P30口即为低电平。于是,当单片机判断一个按键是否按下时,只需检测连接该按键的端口是否为低电平即可。但是,在实际操作中,会伴随这按键的抖动。于是我们要对按键进行消抖处理,才可精确判断按键是否按下。
3.编程实现:统计S4按下次数
思路:在while(1)内循环换:
①读取P33状态
②如果是0,则等待10ms,再读取P33状态
③如果还是0,确定有按键按下;则执行number++;让数码管数字+1
如果不是0,则说明是抖动;则不执行任何程序
④等待按键弹起后,再等待10ms,从①再开始执行
3.1.判断按键是否按下函数
这里我们使用的是状态机法,程序代码如下:
//独立按键状态机法
#define KEY_NO 0 //无按键状态,用于判断是否按下
#define KEY_DOWN 1 //有按键按下状态,判断是否为抖动
#define KEY_UP 2 //等待松手状态,判断是否弹起
u8 vBTN_Read(void) //10ms执行一次
{
static u8 key_state=0; //定义key_state为静态变量,用于保存每次按键状态
u8 key_io=0,key_val=0; //key_io:读取IO口的状态;key_val:返回键值;
key_io=P3&0x0f; //对P3读回来的高4位IO口清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;
}
3.2.按键处理函数
u8 cnt_key; //定义按键计时变量,在定时器中计时
u8 s4_number;//定义用来保存S4按下的次数变量
void vBTN_Process(void)
{
u8 key_val;
if(cnt_key>=10) //10MS进行一次读取
{
cnt_key=0;
key_val=vBTN_Read(); //读取按键的键值
if(key_val==4)
{
s4_number++;
}
}
}
3.3.数码管函数
//共阴数码管码表
u8 smg_code[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//数码管操作函数
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 vSMG_Display()
{
static u8 i=0;
vDevice_Ctrl(0xc0,0); //位选(消除鬼影)
vDevice_Ctrl(0xe0,~smg_buf[i]); //段选
vDevice_Ctrl(0xc0,0x01<<i); //位选
i=(i+1)%8;
}
3.4.外设控制函数
#include "Device.h"
/**
* @brief 外设控制函数
* @param None
* @retval None
*/
void vDevice_Ctrl(unsigned char P2data,unsigned char P0data)
{
P0=P0data;
P2=P2data;
P2=0;
}
3.5主函数
#include "system.h"
#include <intrins.h>
#include "Device.h"
HexToBin led_ctrl,uln_ctrl;
/**
* @brief 系统初始化函数:关闭继电器、蜂鸣器
* @param None
* @retval None
*/
void vSystem_Init(void)
{
vDevice_Ctrl(0xa0,0); /*关闭蜂鸣器、继电器*/
led_ctrl.hex=0xff;
vDevice_Ctrl(0x80,led_ctrl.hex); /*关闭LED*/
}
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟12T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2|=0x04; //开定时器2中断
EA=1;
}
void main(void)
{
vSystem_Init();
Timer2Init();
while(1)
{
vSMG_Process();
vBTN_Process();
}
}
//中断服务程序
void vTimer2_ISR() interrupt 12 //中断入口
{
cnt_key++;
vSMG_Display();
}
注意事项:1.每次按键按下需要单次触发
2.需要有松手检测
3.不用delay延时堵塞程序