延时消抖
阻塞型延时
如果说
while(1)中的 总的延时时间 过长,就会导致 按键检测不灵敏;
延时消抖
按键检测的方法
判断按键按下 IO 口状态的变化; 如:
010:按键没有按下为0;按键按下为1
延时时间的选择
没有硬件消抖
一个按键
消抖时间可以选择为
5~15ms多个按键
消抖时间可以选择为
5~15us
有硬件消抖(加电容)
一个按键
消抖时间可以选择为
1~5ms多个按键
消抖时间可以选择为
1~5us
非阻塞型延时
检测思路
每隔10ms检测一次按键;
如果:按键按下,就让 count++;
否则:检查 count 的当前值为多少;
如果>1就说明按键按下
如果在设定的范围,就说明按键按下了一段时间;
按键短按
//时间轮询,查询
if(Key_TaskTime[0] >= Key_TaskTime[1])
{
if(Get_KeyValue() == 1)
{
Beep_Toggle(BEEP_PORT, BEEP_PIN);
}
Key_TaskTime[0] = 0;
}
//按键
uint8_t Get_KeyValue(void)
{
u8 keyvalue = 0;
static u8 count = 0;
//判断 KEY2是否按下,一直是按下的就 count++
if(KEY2() == 0)
{
count++;
}
else //else执行条件是 按键松开;
{
if(count > 1)
{
keyvalue = 1;
count = 0;
}
else
{
count = 0;
}
}
return keyvalue;
}
按键长按
count 每过 10ms,就加一次,设置好次数,让按键 返回一个 键值;
检查count的值,在自己设定的范围( 10ms*数值=时长 ),就说明按键长按;
uint8_t Get_KeyValue(void)
{
u8 keyvalue = 0;
static u16 count = 0;
//判断 KEY 的引脚如果是低 被按下
if(KEY2() == 0)
{
count++;
}
else //按键松开,判断count的值
{
if((1<count) && (count<100))
{
keyvalue = 1;
count = 0;
}
else if((100<count) && (count<200))
{
keyvalue = 2;
count = 0;
}
else if((200<count) && (count<300))
{
keyvalue = 3;
count = 0;
}
else //count值不符合设定范围
{
count = 0;
}
}
return keyvalue;
}
多种控制:就用switch;用if else太麻烦了;
分段的思想;
if(Get_KeyValue() == 2)
{
switch(flag++) //这样写 flag++,很不错
{
case 0: Motor_TurnRight();break;
case 1: Motor_Stop();break;
}
flag%=2;//这种方法,适合每次+1
}
EXTI外部中断
要求:有硬件消抖;能能产生稳定的上升沿和下降沿;
将外部中断配置为 上升沿/下降沿 触发中断;在中断服务函数设置标志位;
void EXTI_Config(void)
{
//AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//中断线映射
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
//EXTI配置
EXTI_InitTypeDef EXTI_InitStructrue;
EXTI_InitStructrue.EXTI_LineCmd = ENABLE;
EXTI_InitStructrue.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructrue.EXTI_Line = EXTI_Line0;
EXTI_InitStructrue.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructrue);
//NVIC配置
NVIC_SetPriority(EXTI0_IRQn, 3);
NVIC_EnableIRQ(EXTI0_IRQn);
}
//中断服务函数
//EXTI0的中断服务函数
void EXTI0_IRQHandler(void)
{
//清标志
EXTI_ClearFlag(EXTI_Line0);
Led1_Toggle();
}