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

luminofor
Участник
Зарегистрирован: 2020-01-28
Сообщений: 18

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

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

Функция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
Сообщений: 18

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
Сообщений: 18

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
Сообщений: 312

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
Сообщений: 18

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
Сообщений: 312

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

luminofor пишет:

видосы

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

luminofor пишет:

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

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

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

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

luminofor
Участник
Зарегистрирован: 2020-01-28
Сообщений: 18

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
Сообщений: 312

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

luminofor пишет:

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

Понятно.

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

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

luminofor
Участник
Зарегистрирован: 2020-01-28
Сообщений: 18

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
Сообщений: 18

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

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

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

Kaka
Участник
Зарегистрирован: 2018-03-21
Сообщений: 312

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

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

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

luminofor
Участник
Зарегистрирован: 2020-01-28
Сообщений: 18

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

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

#18 Вчера 09:33:46

Kaka
Участник
Зарегистрирован: 2018-03-21
Сообщений: 312

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

luminofor пишет:

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

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

#19 Вчера 14:41:53

Watchdog
Гость

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

luminofor пишет:

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

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

Быстрое сообщение

Введите сообщение и нажмите Отправить

Подвал раздела