wangxiaozhen

延时消抖

阻塞型延时

如果说while(1)中的 总的延时时间 过长,就会导致 按键检测不灵敏;

延时消抖

按键检测的方法

判断按键按下 IO 口状态的变化; 如:010:按键没有按下为0;按键按下为1

延时时间的选择

没有硬件消抖
  1. 一个按键

    消抖时间可以选择为5~15ms

  2. 多个按键

    消抖时间可以选择为5~15us

有硬件消抖(加电容)
  1. 一个按键

    消抖时间可以选择为1~5ms

  2. 多个按键

    消抖时间可以选择为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;
}

按键长按

  1. count 每过 10ms,就加一次,设置好次数,让按键 返回一个 键值;

  2. 检查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太麻烦了;

分段的思想;

image-20201218140445874
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();
}

分类:

技术点:

相关文章: