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

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


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

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

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

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

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

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

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

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

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

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

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

Мой пример на основе 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
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

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

Весь вопрос в том, насколько просто создавать проекты и меню. На мой взгляд, 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 пользователей онлайн

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

    • Все предложенные к рассмотрению источники питания работают примерно по одному принципу: сетевое напряжение выпрямляется, фильтруется (получаем чуть больше 300 вольт постоянного), затем преобразуется снова в переменное, но уже на частотах в несколько десятков килогерц, понижается на трансформаторе и снова выпрямляется. За счёт высокой частоты преобразования используется трансформатор на ферритовом, а не на стальном, сердечнике, гораздо меньших габаритов и стоимости. Минусы: значительное усложнение схемы блока и вероятность возникновения различных помех от него. Модули управления (кроме первого) также являются импульными преобразователями, с теми же достоинствами и недостатками. Если нужно по быстрому собрать некое подобие ЛБП, то уж лучше брать модуль вроде этого. Ну и блок питания к нему соответствующий. Но не очень понятно, какой практический опыт можно получить от соединения готовых модулей парой проводов.  
    • У меня больше всего вопросов вызвала необычная схема обеспечения отрицательного питания. Автор этой обстоятельной заметки пишет: For this supply to work correctly, the transformer must have a secondary voltage of at least 18V RMS.  Почему? Что будет не так с отрицательным питанием, если напряжение на трансформаторе будет меньше 18В?   https://tinyurl.com/23mlwxtt - я в простейшей эмуляции ставлю 12В пикового напряжения для трансформатора и на стабилитроне все как положено: -5.6В.
    • Согласен, очень криво объяснил. Это работа трёх вольтовой линии, просто на диод шотки сдвоенный, на один анод приходит сигнал напрямую с трансформатора, а на второй через дроссель. Вольт/деление 5 вольт в клетке, тайминг по моему 10 МС. Третья фотография это сигнал на катодах уровень земли ровно по центру экрана. Но все линии по итогу в порядке 3.3 в, 5, в, 12 в и -12 в. Нагрузить все линии не могу сразу ,так как тут же выгорают транзисторы (имеется нагрузка 250 ватт по 10 ампер на каждую линию за исключением-12в), поэтому нагружаю 3.3 вольтовую линию на 10 ампер,  подключаю переменный резистор 50 ватт на 15 ом на 5 вольтовую линию и постепенно довожу до той той картины с перекосом (это гдето  50 ватт общее). По поводу микросхемы, вверху имеется скрин где между импульсами проскакивает мини импульс, если так можно сказать, он проскакивает и на одной  и на второй ноге (7,8). Микросхема не tl 494, а lw4933/abx942.1/c9421646. Далее они приходят на базы транзисторов 945g  коллекторы этих транзисторов соединены с  выводами трансформатора. Просто схема типовая, легче мне кажется просто привести фото самого блока, для тех кто разбирается будет гораздо информативне.  Диод шотки по 12 вольтовой линии был подгоревший, заменил на донора. Приводить скрины не буду что бы не захламлять тему. В итоге, пока все так же, при достижении определенной нагрузки суммарно где-то 50 ватт, появляется этот "выброс и перекос". По этому имеются мысли на два варианта, это микросхема , этот мини импульс между периодами, на низкой нагрузке особо не влияет, но при достижении определенной приводит с самовозбуждению входной цепи и непроизвольному открытию транзистора нижнего плеча. Либо дело в "горячей части", плавающий дефект в обвязке силовых ключей.  Спасибо за ответ.
    • @Gomerchik а вы контролировали как меняется уровень сигнала на А1 ардуины?
    • Спасибо за совет. Автором данного проекта я не являюсь, мне нужно было воссоздать уличный датчик для метеостанции взамен пропавшего(( Из разного найденного в интернете этот проект работает с моей станцией Орегон (спасибо автору). В понедельник попробую последовать Вашему совету. Но все равно куча непоняток  как блин это работает)) Если дело в неправильной отправки команды, то как на это влияет подключение датчика температуры? Если совсем не подключать таймер, то передача идет один раз (как и прописано в программе), станция принимает и отображает, но минут через сколько-то естественно станция уже ни чего не показывает, но с таймером питание полностью не пропадает с ардуинки, но передача сигнала каким-то образом работает по таймеру.  В моем понимании данная команда подается один раз потому, что таймер должен отключать питание МК после передачи сигнала и каждые 43 сек снова подавать питание (так того требует станция).  Ардуино передает показания температуры отключается полностью и 43 секунды мк не работает.  Сейчас у меня питание пока сделано на подпитке от солнечной батареи, но пару пасмурных дней и аккумулятор съедается до отключения(
    • thickman Так и сделаю. Вытащу из бу БП.  Буду знать, как отличить. Благодарю. Заменил транзисторы на IRFB20N50K. Картина стала, совсем другой.  Похоже трудность не в драйвере, на момент подвозбуда, переходные процессы, в нем, завершены. Увеличил затворные резисторы до 50ом, стало немного лучше.  Не понятно, почему верхний ключ греется несколько сильнее. Возможно, стоит посмотреть ток в коллекторе.  Снабберные емкости временно удалил, изменений не произошло.  Замена ТГР на другой, на кольце MSTN-16A-TH, так же, результата не принесла.   irfb20n50k.pdf
×
×
  • Создать...