【前言】
使用菜单系统可以分块展示用户所关心的内容,同时也可以为用户交互提供更加友好的界面。这一篇将分享如何创简单的菜单。
1、创建两个用户菜单的文件menu.c/h

2、菜单设计
这次设计了两个菜单,一个用于展示RTC日期与时间,另一个菜单用于展示心率与血氧。在menu.c中设计菜单显示如下:
// 显示日期页面
static void show_date_page(void)
{
uint32_t timesecond;
uint16_t year;
uint8_t mon, day, hour, min, sec;
timesecond = RTC_GetCount();
RTC_GetDate(timesecond, &year, &mon, &day, &hour, &min, &sec);
OLED_Clear(0);
GUI_ShowString(0, 0, (uint8_t *)"Date Page", 16, 1);
GUI_ShowString(0, 16, (uint8_t *)"------------", 16, 1);
char date_str[20];
snprintf(date_str, sizeof(date_str), "%04d-%02d-%02d", year, mon, day);
GUI_ShowString(0, 32, (uint8_t *)date_str, 16, 1);
char time_str[20];
snprintf(time_str, sizeof(time_str), "%02d:%02d:%02d", hour, min, sec);
GUI_ShowString(0, 48, (uint8_t *)time_str, 16, 1);
OLED_Display();
}
// 显示心率页面
extern BloodData g_blooddata;
static void show_heart_rate_page(void)
{
OLED_Clear(0);
GUI_ShowString(0, 0, (uint8_t *)"Heart Rate Page", 16, 1);
GUI_ShowString(0, 16, (uint8_t *)"------------", 16, 1);
char hr_str[20];
snprintf(hr_str, sizeof(hr_str), "HR: %d BPM", (int)g_blooddata.heart);
GUI_ShowString(0, 32, (uint8_t *)hr_str, 16, 1);
char spo2_str[20];
snprintf(spo2_str, sizeof(spo2_str), "SpO2: %.1f%%", g_blooddata.SpO2);
GUI_ShowString(0, 48, (uint8_t *)spo2_str, 16, 1);
OLED_Display();
}3、菜单的切换,我在前面分享了按键处理的文章:【MAX32625PICO开发板】高效按键处理-电子产品世界论坛
在它的工程基础上,实现当键按下后,实现两个菜单的切换,首先创建菜单刷新任务:
// 菜单刷新任务
void vTaskMenu(void *pvParameters)
{
menu_init();
TickType_t last_wake_time = xTaskGetTickCount();
while (1)
{
if (xSemaphoreTake(xMenuMutex, pdMS_TO_TICKS(100)) == pdTRUE)
{
switch (current_menu)
{
case MENU_DATE:
show_date_page();
break;
case MENU_HEART_RATE:
show_heart_rate_page();
break;
default:
break;
}
xSemaphoreGive(xMenuMutex);
}
vTaskDelayUntil(&last_wake_time, pdMS_TO_TICKS(200));
}
}在按键任务中,如捕获取有按键按下,那么就执行menu中的menu_process_key,并传递event。
void vTaskKeyScan(void *pvParameters)
{
key_init();
while (1)
{
key_event_t event = key_get_click();
if (event != KEY_NONE)
{
menu_process_key(event); // 关键修改:将按键事件传递给菜单系统
printf("Key event: %d\n", event);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}在菜单按键任执行后,解除锁,并根据按键不同,切换菜单
// 处理按键切换菜单
void menu_process_key(key_event_t key)
{
if (xSemaphoreTake(xMenuMutex, pdMS_TO_TICKS(100)) == pdTRUE)
{
if (key == KEY_SW2_CLICK)
{
current_menu = (current_menu + 1) % MENU_COUNT;
printf("Menu changed to: %d\n", current_menu);
}
else if (key == KEY_SW3_CLICK)
{
current_menu = (current_menu - 1 + MENU_COUNT) % MENU_COUNT;
printf("Menu changed to: %d\n", current_menu);
}
xSemaphoreGive(xMenuMutex);
}
}最后,创建一个任务,并在main的任务创建中执行创建菜单任务:
void vCreateMenuTask(void)
{
xTaskCreate(vTaskMenu, "MenuTask", 512, NULL, tskIDLE_PRIORITY + 2, NULL);
}【实现效果】
按下开发板中的SW2、SW3实现菜单切换。
我要赚赏金
