资深版主
- 积分
- 4306
- 金钱
- 4306
- 注册时间
- 2018-6-30
- 在线时间
- 808 小时
|
本帖最后由 1208 于 2019-1-21 20:21 编辑
分享一个mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,按键KEY1中断,控制灯亮5秒后熄灭
本实验实现的功能mini板按键KEY0单击、双击、长按和串口实现灯的控制状态,
按键KEY1中断,控制灯亮5秒后熄灭
且通过按键KEY0单击亮红灯、双击亮绿灯、长按两灯都熄灭来实现灯的
1)首先说到按键KEY0单击、双击、长按,这个需要了解按键所处的状态
如单击完后,超过多长时间属于长按,以及双击间隔的时间多长
还有TIM3_Int_Init(99,7199);//10ms,按键扫描计时10ms
这个很关键,超过这个10ms会导致按键单击、双击、长按的失灵
下面这段程序可以通过key = key_read()调用;
[mw_shl_code=c,true]unsigned char key_driver(void)
{
static unsigned char key_state = key_state_0, key_time = 0;
unsigned char key_press, key_return = N_key;
key_press = KEY0; // 读按键IO电平
switch (key_state)
{
case key_state_0: // 按键初始态
if (!key_press) key_state = key_state_1; // 键被按下,状态转换到按键消抖和确认状态
break;
case key_state_1: // 按键消抖和确认状态
if (!key_press) //按键仍然处于按下
{
key_time = 0;
key_state = key_state_2; //,消抖完成,状态转换到按下键时间的计时
}
else
key_state = key_state_0; //按键已抬起,转换到按键初始态。此处完成和实现软件消抖,此时
break; //按键的按下和释放都在此消抖
case key_state_2:
if(key_press)
{
key_return = S_key; // 此时按键的释放,说明是产生一次短操作,回送S_key
key_state = key_state_0; // 转换到按键的初始态
}
else if (++key_time >= 100) // 继续按下,计时10ms
{
key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长按操作
key_state = key_state_3; // 转换到等待按键释放状态
}
break;
case key_state_3: // 等待按键释放状态,此状态只返回无按键事件
if (key_press) key_state = key_state_0; //按键已释放,已转换到按键初始态
break;
}
return key_return;
}
/*=============
时间10ms
===============*/
unsigned char key_read(void)
{
static unsigned char key_m = key_state_0, key_time_1 = 0;
unsigned char key_return = N_key,key_temp;
key_temp = key_driver();
switch(key_m)
{
case key_state_0:
if (key_temp == S_key )
{
key_time_1 = 0; // 第一次单击,不返回,到下个转态判断后面是否出现双击
key_m = key_state_1;
}
else
key_return = key_temp; // 对于无键、长按,返回原事件
break;
case key_state_1:
if (key_temp == S_key) // 又一次单击(间隔时间<500ms)
{
key_return = D_key; // 返回双击键事件,回初始状态
key_m = key_state_0;
}
else
{ // 这里500ms内肯定读到的都是无键事件,
if(++key_time_1 >= 50) //因为长按>1000ms,低层返回都是无按键
{
key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键
key_m = key_state_0; // 返回初始状态
}
}
break;
}
return key_return;
}[/mw_shl_code]
2)KEY0控制单击、双击、长按和串口控制灯,每10ms执行一次
这里需要用一个if ( time_10_ms) 每10ms执行一次来判断检测按键用的
既可以通过按键来控制也可以通过串口来控制
[mw_shl_code=c,true]if ( time_10_ms) //每10ms执行一次
{
time_10_ms = 0 ;
key = key_read();
if (key == S_key||USART_RX_BUF[0]=='0')
{
LED0=0;
printf("LED0亮\n");
delay_ms(1000);
USART_RX_BUF[0]=9;
}
else if(key == D_key||USART_RX_BUF[0]=='1')
{
LED1=0;
printf("LED1亮\n");
delay_ms(1000);
USART_RX_BUF[0]=9;
}
else if(key == L_key||USART_RX_BUF[0]=='2')
{
LED0=1;
LED1=1;
printf("LED0和LED1都灭\n");
delay_ms(1000);
USART_RX_BUF[0]=9;
}
} [/mw_shl_code]
3)KEY1中断按键,红灯5秒后自动熄灭
这个就需要通过定时器的配合来实现倒计时
[mw_shl_code=c,true] if(key1Pressed)
{
LED0 = 0 ;
}
if(count > 500)
{
LED0 = 1 ;
count = 0 ;
key1Pressed = 0 ;
}
extern int key1Pressed ;
extern int count ;
extern int time_10_ms;
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
time_10_ms = 1;
if (LED0 == 0 && key1Pressed == 1 )
count++ ;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
}
[/mw_shl_code]
4)volatile int time_10_ms = 0 ; //volatile提醒编译器它后面定义的变量随时有可能改变
volatile int count = 0 ; //每次存储或读取变量,直接从变量地址中读取数据
volatile int key1Pressed = 0 ;
希望对初学者有所帮助,也向大神请教一下不足之处,喜欢就顶一个! |
|