stm32中断按键去抖
但是效果不是特别好。
用我这个吧,调试好的已经,按键不占用程序时间,只检测状态,在中断中运行
define _KEY_BOARD_C
#include"delay.h"
#include"key.h"
#include"main.h"
u8 KeySta[3] = {1,1,1}; //当前按键状态
u8 KeyCodeMaps[3] = {
'1','2','3'
};
void KeyInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能其时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//输入上拉
GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化按键端口PC2,3,5;
}
void KeyDriver(void)
{
static u8 backup[3] = {1,1,1}; //按键值备份,保存前一次的值
u8 i = 0;
for(i = 0; i < 3; i++)
{
if(KeySta[i] != backup[i])
{
if(backup[i] == 0)
{
KeyAction(KeyCodeMaps[i]);
}
backup[i] = KeySta[i];
}
}
}
void KeyAction(u8 keycode)
{
if(keycode == '1')
{
}
else if(keycode == '2')
{
}
else if(keycode == '3')
{
}
}
/*******************************************************************************
* 文件名:void TIMX_Configuration(u16 arr,u16 psc)
* 描 述: 定时器3初始化配置函数
* 功 能:刷新
* 作 者:大核桃
* 版本号:1.0.1(2015.03.03)
*******************************************************************************/
/*计算中断时间,计算公式如下:
*Tout= ((arr+1)*(psc+1))/Tclk;
*其中:
*Tclk:TIM3 的输入时钟频率(单位为 Mhz)72MHz
*Tout:TIM3 溢出时间(单位为 us)
*/
void TIM3_Configuration(u16 arr,u16 psc)//通用定时器(2,3,4,5)的配置函数
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);//使能定时器3,APB1PeriphClock
//定时器 TIM3 初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc;//设置时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_div1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //②初始化 TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //③允许更新中断
TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
}
void KeyScan(void)
{
static u8 keybuf[3] = {0xFF,0XFF,0XFF}; //按键扫描缓冲区,保存一段时间内的扫描值
u8 i = 0;
keybuf[0] = (keybuf[0] << 1) | KEY1;
keybuf[1] = (keybuf[1] << 1) | KEY2;
keybuf[2] = (keybuf[2] << 1) | KEY3;
for(i = 0; i< 3; i++)
{
if(keybuf[i] == 0x00)
{
KeySta[i] = 0;
}
else if(keybuf[i] == 0XFF)
{
KeySta[i] = 1;
}
else
{
}
}
}
/*******************************************************************************
* 文件名:void TIM3_NVIC_Config(void)
* 描 述: 定时器3中断优先级管理
* 功 能:刷新
* 作 者:大核桃
* 版本号:1.0.1(2015.03.03)
*******************************************************************************/
void TIM3_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
//通用定时器(2,3,4,5)中断优先级 NVIC 设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级1级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //④初始化 NVIC 寄存器
}
/*******************************************************************************
* 文件名:定时器3中断服务函数
* 描 述:
* 功 能:刷新
* 作 者:大核桃
* 版本号:1.0.1(2015.03.03)
*******************************************************************************/
void TIM3_IRQHandler(void) //TIM3 中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否
{
KeyScan();
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除 TIM3 更新中断标志
}
}
呵呵,大核桃!
你确定用定时扫描好?
我要是按住不放呢!
按键滤波采用定时扫描还是比较好的,可以不用delay了,只是每次按键扫描时间到设置一个变量标志++,可以解决长按还有按键处于什么状态执行的问题
可以使用SYSTick定时器代替TIM3吗?这样可以省一个定时器出来呢,呵呵
你想做长按键也可以啊,这个程序
你可以试试,呵呵,我没弄过
所问问题好了吗?
我感觉我采纳的那个就行了,我这段没弄这个
谢谢分享学习一下
这个比延时的要好高明的多,以前也看过一篇类似的文章,写的很经典!
谢谢分享学习一下
其实是占程序时间的,只不过是在中断中占用了。
这种方法又叫连续扫描法,没有延时函数,利用计数器延时判断。但是这种方法在主程序需要连续采样转换的时候不合适。因为中断会打断采样转换的连续性。
当主程序需要死循环连续采样不能间断的时候,就适合按键用外部中断触发。因为平时不用按键,主程序可以连续运行,只有调试的时候才使用按键。如果使用定时器中断查询按键,你想想程序还能工作吗?
点到他的穴了