Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/47: Рейтинг темы: голосов - 47, средняя оценка - 4.91
7 / 7 / 0
Регистрация: 26.11.2018
Сообщений: 262

Создание меню для LCD на основе micromenu

16.04.2021, 18:43. Показов 9684. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Пробую прикрепить микроменю для LCD екрена.
Честно говоря многое не понятного в коде. До этого момента я делал маленькое "меню" для маленького экрана и с минимальным количеством пунктов в нем. Там использовал switch. понимая, что такой подход, мягко говоря, не подходит для большинства проектов, я решил сделать все как по красоте.
За основу взял данный блог https://stm32withoutfear.blogs... enu-2.html

В настоящее время сделал только три основных меню, и перехожу по ним используя кнопки BUTTON_UP и BUTTON_DOWN. Отображается на LCD только один пункт меню. Не понятно, как сделать меню которое бы отражало рабочую зону на экране, допустим, 5 основных меню, когда общее количество пунктов меню есть 10.



C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "main.h"
 
#include "LCD.h"
 
#include "ILI9341_Touchscreen.h"
#include "ILI9341_STM32_Driver.h"
#include "ILI9341_GFX.h"
#include "snow_tiger.h"
 
#include <string.h>
 
extern RNG_HandleTypeDef hrng;
 
static uint8_t getPressKey(void);               // Function for read data from keyboard    // Simulation
static void Generic_Write(const char* Text);    // Function for print text on LCD
 
 
/** This is used when an invalid menu handle is required in
 *  a \ref MENU_ITEM() definition, i.e. to indicate that a
 *  menu has no linked parent, child, next or previous entry.
 */
Menu_Item_t NULL_MENU = {0};
 
/** \internal
 *  Pointer to the generic menu text display function
 *  callback, to display the configured text of a menu item
 *  if no menu-specific display function has been set
 *  in the select menu item.
 */
static void (*MenuWriteFunc)(const char* Text) = NULL;
 
/** \internal
 *  Pointer to the currently selected menu item.
 */
static Menu_Item_t* CurrentMenuItem = &NULL_MENU;
//-------------------------------------------------------------------------------------------
 
//bool flagPressed = false;                     // flag pressed key
 
#define BUTTONn 5                           // How many buttons use
 
typedef enum                                // Enumeration for button state
{
  BUTTON_LEFT   = 0,
  BUTTON_UP   = 1,
  BUTTON_DOWN   = 2,
  BUTTON_RIGHT   = 3,
  BUTTON_SELECT  = 4,
  BUTTON_NOTHING  = 255
} Button_TypeDef;
 
// Menus  Name | Next | Prev | Parent | Child | SelectFunction | EnterFunction | Text
MENU_ITEM(Menu_1, Menu_2, Menu_3, NULL_MENU, NULL_MENU, NULL, NULL, "tMenu-1");
MENU_ITEM(Menu_2, Menu_3, Menu_1, NULL_MENU, NULL_MENU, NULL, NULL, "tMenu-2");
MENU_ITEM(Menu_3, Menu_1, Menu_2, NULL_MENU, NULL_MENU, NULL, NULL, "tMenu-3");
 
bool flagPressed = false;                       // flag presed key
 
void menu()
{
//  bool flagPressed = false;                       // flag presed key
    //Menu_Navigate(&Menu_1);           // <<<<<<< What ti i????????????????????????
    Menu_SetGenericWriteCallback(Generic_Write);
    Menu_Navigate(&Menu_1);
    while (1)
      {
       uint8_t pressed_key = getPressKey();
 
       if (pressed_key != BUTTON_NOTHING && !flagPressed)
       {
//          Menu_Navigate(&Menu_1);         // <<<<<<< What ti i????????????????????????
            //Menu_SetGenericWriteCallback(Generic_Write);  // print menu
            flagPressed = true;
            pressed_key = getPressKey();
            switch(pressed_key)
            {
             case BUTTON_LEFT:
              Menu_Navigate(MENU_PARENT);
              break;
             case BUTTON_UP:
              Menu_Navigate(MENU_PREVIOUS);
              break;
             case BUTTON_DOWN:
              Menu_Navigate(MENU_NEXT);
              break;
             case BUTTON_RIGHT:
              Menu_Navigate(MENU_CHILD);
              break;
             case BUTTON_SELECT:
              Menu_EnterCurrentItem();
              break;
             default:
              break;
            }
       }
       else if (getPressKey() == BUTTON_NOTHING && flagPressed)
       {
           flagPressed = false;
       }
 
      }
}
// -----------------------------------------------------------------------
static uint8_t getPressKey()        // Simulation keyboard
{
////    BUTTON_LEFT   = 0,
////    BUTTON_UP   = 1,
////  BUTTON_DOWN   = 2,
////    BUTTON_RIGHT   = 3,
////    BUTTON_SELECT  = 4,
////    BUTTON_NOTHING  = 255
//  //flagPressed = true;
 
 
    char digit = '\0';
    char buff_lcd[20] = "KEY: ";
    digit = read_one_digit_from_keyboard();
    switch(digit)
    {
        flagPressed = true;         // Flag: Key was pressed
        case '0':
        {
            strncat(buff_lcd, &digit, 1);
            ILI9341_Draw_Text( buff_lcd, 10, 180, WHITE, 3, BLACK);
            return BUTTON_LEFT;
        }
        case '1':
        {
            strncat(buff_lcd, &digit, 1);
            ILI9341_Draw_Text( buff_lcd, 10, 180, WHITE, 3, BLACK);
            return BUTTON_UP;
        }
        case '2':
        {
            strncat(buff_lcd, &digit, 1);
            ILI9341_Draw_Text( buff_lcd, 10, 180, WHITE, 3, BLACK);
            return BUTTON_DOWN;
        }
        case '3':
        {
            strncat(buff_lcd, &digit, 1);
            ILI9341_Draw_Text( buff_lcd, 10, 180, WHITE, 3, BLACK);
            return BUTTON_RIGHT;
        }
        case '4':
        {
            strncat(buff_lcd, &digit, 1);
            ILI9341_Draw_Text( buff_lcd, 10, 180, WHITE, 3, BLACK);
            return BUTTON_SELECT;
        }
        default:
            return BUTTON_NOTHING;
            break;
    }
}
// -----------------------------------------------------------------------
void Generic_Write(const char* Text)
{
    if (Text)
    {
//      lcdClrScr();
//      lcdPuts(Text);
 
        ILI9341_Draw_Text( "                   ", 10, 10, WHITE, 3, BLACK);
        ILI9341_Draw_Text( Text, 10, 10, WHITE, 3, BLACK);
    }
}
// -----------------------------------------------------------------------
Menu_Item_t* Menu_GetCurrentMenu(void)
{
 return CurrentMenuItem;
}
// -----------------------------------------------------------------------
void Menu_Navigate(Menu_Item_t* const NewMenu)
{
 if ((NewMenu == &NULL_MENU) || (NewMenu == NULL))
 {
     return;
 }
 
 CurrentMenuItem = NewMenu;
 
 if (MenuWriteFunc)
 {
     MenuWriteFunc(CurrentMenuItem->Text);
 }
 
 void (*SelectCallback)(void) = CurrentMenuItem->SelectCallback;
 
 if (SelectCallback)
 {
     SelectCallback();
 }
}
// -----------------------------------------------------------------------
void Menu_SetGenericWriteCallback(void (*WriteFunc)(const char* Text))
{
 MenuWriteFunc = WriteFunc;
 Menu_Navigate(CurrentMenuItem);
}
// -----------------------------------------------------------------------
void Menu_EnterCurrentItem(void)
{
 if ((CurrentMenuItem == &NULL_MENU) || (CurrentMenuItem == NULL))
  return;
 
 void (*EnterCallback)(void) = CurrentMenuItem->EnterCallback;
 
 if (EnterCallback)
  EnterCallback();
}// -----------------------------------------------------------------------
.h
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
////////////////////////////////////////////////////////////
// MICRO-MENU
 
void menu(void);                         // FUNCTION FOR TEST !!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
#include <stddef.h>
 
 /** Type define for a menu item. Menu items should be initialized via the helper
  *  macro \ref MENU_ITEM(), not created from this type directly in user-code.
  */
 typedef const struct Menu_Item {
  const struct Menu_Item *Next; /**< Pointer to the next menu item of this menu item */
  const struct Menu_Item *Previous; /**< Pointer to the previous menu item of this menu item */
  const struct Menu_Item *Parent; /**< Pointer to the parent menu item of this menu item */
  const struct Menu_Item *Child; /**< Pointer to the child menu item of this menu item */
  void (*SelectCallback)(void); /**< Pointer to the optional menu-specific select callback of this menu item */
  void (*EnterCallback)(void); /**< Pointer to the optional menu-specific enter callback of this menu item */
  const char Text[]; /**< Menu item text to pass to the menu display callback function */
 } Menu_Item_t;
 
 /** Creates a new menu item entry with the specified links and callbacks.
  *
  *  \param[in] Name      Name of the menu entry, must be unique.
  *  \param[in] Next      Name of the next linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Previous  Name of the previous linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Parent    Name of the parent linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Child     Name of the child linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] SelectFunc  Function callback to execute when the menu item is selected, or \c NULL for no callback.
  *  \param[in] EnterFunc   Function callback to execute when the menu item is entered, or \c NULL for no callback.
  */
 #define MENU_ITEM(Name, Next, Previous, Parent, Child, SelectFunc, EnterFunc, Text) \
  extern Menu_Item_t const Next;     \
  extern Menu_Item_t const Previous; \
  extern Menu_Item_t const Parent;   \
  extern Menu_Item_t const Child;  \
  Menu_Item_t const Name = {&Next, &Previous, &Parent, &Child, SelectFunc, EnterFunc, Text}
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the menu parent. */
 #define MENU_PARENT         (Menu_GetCurrentMenu()->Parent)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the menu child. */
 #define MENU_CHILD          (Menu_GetCurrentMenu()->Child)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the next linked menu item. */
 #define MENU_NEXT           (Menu_GetCurrentMenu()->Next)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the previous linked menu item. */
 #define MENU_PREVIOUS       (Menu_GetCurrentMenu()->Previous)
 
 /** Null menu entry, used in \ref MENU_ITEM() definitions where no menu link is to be made. */
 extern Menu_Item_t NULL_MENU;
 
 /** Retrieves the currently selected meny item.
  *
  *  \return Pointer to the currently selected meny item.
  */
 Menu_Item_t* Menu_GetCurrentMenu(void);
 
 /** Navigates to an absolute or relative menu entry.
  *
  * \param[in] NewMenu  Pointer to the absolute menu item to select, or one of \ref MENU_PARENT,
  *                     \ref MENU_CHILD, \ref MENU_NEXT or \ref MENU_PREVIOUS for relative navigation.
  */
 void Menu_Navigate(Menu_Item_t* const NewMenu);
 
 /** Configures the menu text write callback function, fired for all menu items. Within this callback
  *  function the user should implement code to display the current menu text stored in \ref MENU_ITEM_STORAGE
  *  memory space.
  *
  *  \ref WriteFunc  Pointer to a callback function to execute for each selected menu item.
  */
 void Menu_SetGenericWriteCallback(void (*WriteFunc)(const char* Text));
 
 /** Enters the currently selected menu item, running its configured callback function (if any). */
 void Menu_EnterCurrentItem(void);
 
////////////////////////////////////////////////////////////
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.04.2021, 18:43
Ответы с готовыми решениями:

Создание трехуровневого меню на основе двухуровневого
помогите,пожалуйста, сделать меню,чтобы в нем было 3 уровню....вот есть 2х уровневое, нужно переделать под 3х. &lt;ul...

MicroMenu для ARM
Портирую MicroMenu в ARM. Выскакивает куча ошибок. Я уже окончательно запутался. Кто нибудь работал с ним? MicroMenu.h ...

STM32F4Discovery + LCD через fsmc для индентификации мк LCD
Нужна помощь, может кто поделиться готовым проектом,чтобы на STM32F4-Dyscovery используя параллельную шину FSMC можно было быстро...

5
7 / 7 / 0
Регистрация: 26.11.2018
Сообщений: 262
17.04.2021, 12:29  [ТС]
Не понимаю, этот код. Создается структура Menu_Item с нее создается экземпляр структуры Menu_Item_t.
А дальше есть непонятные дефайны, непонятно что они делают. Кто-то может подсказать что происходит?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 typedef const struct Menu_Item {
  const struct Menu_Item *Next; /**< Pointer to the next menu item of this menu item */
  const struct Menu_Item *Previous; /**< Pointer to the previous menu item of this menu item */
  const struct Menu_Item *Parent; /**< Pointer to the parent menu item of this menu item */
  const struct Menu_Item *Child; /**< Pointer to the child menu item of this menu item */
  void (*SelectCallback)(void); /**< Pointer to the optional menu-specific select callback of this menu item */
  void (*EnterCallback)(void); /**< Pointer to the optional menu-specific enter callback of this menu item */
  const char Text[]; /**< Menu item text to pass to the menu display callback function */
 } Menu_Item_t;
 
 /** Creates a new menu item entry with the specified links and callbacks.
  *
  *  \param[in] Name      Name of the menu entry, must be unique.
  *  \param[in] Next      Name of the next linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Previous  Name of the previous linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Parent    Name of the parent linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] Child     Name of the child linked menu item, or \ref NULL_MENU if no menu link.
  *  \param[in] SelectFunc  Function callback to execute when the menu item is selected, or \c NULL for no callback.
  *  \param[in] EnterFunc   Function callback to execute when the menu item is entered, or \c NULL for no callback.
  */
 #define MENU_ITEM(Name, Next, Previous, Parent, Child, SelectFunc, EnterFunc, Text) \
  extern Menu_Item_t const Next;     \
  extern Menu_Item_t const Previous; \
  extern Menu_Item_t const Parent;   \
  extern Menu_Item_t const Child;  \
  Menu_Item_t const Name = {&Next, &Previous, &Parent, &Child, SelectFunc, EnterFunc, Text}
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the menu parent. */
 #define MENU_PARENT         (Menu_GetCurrentMenu()->Parent)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the menu child. */
 #define MENU_CHILD          (Menu_GetCurrentMenu()->Child)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the next linked menu item. */
 #define MENU_NEXT           (Menu_GetCurrentMenu()->Next)
 
 /** Relative navigational menu entry for \ref Menu_Navigate(), to move to the previous linked menu item. */
 #define MENU_PREVIOUS       (Menu_GetCurrentMenu()->Previous)
Добавлено через 5 минут
Добавил в третье меню функцию которая включает или виключает свитлдодиод. Но все выводится только в одну строку экрана..

Добавлено через 14 минут
как можно выводить на экран все начальное меню, а при переходе в подменю, удалять с экрана начальное меню, а выводить все подменю выбранного меню ??

C
1
2
3
4
MENU_ITEM(Menu_1, Menu_2, Menu_3, NULL_MENU, Menu_1_1, NULL, NULL, "Menu-1");
MENU_ITEM(Menu_2, Menu_3, Menu_1, NULL_MENU, NULL_MENU, NULL, NULL, "Menu-2");
//MENU_ITEM(Menu_3, Menu_1, Menu_2, NULL_MENU, NULL_MENU, NULL, NULL, "Menu-3");
MENU_ITEM(Menu_3, Menu_1, Menu_2, NULL_MENU, NULL_MENU, NULL, Level1Item3_Enter, "Enter ON/OFF red LED");
1
1 / 1 / 0
Регистрация: 26.05.2021
Сообщений: 80
17.01.2022, 11:26
Подскажите, разобрались ли вы с меню? или так и забросили. а то я тоже мучаюсь не могу понять как это работает.
не понятно что за элементы Menu_1, Menu_2. от куда они взялись. это ведь не перечисления и не дефайны...
C++
1
MENU_ITEM(Menu_1, Menu_2, Menu_3, NULL_MENU, Menu_1_1, NULL, NULL, "Menu-1");
0
7 / 7 / 0
Регистрация: 26.11.2018
Сообщений: 262
17.01.2022, 11:50  [ТС]
Цитата Сообщение от Ramzess1488 Посмотреть сообщение
Подскажите, разобрались ли вы с меню? или так и забросили. а то я тоже мучаюсь не могу понять как это работает.
Я его переделал под свой OLED экран и добавил еще скроллбар. Могу дать ссылку на этот проект на github.
выглядит тестовое меню следующим образом:
https://www.youtube.com/watch?v=lXIVXaiC9_o
0
1 / 1 / 0
Регистрация: 26.05.2021
Сообщений: 80
17.01.2022, 12:15
Буду благодарен если сбросите.
А что на счет пунктов Menu_1, Menu_2, не знаете что это за объекты?
0
7 / 7 / 0
Регистрация: 26.11.2018
Сообщений: 262
17.01.2022, 12:45  [ТС]
Цитата Сообщение от Ramzess1488 Посмотреть сообщение
А что на счет пунктов Menu_1, Menu_2, не знаете что это за объекты?
это указатели на экземпляры структуры. Menu_Item_t. Каждый элемент меню основан на структуре Menu_Item. Четыре первых поля которой это ссылки на соответствующие меню, и отвечают за навигацию по меню.
Для того чтобы понять как работает меню, и самостоятельно его сделать я рекомендую Вам ознакомиться с таким понятием как связанный список. Мне это очень помогло, потому что без теории я долго разбирался с этим кодом.

Цитата Сообщение от Ramzess1488 Посмотреть сообщение
Буду благодарен если сбросите.
https://github.com/OlegDemk/MENU_OLED
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.01.2022, 12:45
Помогаю со студенческими работами здесь

Создание класса конструктора для создание объектов в Higchart на основе массивов данных
Привет всем! Нужна ваша помощь в создании управляемой диаграммы. С помощью библиотеки Higchart, я создала круговую диаграмму. В этой...

Меню на LCD
Как грамотно реализовать меню для вывода на LCD дисплей? Кто нибудь реализовывал? Дисплей на HD44780 2х строчный на 16...

Меню lcd stm32f429i
Привет! Нужна реализация многоуровневого меню для stm32f429 tft lcd. Можете поделится советом как реализовать алгоритм.

Делаю меню на LCD CX65
Заимел 5 штук дисплеев cx65. таки освоил как его подключать и даже вывел тестовую программу. и даже связал всё это удовольствие с RTOS ...

Реализация древовидного меню в LCD на МК
Здравствуйте, вобщем у меня есть задание написать меню,которое будет выводиться на lcd экран , для atmega16 , я программист си шарп ,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru