/*===============================================================
功能:一个按键实现按键的长按,短按,多击
长按:按下有效,有长按,短按一般来讲都是松开有效
多击(包含单击):松开有效
按键按下的触发事件:(触发事件可以按需求修改)
长按:点亮Led0
单击:点亮Led1
双击:点亮Led2
三击:点亮Led3
===============================================================*/
/*============================注意事项==================================
1.关于Seg的变量和ucLed可以不必理会,
前者是数码管显示Reg_Test_Count,后者是按键按下后的触发事件。这两个大家可以自己更改
=======================================================================*/
/* 头文件声明区 */
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
sbit KEY4 = P3^3; //定义了一个按键
/* 变量声明区 */
unsigned char Key_Slow_Down; //按键减速专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10}; //数码管显示数据存放数组
unsigned char Seg_Pos; //数码管扫描专用变量
unsigned int Seg_Slow_Down; //数码管减速专用变量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0}; //Led显示数据存放数组
/*变量*/
unsigned int Reg_Test_Count; //测试用的一个变量,表示短按了多少次。这个可以自己定义一个
unsigned int Reg_Tick; //表示每次按下的时间间隔是多少。初始值可以自己改,看后面的代码就知道了
unsigned int Reg_Key_Filter_50ms; //按下时滤波,我这里滤波50ms。
unsigned int Reg_Key_10ms; //10ms计数
/*标志位*/
unsigned char Bit_Short_Press; //短按标志位
unsigned char Bit_10ms; //10ms定时到达标志位
/* 键盘处理函数 */
void Key_Proc()
{
static unsigned int Reg_Key_Press_Time = 0; //请记得标为静态变量
if(Bit_10ms) //10ms进来一次
{
Bit_10ms = 0;
if(KEY4==0) //如果按下了按键
{
Reg_Tick = 50; //给多击的时间间隔赋初值
if(++Reg_Key_Press_Time <=0 ) --Reg_Key_Press_Time; //计量按键时间,并避免数据溢出
if(Bit_Short_Press == 0) //判断短按标志位
{
if(++Reg_Key_Filter_50ms >= 5) //如果滤波时间到达了50ms
{
Reg_Key_Filter_50ms = 0; //滤波时间清0
Reg_Test_Count++;
Bit_Short_Press = 1; //短按标志位置1
}
}
if(Reg_Key_Press_Time >= 100) //长按时间已经到达1s
{
ucLed[0] = 1; //这里写事件,我这里写的点灯
}
}
else//松开
{
Reg_Key_Filter_50ms = 0; //滤波的50ms只有检测到高电平立马清零,此次按键无效
Bit_Short_Press = 0; //短按标志位清零
Reg_Key_Press_Time = 0; //长按计数清零
if(Reg_Tick) //如果多击时间间隔不为零
{
Reg_Tick--;
}
if(Reg_Tick == 0) //只要减到0,就说明此时我已经不再按下按键了,开始写多击事件
{
if(Reg_Test_Count == 1) //如果按下一次
{
ucLed[1] = 1; //写按下一次的事件,这个可以自己改,我写的点灯
}
else if(Reg_Test_Count == 2) //如果按下两次
{
ucLed[2] = 1; //同上
}
else if(Reg_Test_Count == 3) //如果按下三次
{
ucLed[3] = 1; //同上
}
Reg_Test_Count = 0; //Reg_Test_Count清零,等待执行下一次多击事件
//到这里就完整的执行了一次多击事件,注意Reg_Test_Count一定要清零。
}
}
}
}
/* 信息处理函数 */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
Seg_Buf[0] = Reg_Test_Count%10;
}
/* 定时器0中断初始化函数 */
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器中断0打开
EA = 1; //总中断打开
}
/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;//数码管减速专用
if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
if(++Reg_Key_10ms >= 10)
{
Reg_Key_10ms = 0;
Bit_10ms = 1;
}
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}
/* Main */
void main()
{
System_Init();
Timer0Init();
while (1)
{
Key_Proc();
Seg_Proc();
}
}
|