STM32F103按键中断消抖问题求教!

null_L 2019-01-18 07:45:13
最近在学习STM32,想实现4个按键的中断控制,现在有几个问题,想问下。
1:按键利用中断方式控制是不是就能避免抖动?
我认为是不行的,所以想在外部中断处理函数中加入延时起到消抖的目的,但是加入延时函数后,中断函数就无法运行,在网上搜索后我发现是不能在中断函数中加入延时的,延时函数如下:
void delay_ms(u32 time)
{
delaytime=time;
while(delaytime!=0);
}
...
void SysTick_Handler(void)
{
delaytime--;
}

2:那么现在有几个解决方案:
一:在中断函数中仅做状态标志传递,在主函数中用switch根据不同的状态值运行具体的程序,这个办法可以,但是我还是不清楚能不能做到消抖。
二:我在网上看到有人修改内核中的这个函数:
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */

SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}

里面的 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);,改为 NVIC_SetPriority (SysTick_IRQn, 1);然后在中断函数中加入延时函数,我试了一下,发现还是不行。
问题有点多,不过是确实想了很久,不知道应该怎么比较好地解决,希望大家不吝赐教!
...全文
2993 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
cjaizss 2019-02-19
  • 打赏
  • 举报
回复
不要用延时,用状态机。
开心发过火 2019-02-17
  • 打赏
  • 举报
回复
用滴答定时器写一个按键状态机 可以完美解决 具体可以参考http://www.51hei.com/bbs/dpj-29115-1.html 上面网页有源码 把Key_State.c理解就可以了
iwetuan 2019-02-08
  • 打赏
  • 举报
回复 2
中断优先级大于systick,时钟得不到更新,死循环在中断函数里
fly 100% 2019-02-03
  • 打赏
  • 举报
回复
多次扫描是常用方式,其实中断也可以去除掉一些抖动,毕竟中断处理前的抖动都被无视了
疯狂低调 2019-02-01
  • 打赏
  • 举报
回复
不错不错学习些学习学
梁阿狸 2019-01-30
  • 打赏
  • 举报
回复
的确,定时器扫描,然后处理按键操作。设置好检测时间,然后定时器中不停调用。实际应用也很少会出现抖动
static void KeyStatusGet(volatile KEY* pKey, u8 power)
{
	//pKey->hardStatus = pKey->keyHardStatus(pKey);
	//if(pKey->keyHardStatus(pKey) == KEY_UP)
	if ((pKey->GPIOx->IDR & pKey->GPIO_Pin) != (uint32_t)Bit_RESET)
	{
		pKey->status = KEY_STATUS_UP;
		pKey->pressCnt = 0;
	}
	else
	{
		pKey->pressCnt += KEY_SCAN_TIME;
		if(pKey->pressCnt >= KEY_NORMAL_DOWN_TIME && pKey->status == KEY_STATUS_UP)
		{
			//if(power)
			//	;//pKey->status = KEY_STATUS_DOWN_POWER;
			//else
				pKey->status = KEY_STATUS_DOWN_NORMAL;
		}
		else if(pKey->pressCnt >= KEY_LONG_DOWN_TIME)
		{
			pKey->pressCnt = KEY_LONG_DOWN_TIME;
			if(pKey->status != KEY_STATUS_DOWN_POWER && power)
				pKey->status = KEY_STATUS_DOWN_POWER;
			else	if(KEY_STATUS_DOWN_LONG != pKey->status && pKey->status != KEY_STATUS_DOWN_POWER)
					pKey->status = KEY_STATUS_DOWN_LONG;
//			if(power == 0 && KEY_STATUS_DOWN_LONG != pKey->status)
//				pKey->status = KEY_STATUS_DOWN_LONG;
		}	
	}
}
平淡风云 2019-01-25
  • 打赏
  • 举报
回复
弄个10ms的延时就行
天渊之灵 2019-01-22
  • 打赏
  • 举报
回复
学到了,一起学习一起进步。
kingkits 2019-01-22
  • 打赏
  • 举报
回复
一般都是4-10ms扫描程序, 2次扫到同样的内容,才会进行按键解码
yishumei 2019-01-21
  • 打赏
  • 举报
回复
dceacho给出的方法非常实用。我补充一下,普通人按下或者抬起按键时的抖动时间大多数在20ms以内,楼主可以用示波器抓一下波形看看,然后根据这个时间确定定时器的扫描时间和计数次数。
dceacho 2019-01-19
  • 打赏
  • 举报
回复 1
没这个复杂 不管什么中断,里面都不要加延时 如果用外部中断的话,你在IO线上并个电容就可以去抖动了 一般按键用定时器扫描,如果被拉低或拉高就计数,反之清初计数,计数到一定值就认为有按键
void timer0(void)
{
    if(io_key==0)keycnt++;else keycnt=0
    if(keycnt==5)key=1;//连续5次都采集到就认为有按键
}

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧