#1 2020-03-23 01:36:21

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Вызов функции по номеру (указатель на функцию)

Возможно нубский вопрос, но спрошу.
Есть ли возможность и будет ли работать следующая конструкция?

Функция100();
Функция101();
....
Функция110();

Функция200();
Функция201();
...
Функция210();

loop {

for(i = 0; i < 10; i++){
		for(j = 0; j < 10; j++){
Функция(100+i)
Функция(200+j)
}
}
}

Функция с 100 по 110 выводит текст, а с 200 по 210 значение (или наоборот, пока не суть, главное понять возможно ли так)
Понимаю, что функция описана названием и просто так передать номер функции нельзя, но каким то другим способом можно, но как?
Реальное применение:
Допустим нужно вывести на дисплей несколько параметров:
"Напряжение" - текст
"Ток" - текст
"Мощность" - текст
"Что угодно еще" - текст
и затем
величина напряжения
величина тока
величина мощности
величина чего угодно
Текст выводится один раз, а величина потом может изменяться (но это уже другая тема, так что пока опустим).
Сейчас у меня есть готовая конструкция, которая выводит в такой последовательности, но дисплей долго заполняется сперва текстом потом данными, хочу сделать чтобы выводилось в другой последовательности:
"Напряжение" - текст, величина напряжения
"Ток" - текст, величина тока
"Мощность" - текст, величина мощности
"Что угодно еще" - текст, величина чего угодно

Появилась идея описать все функциями и вызывать их через for по номерам

Неактивний

#2 2020-03-23 01:45:13

JustVic
Учасник
Зареєстрований: 2020-03-22
Повідомлень: 5

Re: Вызов функции по номеру (указатель на функцию)

Добавьте пожалуйста примеры ваших функций с 100й по 110 и с 200й по 210
Что то мне подсказывает что такое ОГРОМНОЕ количество функций это огромная проблема в архитектуре
Есть вариант сделать функцию на подобии этой:

void fabricMethod(int funcNum) {
  switch (funcNum) {
  case 1: fun1(); break;
  case 2: fun2(); break;
    ...
  case N: funN(); break;
  default:
    errorFun();
    break;
  }
}

Неактивний

#3 2020-03-23 02:19:39

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Сейчас работает так.
Показывается текст один раз(который хочу переделать в текстовый функции 100....110)

Paint_DrawString_EN(2, 70, "Ток (мА):", &Font16, BLACK, WHITE);

Paint_DrawString_EN(2, 90, "Напряжение (мВ):", &Font16, BLACK, WHITE);

Потом идет отображение данных по циклу (хочу переделать в функции 200...210:

if (fetchWord(CURRENT) < 0) {																// CURRENT
		Paint_DrawString_EN(254, 70, "-", &Font16, BLACK, RED);
		Paint_ClearWindows((265 + 11*digit_counter(abs (fetchWord(CURRENT)))), 70, 309, 87, BLACK);				
		Paint_DrawNum(265, 70, abs (fetchWord(CURRENT)), &Font16, BLACK, RED);
	}

	if (fetchWord(CURRENT) > 0) {
		Paint_ClearWindows(254, 70, 265, 87, BLACK);
		Paint_ClearWindows((265 + 11*digit_counter(fetchWord(CURRENT))), 70, 309, 87, BLACK);
		Paint_DrawNum(265, 70, fetchWord(CURRENT) , &Font16, BLACK, GREEN);
	}
	if (fetchWord(CURRENT) == 0) {
		Paint_ClearWindows(254, 70, 265, 87, BLACK);
		Paint_ClearWindows((265 + 11*digit_counter(fetchWord(CURRENT))), 70, 309, 87, BLACK);
		Paint_DrawString_EN(265, 70, "0", &Font16, BLACK, GREEN);
	}

	Paint_ClearWindows((265 + 11*digit_counter(fetchWord(VOLTAGE))), 90, 320, 107, BLACK);		// VOLTAGE
	Paint_DrawNum(265, 90, fetchWord(VOLTAGE), &Font16, BLACK, GREEN);

Остання редакція luminofor (2020-03-23 02:32:47)

Неактивний

#4 2020-03-23 02:24:27

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Вообще логика такая:
Отображается один раз 11 строк текста и затем и соответственно 11 строк данных по циклу
Проверяется кнопка, если было нажатие, то следующие 12 строк текста один раз и 12 строк данных по циклу.

Ваш подход мне нравится, надо попробовать. А как будет правильнее, объявить все эти функции в setup() или можно в loop()?

Остання редакція luminofor (2020-03-23 02:30:41)

Неактивний

#5 2020-03-23 10:18:42

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

будет ли работать следующая конструкция?

Ну, ты ведь уже пробовал? И знаешь, что - нет? Если хочешь так, надо объявлять массив функций и вызывать по индексу. Хотя, ... думаю, возможно более простое решение, но я задачи не знаю.

Неактивний

#6 2020-03-23 10:54:20

Watchdog
Гість

Re: Вызов функции по номеру (указатель на функцию)

Kaka пише:

... думаю, возможно более простое решение, но я задачи не знаю.

А я догадываюсь. Человек GUI валяет. big_smile А учить мову не желает.

luminofor пише:

будет ли работать следующая конструкция?

Не будет! С не JS, хотя фигурные скобки тоже имеются. Оператором switch(.) также можно, компилятор сам табличные вызовы построит, но лучше явно. Подскажу:

void bar(void) {
// ... 
}

void (*foo)[n](void) = {bar, ...};

for (int i = 0; i < n; i++) foo[i]();

#7 2020-03-23 13:50:29

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Watchdog пише:

А я догадываюсь. Человек GUI валяет. big_smile А учить мову не желает.

Правильно, ваяю GUI big_smile
Это мой первый проект и сразу такой масштабный. Второй месяц ковыряю, почти идеально уже, но нет предела совершенству cool
Желаю, поэтому и консультируюсь. В интернетах нарыл, что, то, что я хочу сделать называется указатель на функцию. Пересмотрел видосы и гайды, есть представление, но нет пока четкого понимания. Много сложной воды и мало примеров.
Однажды я услышал фразу: не нужно зубрить матчасть, нужно сразу брать и пробовать. На удачах и ошибках быстрее научишься.
За подсказку спасибо, примерно это я и имел ввиду.

Неактивний

#8 2020-03-23 14:15:41

JustVic
Учасник
Зареєстрований: 2020-03-22
Повідомлень: 5

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

Однажды я услышал фразу: не нужно зубрить матчасть, нужно сразу брать и пробовать. На удачах и ошибках быстрее научишься.

Если только для души - то все отлично, если с дальнейшим развитием и поиском работы по этой специальности то беда. Приходят потом такие "научившиеся"
и вместо простых циклов городят зоопарки с "GOTO", "не ну ачо работает же"

Неактивний

#9 2020-03-23 15:08:30

Watchdog
Гість

Re: Вызов функции по номеру (указатель на функцию)

JustVic пише:
luminofor пише:

Однажды я услышал фразу: не нужно зубрить матчасть, нужно сразу брать и пробовать. На удачах и ошибках быстрее научишься.

Если только для души - то все отлично, если с дальнейшим развитием и поиском работы по этой специальности то беда. Приходят потом такие "научившиеся"
и вместо простых циклов городят зоопарки с "GOTO", "не ну ачо работает же"

А другие научившиеся таких принимают! smile big_smile lol

Тем кто хочет простоту
Жизни нет без GOTO.

#10 2020-03-23 16:27:40

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

видосы

А что, читать не умеешь? Беда, если так :-(

luminofor пише:

Однажды я услышал фразу: не нужно зубрить матчасть, нужно сразу брать и пробовать.

Надеюсь, ты плюнул в рожу тому, кто тебе такой бред сказал?

А по задаче, делай массив указателей на функции, если так приспичило. Только ещё раз говорю - это прошлый век. На С++ так не пишут. Как пишут - могу подсказать, но надо задачу понимать.

Неактивний

#11 2020-03-24 01:25:11

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Kaka пише:

но надо задачу понимать.

Задача почти допилена, можно в принципе и так бросить, но я пока жду комплектуху из Китая, поэтому допиливаю по мере просветления мозгов.
По I2C подключен некий прибор, который может выдавать тучу параметров. Не хочу трепаться что именно, вдруг выгорит и стану миллионером lol
По SPI подключен IPS TFT дисплей 320х240.
Стандартная библиотека дисплея умеет выводить 'символы' по коду, "строку из букв", числа ну и рисовать всякие отрезки треугольники и прочие прямоугольники. Я пробовал другие библиотеки под чип ST7789, они не завелись. (почему то не работала треть экрана как я его не вращал, хотя в библиотеках была поддержка дисплея 320х240). Это сейчас не важно, использую, то, что работает.
Так вот. Заполнение 11 строк описательным текстом 16м шрифтом занимает 10 секунд, потом отображаются получаемые данные. Данные бывают либо текст, либо цифры. Это еще 2 секунды.
По нажатию кнопки дисплей стирается и отображаются еще 12 строк с тектом и параметрами.
Были некоторые трудности с приведением этого месива в красивый вид, чтобы не моргало лишний раз, об этом я писал в другом посте про оптимизацию вывода на дисплей. Сейчас все красиво и волшебно, но захотелось уплотнить код (сейчас используется 87% ROM и 55% RAM) так как в будущем хочу добавить пару хотелок, или не хочу. Пока не уверен.
После дисплея инфа выводится в сериал. (это я еще допиливаю, раскрашиваю в цвет и делаю таблицу).
Так вот, по поводу оптимизации. Хочу избавится от бесконечных if и goto. Не знаю почему, но опытных программеров они раздражают. Начал делать. И тут пришла идея вообще нафик все переделать. Чтобы было строка_описательного_текста_1 + данные_1, строка_описательного_текста_2 + данные_2 и так далее. Покурил указатели на функции, вроде бы то, что нужно. Ведь все уже набрано, осталось грубо говоря пронумеровать куски и выдавать их потом в любой последовательности.
Пока не могу вкурить как выдать на дисплей String

String formatted_date = "";
formatted_date += year;
formatted_date += "-";
formatted_date += month;
formatted_date += "-";
formatted_date += day;
Serial.println(formatted_date);

Вот так выдать в сериал можно, на дисплей нет

Неактивний

#12 2020-03-24 06:46:43

Watchdog
Гість

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

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

Миллиардером! "Пилите шура она золотая!" - из к.ф. Двенадцать стульев.  cool

#13 2020-03-24 09:58:42

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

Не хочу трепаться что именно, вдруг выгорит и стану миллионером lol

Понятно.

Ну, тогда и я не буду трепаться как это делается, вдруг мне это объяснение кто-нить за миллион закажет.

Неактивний

#14 2020-04-04 19:48:18

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Watchdog пише:

Подскажу:

void bar(void) {
// ... 
}

void (*foo)[n](void) = {bar, ...};

for (int i = 0; i < n; i++) foo[i]();

Ваша конструкция не заработала, не знаю почему. Я не силен тонкостях программирования. Подсмотрел здесь
решение, не все понял, но результат устраивает. То, чего я добивался, получилось. Вот результат:

volatile boolean intFlag = false;   // Флаг прерывания
int key = false;				// Флаг нажатия кнопки
int newscreen = false;		// Флаг нового экрана
pinMode(7, INPUT_PULLUP);	// Кнопка на седьмой пин где будет ловиться прерывание №4

char *text1[]={				// Массив текстовых сообщений 1
	"Сообщение 0:",
	....
	"Сообщение 9:",
};

void function_0 (void);		// Объявление функций, сами функции расписаны в конце
....
void function_9 (void);

void (*a0)(void) = &function_0;  	// Создание указателей на адреса функций,
....						      // которые получают данные с устройства
void (*a9)(void) = &function_9;

typedef void (* FuncPtr1) ();	// Создание типа с названием FuncPtr1
						// который представляет собой указатель на функцию

FuncPtr1 param1[10] = {a0, .... , a9};   // Складывание указателей в массив

// То же самое для второго экрана

char *text1[]={				// Массив текстовых сообщений 2
	"Сообщение 10:",
	....
	"Сообщение 19:",
};

void function_10 (void);		// Объявление функций, сами функции расписаны ниже
....
void function_19 (void);

void (*b0)(void) = &function_10;   // Создание указателей на адреса функций
....						   // которые получают данные с устройства
void (*b9)(void) = &function_19;

typedef void (* FuncPtr1) ();	// Создание типа с названием FuncPtr2
						// который представляет собой указатель на функцию
FuncPtr1 param2[10] = {b0, .... , b9};   // Складывание указателей в массив

void setup()
{

	//	Тут всякие нужные действия
}

void loop()
{
switch (intFlag) {				// Обработчик нажатия кнопки
	case true:
		intFlag = false;			// Сброс флага прерывания		
		key = !key;			// Нажатие на кнопку зафиксировано
		newscreen = !newscreen;	// Новый экран - Да
		LCD_Clear(0x0000);		// Очистка всего экрана
		break;
	}
	
	
	switch (key) {				// Реакция на кнопку выбора экрана
	case false:					// Первый экран
		switch (newscreen) {		// Новый экран?
		case false:				// Да, новый екран
			for (int i = 0; i < 10; i++){														
				Paint_DrawString_EN(x, y(i), text1[i], шрифт, фон, цвет);	// Выводить текст 1 с просчетом координаты Y
				switch (device_ready()) {										// Подключено ли устройство:
				case false:														// Нет - ничего не выводить
					break;
				default:														// Да - выводить данные 1
					param1[i]();
				}
			}
			newscreen = !newscreen;												// Сбрасываем флаг "Новый экран"
			break;
		case true:																// Экран уже был, выводить только данные
			for (int i = 0; i < 10; i++){
				switch (device_ready()) {										// Подключено ли устройство:
				case false:														// Нет - затереть пробелами предыдущие значения
					Paint_DrawString_EN(x, y(i), "     ", шрифт, фон, цвет);	// с просчетом координаты Y
					break;
				default:														// Да - выводить данные 1
					param1[i]();
				}
			}
			break;
		}			
		
		attachInterrupt(4, buttonTick, LOW);									// Реакция на кнопку разрешена
		break;
		
		
	case true:																	// Второй экран
		switch (newscreen) {													// Новый экран?
		case false:																// Да, новый экран
			for (int i = 0; i < 10; i++){
				Paint_DrawString_EN(x, y(i), text2[i], шрифт, фон, цвет);		// Выводить текст 2
				(device_ready()) {												// Подключено ли устройство:
				case false:														// Нет - ничего не выводить
					break;
				default:														// Да - выводить данные 2
					param2[i]();
				}
			}
			newscreen = !newscreen;												// Сбрасываем флаг "Новый экран"
			break;
		case true:																// Экран уже был, выводить только данные
			for (int i = 0; i < 10; i++){																
				switch (device_ready()) {										// Подключено ли устройство:
				case false:														// Нет - затереть пробелами предыдущие значения
					Paint_DrawString_EN(x, y(i), "     ", шрифт, фон, цвет);	// с просчетом координаты Y
					break;
				default:														// Да - выводить данные 2
					param2[i]();
				}
			}
			break;
		}		
		
		attachInterrupt(4, buttonTick, LOW);									// Реакция на кнопку разрешена
		break;
		
	}
	// Далее вывод в сериал
}

// Куча полезных функций

void function_0(){}		// Функции объявленные в самом начале
....					
void function_19(){}

void buttonTick() {									// Хитрая реакция на прерывание, подсмотрел на одном форуме
	detachInterrupt(digitalPinToInterrupt(7));		// Запрещаем прерывания по пину 7
	intFlag = true;									// Установка флага прерывания
}

Всем спасибо за идеи, конструктивная критика и новые идеи приветствуются  smile

Неактивний

#15 2020-04-04 20:00:28

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Есть еще одна проблема. Если плата подключена к компу по USB и комп выключить, то плата виснет. Помогает только передергивание кабеля. Не критично, но раздражает. Думаю как то сторожевого пса приделать, чтоб следил за Serial. Но пока не курил эту тему

Неактивний

#16 2020-04-04 21:30:06

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: Вызов функции по номеру (указатель на функцию)

А не проще компьютеры объяснить, чтобы он юсб не вырубал? Ты ж не из розетки выдёргиваешь?

Неактивний

#17 2020-04-04 23:30:12

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Забыл сказать. Плата не питается от USB, у нее отдельное питание. По USB только передается инфа в Serial. Так что, если даже компу сказать, чтобы он не отрубал питание с USB, не факт, что плата не зависнет.
И потом, расчитывая на все случаи жизни, лучше заранее предусмотреть защиту от такого поведения.

Неактивний

#18 2020-04-05 09:33:46

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

лучше заранее предусмотреть защиту от такого поведения.

Ну, тогда предусматривай.

Неактивний

#19 2020-04-05 14:41:53

Watchdog
Гість

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:

Есть еще одна проблема. Если плата подключена к компу по USB и комп выключить, то плата виснет. Помогает только передергивание кабеля. Не критично, но раздражает. Думаю как то сторожевого пса приделать, чтоб следил за Serial. Но пока не курил эту тему

Тут пёс ничем не поможет, это же не шахматы. И занятие это не для раздражительных, можно обкуриться до тошноты, если нервничать по мелочам. smile  lol

#20 2020-04-14 12:53:47

Watchdog
Гість

Re: Вызов функции по номеру (указатель на функцию)

luminofor пише:
Watchdog пише:

Подскажу:

void bar(void) {
// ... 
}

void (*foo)[n](void) = {bar, ...};

for (int i = 0; i < n; i++) foo[i]();

Ваша конструкция не заработала, не знаю почему. Я не силен тонкостях программирования. ...

Не во всех версиях С допустимы массивы функций да ещё и с анонимными типами. Я же привёл псевдокод. Вот это работает в С99 и С11.

void bar(void) {
// ... 
}

typedef void (*foo_t)(void);

foo_t foo[] = {bar, bar};

int main ()
{
    for (int i = 0; i < 2; i++) foo[i]();
    return 0;
}

smile

#21 2020-04-14 17:51:14

Lic Control
Учасник
Зареєстрований: 2016-01-23
Повідомлень: 124

Re: Вызов функции по номеру (указатель на функцию)

Так вот. Заполнение 11 строк описательным текстом 16м шрифтом занимает 10 секунд, потом отображаются получаемые данные. Данные бывают либо текст, либо цифры. Это еще 2 секунды.

Боюсь вас огорчить, но по моему мнению за такое никто не заплатит.
Почему вы не хотите использовать WEB-интерфейс. Например ESP32 + WiFi. Программирование то же, что и для Arduino, но в результате получите возможность отобразить ваши результаты мгновенно в "цветах и красках" на WEB странице любого устройства - компьютера, смартфона, планшета. Дополнительно появляется возможность анимации, графики и картинки.
Вот, например структурная схема подобной системы
Lic Control

ESP32 управляет фанкойлами системы кондиционирования, при этом к ней можно подлючиться по WiFi для просмотра параметров и управления процессом.
Для ESP32 мы разработали печатную плату, которая помещается в стандартный подрозетник. Удобно, когда есть сложности с прокладкой проводов, например в действующих офисах.

Неактивний

#22 2020-04-16 11:49:21

luminofor
Учасник
Зареєстрований: 2020-01-28
Повідомлень: 52

Re: Вызов функции по номеру (указатель на функцию)

Lic Control пише:

Боюсь вас огорчить, но по моему мнению за такое никто не заплатит.
Почему вы не хотите использовать WEB-интерфейс. Например ESP32 + WiFi.

Я разрабатываю не массовое устройство. Так что да, заплатят только те, кому это очень нужно. Я промониторил рынок, есть только два похожих прибора в ценовой категории до 250$. Мой девайс обойдется дешевле, при почти тех же возможностях.
Веб интерфейс мне не нужен, это настольный прибор. Допустим как осцилограф. Хотя наличие вебморды было бы интересным решением, но только в связке с соответтствующим ПО для смартфона и возможностью мониторинга удаленно, а не только в домашней сети. За такую опцию точно никто не заплатит))
Рассматриваю кстати использование вместо ESP32 вместо Arduino. Будет и быстрее и даже немного дешевле.
Попутно столкнулся с другими проблемами. Не все комплектующие работают так как задумывалось, приходится импровизировать на ходу. Корпусно-крепежные проблемы.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму