/*** * @Author: * @Date: 2023-08-01 19:47:20 * @LastEditors: xxx * @LastEditTime: 2023-08-01 19:48:10 * @Description: 这是一个简单的菜单系统实现,包括菜单页面的创建、添加、获取、注册按键、检测菜单定时器和关闭菜单定时器的函数。菜单系统使用定时器发送消息,当定时器过期时,菜单系统将发送消息给下一个页面或刷新当前页面 * @email: * @Copyright (c) 2023 by xxx, All Rights Reserved. */ /** * 使用教程 #include "menu.h" // 定义菜单项 menu_txt_t menu_items[] = { {"选项1", MENU_WHAT(NULL)}, {"选项2", MENU_WHAT(NULL)}, {"选项3", MENU_WHAT(NULL)}, }; menu_page_t page1 = { 1, 0, 0, 1, NULL }; menu_page_t page2 = { 2, 1, 0, 2, NULL }; menu_page_t page3 = { 3, 1, 0, 3, NULL }; void page1_operate() { // 在这里实现选项1的功能 printf("选项1的功能实现\n"); } void page2_operate() { // 在这里实现选项2的功能 printf("选项2的功能实现\n"); } void page3_operate() { // 在这里实现选项3的功能 printf("选项3的功能实现\n"); } int main(void) { menu_t *menu = menu_create(1000); // 创建菜单,每隔1000毫秒刷新一次 menu_page_add(&page1); menu_page_add(&page2); menu_page_add(&page3); menu_key_register(KEY_UP); // 注册上键 menu_key_register(KEY_DOWN); // 注册下键 menu_key_register(KEY_ENT); // 注册进入键 menu_timer_start(1000, WM_CREATE); // 启动菜单定时器,每隔1000毫秒发送一次创建消息 while (1) { menu_detection(); // 检测菜单定时器 if (menu->wm_msg == WM_CREATE) { // 刷新当前窗体 menu->wm_msg = 0; } else if (menu->wm_msg == WM_NEXT) { // 下一个窗体 menu->current_index = (menu->current_index + 1) % menu->pages->cnt; menu->wm_msg = 0; } else if (menu->wm_msg == WM_REFUSH) { // 刷新当前窗体 menu->wm_msg = 0; } menu_page_t *cur_page = get_menu_page(menu->current_index); if (cur_page != NULL) { cur_page->CurrentOperate(); } delay_ms(10); } return 0; } */ #ifndef __MENU_H__ #define __MENU_H__ #include "lib.h" #define KEY_ESC BIT1 // 返回 #define KEY_UP BIT2 // 上 #define KEY_DOWN BIT3 // 下 #define KEY_ENT BIT4 // 确认 #define KEY_LEFT BIT5 // 左 #define KEY_RIGHT BIT6 // 右 #define KEY_AUTO BIT7 // 自动 #define WM_CREATE BIT8 // 创建 #define WM_REFUSH BIT9 // 用于刷新当前窗体 #define WM_NEXT BIT10 // 下一个窗体 #define WM_LONG BIT11 // 长按 #define WM_LOADING BIT12 // 加载中 #define WM_COMPLETE BIT13 // 加载完成 #define KEY_IS_LONG(st) (st & WM_LONG) #define MENU_WHAT(n) \ { \ (uint8_t **)n, (sizeof(n) / sizeof(uint8_t *)), 0 \ } typedef struct MENU_TXT menu_txt_t; typedef struct MENU menu_t; // Bar型菜单的数据结构 struct MENU_TXT { uint8_t **Text; // 指向显示内容数组的指针 uint8_t TextNum; // 项个数 void *(*Action)(); // 对应的执行函数 }; // 父窗 函数 (索引号从1开始,0表示没有下一个窗体,也没有父窗体) typedef struct { uint8_t Index; // 窗体索引号 (从1开始) uint8_t FatherIndex; // 父窗体索引号 uint8_t CurItem; // 当前状态索引号 uint8_t NextItem; // 下个窗体的索引号 (从1开始) void (*CurrentOperate)(); // 当前状态应该执行的功能操作 } menu_page_t; struct MENU { uint16_t menu_ticks; // 菜单刷新时间 clist_node_t *pages; // 窗体链表 volatile uint64_t wm_msg; // 窗体消息 uint8_t current_index; // 当前窗体索引号 uint32_t key_long_ticks; // 长按时间 uint8_t dir; // 按键方向 0:正常, 1:180度 }; extern menu_t *menu_create(uint16_t menu_ticks); // 创建菜单 extern void menu_rebuild(void); extern menu_t *get_menu(void); // 获取菜单 extern void menu_page_add(menu_page_t *page); // 添加菜单页面 extern menu_page_t *get_menu_page(uint8_t index); // 获取菜单页面 extern menu_page_t *get_menu_sub_page(uint8_t index, uint8_t sub_index); // 获取菜单子页面 extern uint8_t get_menu_sub_page_count(uint8_t index, uint8_t sub_index); // 获取菜单子页面个数 extern void menu_key_register(uint64_t key); // 注册按键 extern void menu_key_long_start(void); // 开始长按 extern void menu_key_long_stop(void); // 停止长按 extern void menu_set_scandir(uint8_t dir); // 设置菜单扫描方向 extern void menu_set_ticks(uint16_t menu_ticks); // 设置菜单刷新时间 extern void menu_detection(void); // 菜单检测 extern void menu_timer_start(uint16_t time, uint64_t wm_msg); // 启动菜单定时器 extern void menu_timer_stop(void); // 关闭菜单定时器 #endif // __MENU_H__