|
[Вроде решено] Массив указателей на функции. Указатель на массив |
|
|
|
Jan 29 2017, 05:14
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Запутался. Честно скажу, с указателями я не всегда дружу.  Помогите написать правильно. Нужно: есть массивы указателей на функцию. И переменные-состояния конечных автоматов, индексы для массивов. CODE //************************************************************************ //************************ Главный автомат ******************************* //************************************************************************
//======================================================================== STATE (PROC_DEVICE_INIT, proc_device_init) STATE (PROC_DEVICE_WAIT_SWITCH_MODE, proc_device_wait_switch_mode) STATE (PROC_DEVICE_MANUAL, proc_device_manual_mode) STATE (PROC_DEVICE_AUTOMAT, proc_device_automat_mode) STATE (PROC_DEVICE_EMERG_MODE, proc_device_emerg_mode) //========================================================================
enum _proc_device { #define STATE(name, func) name, #include "_proc_device.h" #undef STATE
PROC_DEVICE_STATES, };
//======================================================================== typedef void (*FUNC)(void); //========================================================================
__flash FUNC proc_device_func [PROC_DEVICE_STATES] = { #define STATE(name, func) func, #include "_proc_device.h" #undef STATE };
static u08 _proc_device; static u08 _proc_device_slave;
void proc_device (void) { // proc_sens_pwr (SAVE_EEPROM_PARAMETERS); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
proc_device_func [_proc_device] (); // В данный момент работает так. }
Мне нужна функция, у которой в качестве параметров proc_device_func и _proc_device. Что-то вроде proc_fsm_func (proc_device_func, get_proc_device_state ()) Мои пробы выдают ошибки.
Сообщение отредактировал demiurg1978 - Jan 29 2017, 14:47
|
|
|
|
|
 |
Ответов
|
Jan 29 2017, 10:27
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Определяем тип переменной PROCEDURE - указатель на функцию Код typedef void (*PROCEDURE)(void); Пишем текст функций. Код void function1(void) { ... } void function2(void) { ... } void function3(void) { ... } Определяем, сколько у нас функций в массиве. Код #define STATES 3 Создаем массив указателей на функции в программной памяти, что у нас, AVR.. Код __flash const PROCEDURE function[STATES_QTY] = { function1, function2, function3 }; Все, в программе вызываем вызываем функцию, соответствующую номеру состояния state: Код function[state](); Цитата(demiurg1978 @ Jan 29 2017, 08:14)  Мне нужна функция, у которой в качестве параметров proc_device_func и _proc_device. Что-то вроде proc_fsm_func (proc_device_func, get_proc_device_state ()) А зачем так сложно - в функцию передавать указатель на функцию? Чтобы вызвать? Ну так вызовите добавлением скобок.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 29 2017, 12:16
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Dog Pawlowa @ Jan 29 2017, 16:27)  А зачем так сложно - в функцию передавать указатель на функцию? Чтобы вызвать? Ну так вызовите добавлением скобок. Покажите, как.
|
|
|
|
|
Jan 29 2017, 13:09
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(demiurg1978 @ Jan 29 2017, 15:16)  Покажите, как. Уже сделано! Функция вызывается по индексу в таблице: Код function[state](); Что не устраивает?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 29 2017, 13:16
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Все приведенные примеры по сути повторяют то, что написано в первом сообщении. Излишняя навороченность кода в том сообщении, по сути enum и массив, обвернутые в макросы. И вызов функции один в один как у вас. Код proc_device_func [_proc_device] ();
|
|
|
|
|
Jan 29 2017, 13:25
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(demiurg1978 @ Jan 29 2017, 16:16)  Все приведенные примеры по сути повторяют то, что написано в первом сообщении. Излишняя навороченность кода в том сообщении, по сути enum и массив, обвернутые в макросы. И вызов функции один в один как у вас. Правильно, макросы вредны, а все остальное - классика, которую использует каждый второй. Что не устраивает то? Вам то зачем дополнительная прослойка в виде функции, в которую будете передавать указатель на функцию? Будьте проще, пишите как есть, все же работает.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 29 2017, 15:02
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Вроде решил вопрос. CODE //======================================================================== typedef void (*FUNC)(void); //========================================================================
void proc_fsm_func (FUNC __flash *ptr_func, u08 s);
void func_1 (void); void func_2 (void); void func_3 (void); void func_4 (void);
extern FUNC __flash list_func []; void __flash * get_list_func (void);
void func_1 (void) {
}
void func_2 (void) {
}
void func_3 (void) {
}
void func_4 (void) {
}
__flash FUNC list_func [4] = { func_1, func_2, func_3, func_4, };
void proc_fsm_func (FUNC __flash *ptr_func, u08 s) { ptr_func [s] (); }
void __flash * get_list_func (void) { return list_func; }
proc_fsm_func (get_list_func (), 2);
Задумка такая: что-то вроде ядра обработчика конечных автоматов. Можно было и так оставить, как сделано в первом сообщении. Для каждого автомата своя строка вызова функции по индексу. А когда задумал ядро обработчика, тут и возникли трудности. Честно говоря, я еще думаю, стоит ли дальше работать над этим ядром и применять его в проектах.
Сообщение отредактировал demiurg1978 - Jan 29 2017, 17:29
|
|
|
|
|
Jan 29 2017, 16:14
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(demiurg1978 @ Jan 29 2017, 18:02)  Для каждого автомата своя строка вызова функции по индексу. Это реализуется очень просто - одним массивом всех функций, но группы индексов массива для каждого автомата не должны перекрываться. Например, первые 6 функций - автомат А, следующие 19 функций автомат B, и еще 9 функций автомата C. тогда если массив называется f, обработка всех автоматов будет выглядеть так: Код f[stateA](); f[stateB](); f[stateC](); Я так делал один раз в очень специфическом проекте.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 29 2017, 16:56
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
Цитата(Dog Pawlowa @ Jan 29 2017, 19:14)  Например, первые 6 функций - автомат А, следующие 19 функций автомат B, и еще 9 функций автомата C. Я так делал один раз в очень специфическом проекте. Допустим нужно добавить еще несколько состояний в автомат A, что делать? Менять условия всякий раз?  Насколько понимаю, ТС разбивает весь код на задачи и у каждой задачи - свой автомат состояний. Т.е. при переключении на соответствующую задачу должен подключаться соответствующий автомат состояния. В принципе, очень типичная задача. Ничего специфического. Даже тема была https://electronix.ru/forum/index.php?showt...=136908&hl=
|
|
|
|
|
Jan 29 2017, 19:05
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Если конечный автомат сделан по индексному переходу, то не инициализированная переменная-состояние может наделать делов. Именно поэтому хорош способ, когда нулевое состояние - инициализация всего и вся. Тем более что такой способ бесплатен. ОЗУ инициализировано нулями. Но если switch-case и состояний много, то код становится трудночитаемым. Опять же, switch-case нагляден. Индексный вызов функций - это блудить и искать нужную функцию. Но в этом случае можно частично облегчить задачу. Например, в одном месте вывести названия состояний и соответствующие названиям функции. Пример: Код //************************************************************************ //************************ Главный автомат ******************************* //************************************************************************
//======================================================================== STATE (PROC_DEVICE_INIT, proc_device_init) STATE (PROC_DEVICE_WAIT_SWITCH_MODE, proc_device_wait_switch_mode) STATE (PROC_DEVICE_MANUAL, proc_device_manual_mode) STATE (PROC_DEVICE_AUTOMAT, proc_device_automat_mode) STATE (PROC_DEVICE_EMERG_MODE, proc_device_emerg_mode) //========================================================================
Сообщение отредактировал demiurg1978 - Jan 29 2017, 19:11
|
|
|
|
|
Jan 31 2017, 15:39
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(jcxz @ Jan 31 2017, 17:23)  Где Вы её узрели в моём сообщении? вот: Цитата(jcxz @ Jan 31 2017, 00:34)  PC - вот лучшее место для хранения состояния автомата состояния! Самый лучший автомат состояния - это последовательное выполнение команд, тогда состояние однозначно отражается местом в коде. Полностью согласен. К сожалению, это возможно только для простейших устройств (один автомат), чтобы сделать то же самое для более сложных устройств (больше одного автомата) и сохранить привязку автомата к PC, нужно иметь инструмент, который принудительно переключает PC между "автоматами". Такой инструмент называется RTOS. Как?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 31 2017, 17:03
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Dog Pawlowa @ Jan 31 2017, 17:39)  нужно иметь инструмент, который принудительно переключает PC между "автоматами". Такой инструмент называется RTOS. Нет. Вы очевидно полагаете, что ОС это нечто такое, божественное, состоящее не из команд, действующее непостижимым образом. Нет, всё проще - ОС состоит из тех же самых команд, что и остальной код и переключение контекста (которое есть и в ОС), никто не мешает сделать вручную. И принудительности никакой не надо - переключение надо делать там-же, где у ТС-а находится switch/case (ну или вызов очередной функции из таблицы), только вместо этого будет сохранение контекста точки вызова (регистры, указатель стека, PC) и восстановление контекста тела автомата. И в результате получаем тело автомата в виде линейного кода, а не разорванного на много частей switch/case-ами и не распиленное на отдельные функции. И таких автоматов может быть сколько угодно - для каждого свой стек. Единственное что правда, так это то, что тело такого автомата будет похоже на задачу ОС с корпоративной многозадачностью.
|
|
|
|
Сообщений в этой теме
demiurg1978 [Вроде решено] Массив указателей на функции. Указатель на массив Jan 29 2017, 05:14 psL Цитата(demiurg1978 @ Jan 29 2017, 08:14) ... Jan 29 2017, 09:35 demiurg1978 Мне нужна функция, в качестве параметров которой у... Jan 29 2017, 09:43  psL Цитата(demiurg1978 @ Jan 29 2017, 12:43) ... Jan 29 2017, 09:54  andrew_b Цитата(demiurg1978 @ Jan 29 2017, 12:43) ... Jan 29 2017, 10:00       demiurg1978 Еще на ассемблере я использовал функции очистки ОЗ... Jan 29 2017, 16:27            Dog Pawlowa Цитата(demiurg1978 @ Jan 29 2017, 22:05) ... Jan 29 2017, 19:16                  jcxz Цитата(Dog Pawlowa @ Feb 1 2017, 06:56) Е... Feb 1 2017, 09:53                 demiurg1978 Цитата(jcxz @ Jan 31 2017, 23:03) И в рез... Feb 1 2017, 10:05                  jcxz Цитата(demiurg1978 @ Feb 1 2017, 12:05) В... Feb 1 2017, 11:58                   demiurg1978 Если честно, немного извращенно. Прототреды и то п... Feb 1 2017, 14:18                    jcxz Цитата(demiurg1978 @ Feb 1 2017, 16:18) Е... Feb 1 2017, 14:30                     demiurg1978 Я единственный раз использовал дополнительную пере... Feb 1 2017, 14:45                   Dog Pawlowa Цитата(jcxz @ Feb 1 2017, 15:58) Получили... Feb 2 2017, 07:52                    jcxz Цитата(Dog Pawlowa @ Feb 2 2017, 09:52) А... Feb 2 2017, 09:38                     demiurg1978 Цитата(jcxz @ Feb 2 2017, 15:38) А вот в ... Feb 2 2017, 09:56                      jcxz Цитата(demiurg1978 @ Feb 2 2017, 11:56) Х... Feb 2 2017, 13:19                       demiurg1978 Цитата(jcxz @ Feb 2 2017, 19:19) Вариант ... Feb 2 2017, 14:26                        jcxz Цитата(demiurg1978 @ Feb 2 2017, 16:26) В... Feb 2 2017, 15:07                         Dog Pawlowa Цитата(jcxz @ Feb 2 2017, 19:07) занимает... Feb 2 2017, 15:50                          demiurg1978 Что-то мне это баловство со стеком не нравится. Хо... Feb 2 2017, 16:33                           jcxz Цитата(demiurg1978 @ Feb 2 2017, 18:33) И... Feb 3 2017, 09:35                            Dog Pawlowa Цитата(jcxz @ Feb 3 2017, 12:35) Цель: ка... Feb 3 2017, 11:24                             jcxz Цитата(Dog Pawlowa @ Feb 3 2017, 13:24) Б... Feb 3 2017, 13:46                              Dog Pawlowa >> Покажите как Вы с помощью этого макроса р... Feb 4 2017, 10:28                               zltigo Цитата(Dog Pawlowa @ Feb 4 2017, 12:28) Д... Feb 4 2017, 12:29                                Dog Pawlowa Цитата(zltigo @ Feb 4 2017, 16:29) нет ЕС... Feb 5 2017, 07:53                                 zltigo Цитата(Dog Pawlowa @ Feb 5 2017, 09:53) Е... Feb 5 2017, 12:14                                  Dog Pawlowa Цитата(zltigo @ Feb 5 2017, 15:14) При эт... Feb 5 2017, 14:18                                   zltigo Цитата(Dog Pawlowa @ Feb 5 2017, 16:18) С... Feb 5 2017, 18:17                                    Dog Pawlowa Цитата(zltigo @ Feb 5 2017, 21:17) Быстры... Feb 5 2017, 18:35                                     zltigo Цитата(Dog Pawlowa @ Feb 5 2017, 20:35) Т... Feb 6 2017, 04:08                               jcxz Цитата(Dog Pawlowa @ Feb 4 2017, 12:28) Я... Feb 7 2017, 00:59                                Dog Pawlowa Цитата(jcxz @ Feb 7 2017, 03:59) PC сохра... Feb 7 2017, 14:36             k155la3 Цитата(jcxz @ Jan 31 2017, 01:34) . . . .... Feb 4 2017, 12:07 Obam ЦитатаВаш вызов функции против моего вызова функци... Feb 3 2017, 11:46
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|