Перейти к содержанию

Пример Реализации Меню На Микроконтроллере


dm37

Рекомендуемые сообщения

Сделал два варианта (попроще и посложнее). Может кому надо. Внутри архива исходники на C (IAR) + проект для Proteus.

Оборудование:

- ATmega32;

- LCD 1602/1604 (HD44780);

- клавиатура (4/8 кнопок);

- 2 регистра ввода (74HC245);

- 2 регистра вывода (74HC573);

- зуммер.

https://ru.files.fm/u/a2sfccuf#/list/

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Проект довольно накрученный, по крайней мере с ходу я не разобрался где задаются пункты меню и как оно организовано на низком уровне. Ну и такое дерево директорий выглядит великоватым для такой задачи.

Ну и хотелось бы посмотреть результат - сколько места занимает само меню (и сколько - каждый пункт) и с какой скоростью выполняется.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

ИМХО в AVR не так много памяти чтобы извращаться указателями на функции входа и выхода. Логичнее и проще сделать общую функцию отображения любого элемента, а само меню реализовать в виде дерева или графа. От узлов все равно ожидается одинаковое поведение - переход по графу или выполнение листьев. От листьев экзотика тоже требуется не всегда: в той версии, которую я делал, большая часть листьев занималась вводом и выводом чисел настроек.

По существу: было бы неплохо все-таки выложить описание, но не где-то в глубине ссылки, а в первом посте (думаю, админы помогут переместить если что) и более по существу.

Ну вопрос объема не раскрыт.

Поскольку описаний реализации меню довольно много (хотя народ все равно сначала городит велосипед и только потом сравнивает с готовым), хорошо бы привести достоинства и недостатки именно вашего варианта.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Мой пример на основе MicroMenu.

проекта на этом меню.

//========================================================================
#ifndef MENU_H

#define MENU_H

#include "menu.h"

#include "main_def_func.h"
//========================================================================

//========================================================================
// Typedefs:
typedef void (*FuncPtr)(void);
//========================================================================

//========================================================================
typedef struct menu_item
{
void		 *Parent;
void		 *Child;
void		 *Next;
void		 *Prev;
FuncPtr	 MenuFunc;
FuncPtr	 EnterFunc;
char __flash *Text;
} menu_item;
//========================================================================

// Externs:
//========================================================================
extern menu_item __flash *CurrMenuItem; // Текущий пункт меню.
extern menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.

extern __flash menu_item Null_Menu;

extern char Menu_Str_Buf []; // Буфер для вывода текста.

extern void (*MenuFuncPtr)(void);
//========================================================================

// Defines and Macros:
//========================================================================
#define NULL_ENTRY Null_Menu
#define NULL_FUNC (void*)0
#define NULL_TEXT 0x00
#define PAGE_MENU 3
//========================================================================

//========================================================================
#define MAKE_MENU(Name, Parent, Child, Next, Prev, MenuFunc, EnterFunc, Text) \
extern menu_item __flash Parent;													 \
extern menu_item __flash Child;													 \
extern menu_item __flash Next;														 \
extern menu_item __flash Prev;														 \
 menu_item __flash Name =													 \
{																					 \
 (menu_item*)	 &Parent,													 \
 (menu_item*)	 &Child,													 \
 (menu_item*)	 &Next,														 \
 (menu_item*)	 &Prev,														 \
					 MenuFunc,													 \
					 EnterFunc,													 \
				 {Text}														 \
}
//========================================================================

//========================================================================
#define PARENT	 *((menu_item __flash*) (CurrMenuItem->Parent))
#define CHILD	 *((menu_item __flash*) (CurrMenuItem->Child))
#define NEXT	 *((menu_item __flash*) (CurrMenuItem->Next))
#define PREV	 *((menu_item __flash*) (CurrMenuItem->Prev))
#define MENU_FUNC *((FuncPtr) (CurrMenuItem->MenuFunc))
#define ENTER_FUNC *((FuncPtr) (CurrMenuItem->EnterFunc))
//========================================================================

//========================================================================
#define SET_MENU_LEVEL(x) \
Set_Menu_Level(&x)

#define SET_MENU_ITEM(x) \
Set_Menu_Item(&x)

#define GO_MENU_FUNC(x) \
MenuFunc((FuncPtr*)&x)

#define EXTERN_MENU(Name) \
extern menu_item __flash Name;
//========================================================================

//========================================================================
enum
{
SET_LEVEL = 0,
SET_NEXT,
SET_PREV,
};
//========================================================================

// Prototypes:
//========================================================================
void Set_Menu_Level (menu_item __flash *NewMenu);
void Set_Menu_Item (menu_item __flash *NewMenu);
void MenuFunc(FuncPtr* Function);
//========================================================================

//========================================================================
EXTERN_MENU (L_OUT_MODE);
//========================================================================

//========================================================================
void Out_Menu_Items_Init (void);
void Out_Menu_Items (void);
//========================================================================

//========================================================================
bool proc_menu_keys (void);
//========================================================================

//========================================================================
void out_name_level (void);
u08 count_chars (char __flash *data);
void make_page_menu (void);
void inc_pos_y_curs (void);
void dec_pos_y_curs (void);
void set_pos_curs (void);
//========================================================================

#endif

//========================================================================
#include "menu.h"
//========================================================================

//========================================================================
static u08 quant_items;
static u08 pos_y_curs;
//========================================================================

//==============================================================================================================================================
menu_item __flash *CurrMenuItem; // Текущий пункт меню.

menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.

menu_item __flash *temp_menu;

menu_item __flash Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0, NULL_FUNC, NULL_FUNC, {NULL_TEXT}};

void (*MenuFuncPtr)(void);
//==============================================================================================================================================

//========================================================================
void Set_Menu_Level (menu_item __flash *NewMenu)
{
if ((void*)NewMenu == (void*)&NULL_ENTRY)
 return;

CurrMenuItem = NewMenu;

Out_Menu_Items_Init (); // Так как новый уровень, инициализация переменных.
Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.

GO_MENU_FUNC (MENU_FUNC);
}
//========================================================================

//========================================================================
void Set_Menu_Item (menu_item __flash *NewMenu)
{
if ((void*)NewMenu == (void*)&NULL_ENTRY)
 return;

CurrMenuItem = NewMenu;

Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.

GO_MENU_FUNC (ENTER_FUNC);
}
//========================================================================

//========================================================================
void MenuFunc (FuncPtr* Function)
{
if ((void*) Function == (void*) NULL_FUNC)
 return;

((FuncPtr) Function)();
}
//========================================================================

//========================================================================
bool proc_menu_keys (void)
{
switch (GetKeyCode ())
{
 case KEY_ESC_COD:
	 SET_MENU_LEVEL (PARENT);
	 return true;

 case KEY_ENTER_COD:
	 SET_MENU_LEVEL (CHILD);
	 return true;

 case KEY_NEXT_COD:
	 inc_pos_y_curs ();
	 SET_MENU_ITEM (NEXT);
	 return true;

 case KEY_PREV_COD:
	 dec_pos_y_curs ();
	 SET_MENU_ITEM (PREV);
	 return true;

 default:
	 return false;
}
}
//========================================================================

/*
Уровни, пункты, текст - все выводится автоматом.
Так как все переходы по меню расписаны в структуре, то отпадает надобность в запоминании перемещений по меню.
*/

//========================================================================
void Out_Menu_Items_Init (void)
{
quant_items = 1;
pos_y_curs = 1;

// Получение адреса начала массива уровня меню.
BeginCurrMenuLevel = CurrMenuItem;
temp_menu = (menu_item __flash *)(CurrMenuItem->Prev);

while (1)
{
 if ((void*)temp_menu == (void*)&NULL_ENTRY)
 {
	 break;
 }
 else
 {
	 BeginCurrMenuLevel = temp_menu;
	 temp_menu = (menu_item __flash *)(temp_menu->Prev);
 }
}

// Получение количества пунктов меню.
temp_menu = (menu_item __flash *)(BeginCurrMenuLevel->Next);

while (1)
{
 if ((void*)temp_menu == (void*)&NULL_ENTRY)
 {
	 break;
 }

 temp_menu = (menu_item __flash *)(temp_menu->Next);
 quant_items++;
}

// Позиция курсора.
if (quant_items > 1)
{
 temp_menu = BeginCurrMenuLevel;

 while (1)
 {
	 if ((void*)temp_menu == (void*)&NULL_ENTRY)
	 return;

	 if (temp_menu == CurrMenuItem)
	 return;
	 else
	 pos_y_curs++;

	 temp_menu = (menu_item __flash *)(temp_menu->Next);
 }
}
}

void Out_Menu_Items (void)
{
clr_dsp_buf ();

out_name_level (); // Вывод названия уровня меню.

make_page_menu (); // Вывод пунктов меню.

set_pos_curs (); // Установка позиции и вывод курсора.
}
//========================================================================

//========================================================================
// Вывод названия уровня меню.
void out_name_level (void)
{
temp_menu = (menu_item __flash *)(CurrMenuItem->Parent); // Считывание названия уровня меню из пункта меню в верхнем уровне.

if ((void*)temp_menu != (void*)&NULL_ENTRY)
{
 char __flash *data = temp_menu->Text;

 u08 i = count_chars (data); // Подсчет кол-ва символов в строке.

// Выравнивание текста посередине строки дисплея.

 u08 a = i;

 i = (20 - i); // Дисплей 20x4. Отнимаем от 20 число символов.

 i >>= 1; // Делим остаток на 2.

 if (a & (1<<0))
	 i += 2; // Если число нечетное.
 else
	 i++; // Если число четное.

 Print_Buf (1, i, temp_menu->Text);
}
}
//========================================================================

//========================================================================
// Подсчет кол-ва символов в строке.
u08 count_chars (char __flash *data)
{
u08 i = 0;

while (data [i])
{
 i++;
}
return i;
}
//========================================================================

//========================================================================
void make_page_menu (void)
{
signed char tmp_pos_y_curs;
u08 i; // Счетчик страниц.
u08 j; // Страница меню.

if (quant_items > 1) // Если пунктов меню больше 1, значит есть что выводить.
{
 temp_menu = BeginCurrMenuLevel;

 if (pos_y_curs > PAGE_MENU)
 {
	 tmp_pos_y_curs = pos_y_curs;

	 i = 0; // Счетчик страниц.

	 while (tmp_pos_y_curs > 0)
	 {
	 tmp_pos_y_curs -= PAGE_MENU;
	 i++;
	 }
	 tmp_pos_y_curs += PAGE_MENU;

	 j = PAGE_MENU; // Страница меню.

	 while (i-- > 1)
	 {
	 while (j--)
	 {
		 temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню.
	 }
	 j = PAGE_MENU; // Страница меню.
	 }
 }

 u08 pos_y_text_item = 2; //
 j = PAGE_MENU; // Страница меню.

 while (j--)
 {
	 Print_Buf (pos_y_text_item, 2, temp_menu->Text); // вывод названия пункта меню.

	 temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню.

	 if ((void*)temp_menu == (void*)&NULL_ENTRY) // Если элемент Next
	 return;								 // пустой, то выход.
	 else
	 pos_y_text_item++;
 }
}
}
//========================================================================

//========================================================================
void inc_pos_y_curs (void)
{
if (quant_items > 1)
{
 if (pos_y_curs < quant_items) pos_y_curs++;
}
}

void dec_pos_y_curs (void)
{
if (quant_items > 1)
{
 if (pos_y_curs > 1) pos_y_curs--;
}
}
//========================================================================

//========================================================================
void set_pos_curs (void)
{
if (quant_items > 1)
{
 signed char tmp = pos_y_curs;

 while (tmp > 0)
 {
	 tmp -= PAGE_MENU;
 }

 if (tmp <= 0) tmp += PAGE_MENU;

 PrintChar (tmp + 1, 1, ARROW_RIGHT);
}
}
//========================================================================

//=======================================================================================================================================================================================================================================================
//		 NAME	 PARENT	 CHILD	 NEXT	 PREV	 MENU_FUNC			 ENTER_FUNC TEXT
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MAKE_MENU (L_OUT_MODE, NULL_ENTRY, L1_I1,	 NULL_ENTRY, NULL_ENTRY, set_main_tui_service, NULL_FUNC, "ПАРАМЕТРЫ");
MAKE_MENU (L1_I1,	 L_OUT_MODE, NULL_ENTRY, L1_I2,	 NULL_ENTRY, set_menu_parameters, NULL_FUNC, "ПУНКТ_1");
MAKE_MENU (L1_I2,	 L_OUT_MODE, NULL_ENTRY, L1_I3,	 L1_I1,	 NULL_FUNC,		 NULL_FUNC, "ПУНКТ_2");
MAKE_MENU (L1_I3,	 L_OUT_MODE, NULL_ENTRY, L1_I4,	 L1_I2,	 NULL_FUNC,		 NULL_FUNC, "ПУНКТ_3");
MAKE_MENU (L1_I4,	 L_OUT_MODE, NULL_ENTRY, NULL_ENTRY, L1_I3,	 NULL_FUNC,		 NULL_FUNC, "ПУНКТ_4");
//=======================================================================================================================================================================================================================================================

Изменено пользователем demiurg1978
Ссылка на комментарий
Поделиться на другие сайты

Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)

Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.

На вебинаре мы представили информацию не только по линейкам аккумуляторной продукции EVE, но и по решениям для управления ею, что поможет рассмотреть эти ХИТ в качестве дополнительной альтернативы для уже выпускающихся изделий. Также рассмотрели нюансы работы с производителем и сервисы, предоставляемые Компэл по данной продукции. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Ну достоинства и недостатки наверно лучше расскажут другие (хвалиться не буду).

Я просто привёл в нормальный вид свой проект с меню и решил им поделиться (на указателях построено большинство меню).

Также показал свой код работы с LCD индикатором на HD44780 от 0801 до 4002 (выбирается дефайнами без изменения кода), в том числе перекодировку символов для индикатора двумя способами (макрос и таблица), обработку клавиатуры и работу с входными и выходными дискретами.

Да, описание немного страдает.

Как мне кажется, меню создать не сложно (мне кажется просто, в описание это показал). Каждое меню отдельный файл, для каждой кнопки своя функция. На скорость работы вроде не жалуются.

Время выполнения кода в прерывании (таймер на 1 млсек) (опрос клавиатуры, вывод на экран, ввод/вывод дискретов) - ~40 мксек при кварце 8 МГц (при 16 МГц будет работать в 2 раза быстрее :-) )

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Весь вопрос в том, насколько просто создавать проекты и меню. На мой взгляд, MicroMenu это обеспечивает.

Увидеть бы видео хотя бы тестового проекта и сам проект по вашему способу.

Кстати, в IAR есть файл intrinsics.h, там много интересного.

__enable_interrupt (); - sei
__disable_interrupt (); - cli
__watchdog_reset (); - wdr

Изменено пользователем demiurg1978
Ссылка на комментарий
Поделиться на другие сайты

Добавил видео по созданию нового пункта меню

https://ru.files.fm/u/a2sfccuf#/list/

Скачивать по ссылке, далее нажимая на кнопку "Скачать" или в таблице столбец "Download"

Ссылка на комментарий
Поделиться на другие сайты

Если честно, то я не составил никакого мнения. Главные критерии создания меню - легкость, минимум мест правки. Ваш проект состоит из туевой хучи файлов и непонятно какие файлы смотреть. Займитесь этим. Вычистите проект, избавьтесь от лишних файлов. Когда будет готово, напишите новое сообщение, чтобы было понятно, что у вас что-то готово.

Ссылка на комментарий
Поделиться на другие сайты

Чиститься ничего не будет, файлы проекта разбиты на функционалу. Дерево файлов проекта описано. Лёгкость построения меню я показал в видео.

Построение меню похоже на работу панелей операторов для связи с ПЛК: создаётся экран и на кнопки прописываются функции (например переход на другой экран).

Можно легко перейти с одного дисплея на другой (с 1602 на 2004) не меняя код. Если засунуть весть этот код в один файл неужели легче будет разобраться?

Если есть вопросы спрашивайте - отвечу.

Много пустых функций в меню можно убрать и поставить заглушку stub() (также было в описание). Код будет выглядеть уже так:

//==============================================================================
// Меню "Версия устройства"
//==============================================================================
#include "..\module\menu.h"
extern const uint8_t __flash MsgName[];
extern const uint8_t __flash MsgVersion[];
//==============================================================================
// Отображение меню
//==============================================================================
static void show(void)
{
 ShowTextF(6, MsgName);	  // отображаем имя проекта
 ShowTextF(16, MsgVersion);  // отображаем версию проекта
}
//==============================================================================
// Действие кнопки "Параметр"
//==============================================================================
static void param(void)
{
 MenuSetMenu(MENU_DEFAULT);  // при нажатии кнопки "Param" переходим на "Главный экран"
}
//==============================================================================
const TMenu __flash MenuVersion = {show, stub, stub, {stub, stub, param, stub}};

Изменено пользователем dm37
Ссылка на комментарий
Поделиться на другие сайты

Подход как к панели оператора одобряю, сам использую именно такой подход. По поводу меню, кнопок и так далее. Выше я приводил пример. В самом конце само меню. Обслуживание меню только на конечных автоматах. Иначе никак. От слова совсем. Кто-то скажет прототреды, но прототреды те же самые конечные автоматы, только в фантике.

Кнопки у вас намертво завязаны на функции. И это уже накладывает ограничения.

Лично я не хочу ковыряться во всех ваших файлах.

Как сделано у меня: модуль меню (интерпретатор структуры меню), аппаратный модуль дисплея, модуль вывода информации (модуль меню - всего лишь часть этого модуля).

Ссылка на комментарий
Поделиться на другие сайты

что вы имеете ввиду

"Кнопки у вас намертво завязаны на функции. И это уже накладывает ограничения."?

я могу не вернуться туда откуда пришёл, если я захожу в один экран из разных мест? Да это так. Но можно и это обойти добавив адрес возврата.

у меня только скелет меню, и многоуровневое меню из проекта avr_menu2 только небольшая надстройка. Ввиду идентичности экранов меню общие функции вынесены в файл menu.c.

Отображение идёт на уровне экранов, что захотите, то и поместите на экран.

Ссылка на комментарий
Поделиться на другие сайты

Если для добавления пункта меню надо делать специальное видео это уже критерий что что-то не так.

Вопрос занимаемого объема остается открытым, вопрос достоинств и недостатков тоже.

На что вы рассчитывали, давая ссылку на свой вариант? Что новички (у тех кто поопытнее часто уже есть своя или сторонняя реализация) кинутся разбираться в ваших десятках файлов, смотреть видео и т.д. чтобы получить кота в мешке?

Если бы оформили меню как отдельный модуль с нормальным описанием - другое дело.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...
  • 1 год спустя...

Очень заинтересовал меня Ваш проект.

Я не знаком с IAR, до этого работал с Atmel Studio, установил IAR 7.10.1 выдает 24 ошибки.

[Og007]: Assembler list file generation not allowed in this version of the compiler 
Error while running C/C++ Compiler 

В чем может быть причина?
 

 

Ссылка на комментарий
Поделиться на другие сайты

В 08.07.2016 в 21:56, COKPOWEHEU сказал:

в AVR не так много памяти чтобы извращаться указателями на функции входа и выхода. Логичнее и проще сделать общую функцию отображения любого элемента, а само меню реализовать в виде дерева или графа. От узлов все равно ожидается одинаковое поведение - переход по графу или выполнение листьев

А я несколько иного мнения о том, какое именно меню должно быть... и именно по причине малой памяти. Плюс требование удобства.

Моё понимание меню тезисно таково:

1. Меню делается для изменения настройки ограниченного количества параметров программы
2. Параметры это числа в пределах 1-2 байт или (реже) строковые значения. Во многих случаях параметр имеет "булев" тип, т.е. вкл/выкл.
3. Удобно сразу видеть в меню значение параметра
4. Удобно сразу менять значение видимого параметра

Поэтому я всегда стараюсь делать меню состоящим из следующих категорий "пунктов":

- пункт для правки байтового параметра
- пункт для правки булева параметра
- пункт для правки "пользовательского" параметра
- пункт-ветка, т.е. вход в меню следующего уровня

При выводе "наименования" пункта сразу автоматически выводится и значение соответствующего параметра. Например, параметр для регулировки яркости подсветки задается макросом типа MENU_ITEM("Яркость", MI_BYTE, &config.bright, 0, 100), где MI_BYTE задает "тип" пункта (пункт-байт), далее - адрес этого самого байта, а затем - минимальное и максимальное значение параметра.

Соответственно, функции управления я делаю так, чтобы при нажатии на кнопки влево-вправо менялся параметр в соответствии с типом пункта меню (и при этом срезу перерисовывался пункт), нажатие "Enter" приводит к выходу из меню с запоминанием настроек или входу в подменю, а "Esc" - к выходу из меню (подменю) без запоминания сделанных изменений. Ну а кнопки вверх-вниз двигают указатель по меню.

"Пользовательский" параметр, как правило, применяется для изменения настроек, не укладывающихся в вышеперечисленные типы и требующие особых подходов. Например, выбор нужного файла или одной из нескольких строк...

С некоторыми вариациями этот подход я реализую постоянно, и он себя оправдывает, хотя без указателей на функции обработки разных типов меню тут я не обхожусь... 

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Только что, Mark_22 сказал:

@ARV, Вы можете выслать мне, пример Вашего МЕНЮ?

Ну вот здесь посмотрите... там и ссылка на скачивание есть. Там же поиском по слову TUI можете посмотреть. Но там несколько отличающаяся реализация, т.к. я не пришел к окончательному варианту, я все время в поиске :)

Скачать видео

 

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

6 часов назад, Mark_22 сказал:

В чем может быть причина?

Попробуйте в настройках компилятора IAR:

Project -> Options -> C/C++ Compiler -> List
Project -> Options -> Assembler -> List
Project -> Options -> Linker -> List

снять все галочки

Изменено пользователем technik-1017
Ссылка на комментарий
Поделиться на другие сайты

С ошибками разобрался.

Я так понял есть превышение по коду?

Fatal Error[e89]: Too much object code produced (more than 0x1000 bytes) for this package 
Может надо еще какую-то галочку убрать?

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Mark_22 сказал:

Может надо еще какую-то галочку убрать?

скорее всего у вас установлена версия бессрочная, но с ограничением по размеру кода. Попробуйте установить оценочную версию на 30 дней, она не должна иметь подобного ограничения.
Если скомпилируется, то остаётся купить (~2820 EUR) или поискать лекарство.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • @irfpsДоброго А какое напряжение автогена вам необходимо?  в теме про магнитные усилители выкладывал автоген пуш-пул с напряжением запуска 2,2 В с "катушкой зажигания", но потом забросил, остался лишь макет, работает от одного литиевого аккумулятора.  В том случае(с "катушкой зажигания") можно пускать любой автоген при любом напряжении. Успехов
    • Уже который день пытаюсь разобраться с дисплеем. Слишком там как то в коде дисплея запутано. Я ещё разок наверное попробую сделать. Но если не получится, то я откажусь от дисплея и поставлю семисегментные индикаторы и многоцветные светодиоды и буду выводить кое какую информацию так. Ими управлять намного проще. Разве что имя воспроизводимого файла вывести не удастся. Но не велика потеря. Можно ведь просто номер музыки выводить. Всё лучше чем ничего. С самим плеером там всё понятно сложностей не будет точно нужно всего будет уточнить несколько деталей по командам, а то в описаниях не очень понятно. С UART там тоже всё понятно никаких сложностей нет.Но вот с дисплеем какой то затык получается.
    • Приветствую. Ревер запустил, побаловался - ну, такое себе. Не именно качество пружинного ревера, а сама по себе идея эха не понравилась. Зачем? Хорошая гитара с хорошими активными звучками и так звучит отлично. Причем, довольно объемно и без эха. Наваял вот такой девайс для управления ревером по схеме отсюда: https://sound-au.com/project34.htm Схема такая: Данная схема приглянулась тем, что можно отдельно регулировать уровень "чистого" сигнала и добавлять к нему сигнал ревера. Все заработало с первого раза. Если кому-то интересно - выложу мой вариант схемы и печатку сюда. На моей схеме и плате (при помощи джамперов) предусмотрел возможность использования схемы с разными реверами согласно таблице: Данная схема не понравилась тем, что ревер в ней всегда работает "на всю мощь" - регулируется только его громкость. Мне кажется, если схему добавить возможность ограничения усиления перед ревером, то это даст возможность регулировать итенсивность эха. Или нет? Стоит по этому поводу заморочиться и дать схеме еще один шанс? Интерес к данному проекту я потерял, планирую попробовать цифровой ревер. Если кому-то интересно продолжить проект или просто поэкспериментировать - могу поделиться новым ревером и спаянной платой. Советы и замечания по прежнему принимаются - может я не туда копаю? Кстати, сам ревер установлен внутри комбика и совершенно не зависит от его громкости и вибрации корпуса. Как говорили выше. Опробовано на практике. Звук, да - как из консервной банки. Но я еще пока не занимался настройкой схемы и самим ревером.
    • Тут ещё какая штука- сечение от диаметра имеет квадратичную зависимость. Увеличение диаметра в 2 раза даёт увеличение сечения в 4. Поэтому ошибка получается очень большая.  ПЕРЕСЧЁТ ДИАМЕТРА ПРОВОДА НА ПОПЕРЕЧНОЕ СЕЧЕНИЕ.xls
    • Хорошо, если вам хочется называть проценты попугайчиками, то пожалуйста. Но, хотелось бы спросить. Вы всё-таки понимаете разницу между измерением напряжения 1 В с точностью +-0,1% и измерением отношения напряжений Х В и 0,5Х В с такой же точностью? 
    • Про R20 Я тоже думал поставить постоянный на 800 ом и 200 ом переменником крутить
×
×
  • Создать...