#include "Timer.h"
/* 进行长短按键判断时,判断步骤0,1,2 ,对应VT_Key.key_sta */
#define KEY_STA_0 0 // 按键按下
#define KEY_STA_1 1 // 确认按键按下
#define KEY_STA_2 2 // 判断长短按键
/* 按键结构体 */
struct MY_Key
{
uint8_t key_sta; // 步骤标志位
bool key_single; // 按键状态位
bool key_short; // 短按键标志位
bool key_long; // 长按键标志位
uint8_t key_time; // 软件计时(ms)
};
uint8_t Count_10ms = 0;
bool Count_500ms_flag = 0;
struct MY_Key User_Key = {0};
uint8_t short_key_sta = 0; // 短按键次数
/**
* @brief tmr1 configuration.
* @param none
* @retval none
* 配置定时器1,使其以1Hz的频率触发溢出中断,并在溢出时执行相应的中断处理程序
*/
void tmr1_config(void)
{
crm_clocks_freq_type crm_clocks_freq_struct = {0}; //定义并初始化系统时钟频率结构体
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct); //获取系统时钟频率
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE); //启用定时器1的外设时钟:144MHZ
/* (systemclock / (144M/144)) / 10000 = 100Hz(0.001s=10ms) */
// system_core_clock 高速内部时钟(high speed internal clock) HICK_VALUE 的频率为8MHz!!!!!
tmr_base_init(TMR1, 9999, 143); //初始化定时器基本参数:能推出 TMR1 的时钟源为系统时钟
tmr_cnt_dir_set(TMR1, TMR_COUNT_UP); //设置定时器计数方向为 向上计数
tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1); //设置定时器时钟源分频
tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE); //使能定时器1的 溢出 中断
nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 0); //使能定时器1的 NVIC 中断
}
/**
* @brief tmr1 interrupt handler
* @param none
* @retval none
*/
void TMR1_OVF_TMR10_IRQHandler(void)
{
//检查定时器溢出中断标志位是否被设置:定时中断
if(tmr_interrupt_flag_get(TMR1,TMR_OVF_FLAG) != RESET)
{
at32_led_toggle(LED2); // 100次中断/秒 = 0.01s(10ms)/次
/* delay 500ms */
Count_10ms++;
if(Count_10ms == 50)
{
at32_led_toggle(LED3); //0.01s(10ms) * 50 = 500ms
Count_500ms_flag = true;
Count_10ms = 0;
}
/* Key Handle */
User_Key.key_single = at32_button_state(); // 获取按键状态
/* 判断步骤进行到哪一步:定时器每10ms进入一次中断(switch) */
switch(User_Key.key_sta)
{
/* 步骤一:按键按下,计时清零,进入步骤1 */
case KEY_STA_0:
if(User_Key.key_single == RESET)
{
User_Key.key_time = 0;
User_Key.key_sta = KEY_STA_1;
}
break;
/* 步骤二:确认按键按下,进入步骤2,否则进入步骤1 */
case KEY_STA_1:
if(User_Key.key_single == RESET)
{
User_Key.key_sta = KEY_STA_2;
}
else
{
User_Key.key_sta = KEY_STA_0;
}
break;
/* 步骤三:长短按键界限可自定义,若按键仍然按下,开始计时 */
case KEY_STA_2:
if(User_Key.key_single == SET)
{
if(User_Key.key_time <= 100) // 长短按键时间界限:100*10ms
{
at32_led_toggle(LED4);
User_Key.key_short = 1;
User_Key.key_sta = 0;
}
User_Key.key_time = 0;
}
else
{
User_Key.key_time++;
if(User_Key.key_time > 100)
{
User_Key.key_long = 1;
}
}
break;
default:
//Serial_SendString("Unknown state\n");
break;
}
tmr_flag_clear(TMR1,TMR_OVF_FLAG);
}
}
/* 获取并更新500ms标志位*/
bool Get_500ms(void)
{
bool Retuen_500ms_flag = Count_500ms_flag;
Count_500ms_flag = false;
return Retuen_500ms_flag;
}
/* 获取并更新按键次数*/
uint8_t Get_short_key_sta(void)
{
bool short_key_flag = User_Key.key_short;
if(short_key_flag == true) // 短按键标志位判断
{
short_key_sta++;
if(short_key_sta == 3) // 计数范围0~2
{
short_key_sta = 0;
}
/* 测试 */
// char Print_Text[30] = {0};
// sprintf(Print_Text, "short_key_sta:%d \r\n", short_key_sta);
// Serial_SendArray((uint8_t *)Print_Text, strlen(Print_Text));
}
/* 长短按键标志位均清零 */
User_Key.key_short = false;
User_Key.key_long = false;
short_key_flag = false;
return short_key_sta;
}
【雅特力AT32-KEY-TMR】定时器实现延时消抖与长短按键判断(话不多说上源码)
于 2024-09-30 18:57:15 首次发布