HALSTM32通用定时器+EXTI实现单击/双击/长按功能
- ✨在使用USB功率计的时候,发现上面的一个按键实现多画面功能切换,于是探索了一下是如何实现的,将其实现的基本思路以及综合网上收集的相关实现方法,粗陋的整理了一下,将其基本功能实现了一下,具体的功能没有做,只是做了一个简单的框架。
🛠HAL STM32CubeMX工程配置
-
🌿基于
STM32F103
芯片。 -
🌿主要配置一个外部中断按键引脚。
-
🔖GPIO引脚按键外部使用电路参考:
-
🌿配置一个定时器
-
🌿NVIC中断使能以及优先级配置。
-
🌿其他串口和I2C配置用于显示和调试输出。(这里根据个人需求配置,个人推荐还是使用软件I2C实现比较好,硬件I2C如果程序比较复杂,cpu处理各种中断,容易导致硬件I2C出错,导致显示画面异常的情况。)
-
🌿其他时钟配置和工程生成就不展示了,根据个人情况配置。
⛳功能实现
- 🌿完善按键中断回调内容
//重写回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{/*判断是中断引脚*/if(GPIO_Pin == KEY_Pin){Trg++;HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5);//状态翻转}
}
- 🌿定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{static uint32_t click = 0;static char keyStatus = 0;static char LongPress = 0;if(htim ->Instance == TIM6){if(++cnt_1ms >= 1000){cnt_1ms = 0;HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);//状态翻转}if(Trg > 0){keyStatus = HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin);//读取按键状态click++;if((click > _debounce_ms) && (keyStatus == 1) && (LongPress == 0)) //1000{if((Trg == 1) || (Trg > 2)) //单击{Trg = 0;funIndex ++;printf("_click_ms,%d\r\n", funIndex);click = 0;//清零}if(Trg == 2) //双击{Trg = 0;funIndex += 2;printf("_doubleClick %d\r\n", funIndex);click = 0;//清零}}if((click > _press_ms) && (keyStatus == 0) && (LongPress == 0)) //1000{printf("_longPressStart\r\n");LongPress = 1;}if((LongPress == 1) && (keyStatus == 1)){LongPress = 0;Trg = 0;funIndex += 3;//松开才赋值click = 0;printf("_longPressStop %d\r\n", funIndex);}}if(funIndex > 8)funIndex = 0;}
}
- 🌿oled驱动显示内容,可以根据个人使用的屏幕规格型号自行完善,个人使用的是SH1106 1.3“寸的OLED屏幕作为显示。
- 🌿按键菜单显示内容参考网上的内容。
unsigned char funIndex = 0;//9和0->1-1
void menu11(void);
void menu12(void);
void menu21(void);
void menu22(void);
void menu23(void);
void menu31(void);
void menu32(void);
void menu33(void);
void menu34(void);
//定义按键操作数据
KEY_TABLE table[9] =
{{0, 0, 1, 0, 2, (*menu11)},{1, 0, 1, 1, 4, (*menu12)},{2, 2, 3, 0, 5, (*menu21)},{3, 2, 3, 0, 7, (*menu22)},{4, 4, 4, 1, 4, (*menu23)},{5, 5, 6, 2, 5, (*menu31)},{6, 5, 6, 2, 6, (*menu32)},{7, 7, 8, 3, 7, (*menu33)},{8, 7, 8, 3, 8, (*menu34)},
};void ShowMenu(int16_t x, int16_t y,char *text)
{OLED_ShowString(x, y, text, 12);//x,y,字符串,字体大小
}//一级菜单1
void menu11(void)
{// OLED_Clear();OLED_ShowString(36, 6, "menu1-1", 16);
}//一级菜单2
void menu12(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu1-2", 16);
}//二级菜单1
void menu21(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu2-1", 16);
}//二级菜单2
void menu22(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu2-2", 16);
}//二级菜单3
void menu23(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu2-3", 16);}//三级菜单1
void menu31(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu3-1", 16);
}//三级菜单2
void menu32(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu3-2", 16);
}//三级菜单3
void menu33(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu3-3", 16);
}//三级菜单4
void menu34(void)
{
// OLED_Clear();OLED_ShowString(36, 6, "menu3-4", 16);}
- 📝main主函数
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C1_Init();MX_USART1_UART_Init();MX_I2C2_Init();MX_TIM6_Init();/* USER CODE BEGIN 2 */OLED_Init();HAL_TIM_Base_Start_IT(&htim6);ShowMenu(2, 0, "OneKey Mul-Menu");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */current = table[funIndex].operation;//根据需要获取对应需要执行的函数(*current)();//执行获取到的函数}/* USER CODE END 3 */
}
📚工程源码
链接:https://pan.baidu.com/s/1eR14Lpfjqm7nA0lvwbv5xg
提取码:vs7f