Jump to content

    

Инкрементирующийся define

состояние-событие-выполнить действие-перейти в новое состояние

Как быть с ветвлением, т.е. если новое состояние определяется исходом действия?

Share this post


Link to post
Share on other sites
А кто придумывает номера для "состояний"?

При добавлении новой записи нужно править поле "перейти в новое состояние" предыдущей записи?

Или можно ставить только поля "событие" и "выполнить действие" а выполняться все будет линейно пока не дойдет до конца таблицы?

 

Чтобы не заморачиваться с ручной адресацией массива-таблицы, можно примерно так.

(но таблиц нужно 2 - одна состояний, вторая - переходов, в которую включены указатели на функции-обработчики)

IMHO

enum FSM_StateGo
{
    A1,
    A2,
    A3, 
    A_Stop,
    B1,
    B2,
    B3, 
    B_Stop,
    . . . .
};

enum FSM_State
{
    STATE_A,
    STATE_B
    . . .
};

TRun_Table RT[] =
{
[A1] = { STATE_A, A2 . . . . .  },
[A2] = { STATE_A, B2 . . . . .     },
[A3] = { STATE_A, A1 . . . . .  },
[A_STOP] = { STATE_A, A_STOP . . . . .  },
[B1] = { STATE_B, A2 . . . . .  },
[B2] = { STATE_B, B2 . . . . .     },
[B3] = { STATE_B, A1 . . . . .  },
[B_STOP] = { STATE_A, A_STOP . . . . .  },
. . . . . 
};

Edited by k155la3

Share this post


Link to post
Share on other sites
Как быть с ветвлением, т.е. если новое состояние определяется исходом действия?

 

По исходу действия генерируем событие, в таблице описываем переход по этому событию в нужное состояние.

 

У меня таблица выглядит так

 

__flash state_table_type STATE_MODBUS_NASTER_TABLE[]=    // Таблица состояний, условий перехода и действий режима ModBus мастер
   {
/*      из состояния                по событию              выполнить                   в состояние             в режим     */

       {ANY_STATE,                 NOT_NET_ACCESS,         init_state_mashine,         INIT,                   MODBUS_MASTER},
       {ANY_STATE,                 TIMER_OVFL,             init_state_mashine,         INIT,                   MODBUS_MASTER},
       {INIT,                      NET_ACCESS,             request_ana_from_monoblock, WAIT_MONOBLOCK_ANA,     MODBUS_MASTER},
       {WAIT_MONOBLOCK_ANA,        MONOBLOCK_DATA_RECEIVED,send_ana_to_modbus,         WAIT_CHECK_MODBUS_ANA,  MODBUS_MASTER},
       {WAIT_CHECK_MODBUS_ANA,     MODBUS_SENDED,          receive_ana_modbus_check,   NO_NEW_STATE,           MODBUS_MASTER},
       {WAIT_CHECK_MODBUS_ANA,     MODBUS_RECEIVED,        test_ana_modbus_check,      NO_NEW_STATE,           MODBUS_MASTER},
}

Share this post


Link to post
Share on other sites
__flash state_table_type STATE_MODBUS_NASTER_TABLE[]=

Терминология MONOBLOCK и _ana_ не из оперы modbus. Всегда поражаюсь людям изобретающим велосипеды...

 

PDU (Protocol Data Unit) — общая для всех физических уровней часть пакета MODBUS. Включает в себя код функции и данные пакета.

ADU (Application Data Unit) — полный пакет MODBUS. Включает в себя специфичную для физического уровня часть пакета и PDU.

Share this post


Link to post
Share on other sites

Опечатка?

Я хронический лентяй, программа работает на изделии с 2002 года. Исправлять лениво :-)

 

Терминология MONOBLOCK не из оперы modbus. Всегда поражаюсь людям изобретающим велосипеды...

 

Моноблок - это блоки нашей разработки на кастомном протоколе. А сие поделие является шлюзом в Modbus.

 

Вот, кстати, ссылка на автомат конечных состояний, описанный таблицей, управляемый событиями.

http://chipenable.ru/index.php/programming...nizatsiya-progr

Edited by Andrew_Q

Share this post


Link to post
Share on other sites
По исходу действия генерируем событие, в таблице описываем переход по этому событию в нужное состояние.

А как быть если после некоторых состояний необходимо пройти через определённую цепочку состояний, а затем вернуться к исходной цепочке? И так - в разных местах. :rolleyes:

состояние1

состояние2

состояние10

состояние11

состояние12

состояние3

состояние4

состояние5

состояние10

состояние11

состояние12

состояние6

...

Share this post


Link to post
Share on other sites
А как быть если после некоторых состояний необходимо пройти через определённую цепочку состояний, а затем вернуться к исходной цепочке?

Ваш пример похож на последовательность выполнения строк на бэйсике, соответственно используется что-то типа GOSUB :)

Ну и объединить цепочку состояний в одно состояние с дополнительным индексом ничего не мешает.

Регулярность и простота автоматов - хорошо, но все же иногда нужно немного и усложнять реализацию.

 

Share this post


Link to post
Share on other sites
Ваш пример похож на последовательность выполнения строк на бэйсике, соответственно используется что-то типа GOSUB :)

Ну и объединить цепочку состояний в одно состояние с дополнительным индексом ничего не мешает.

Регулярность и простота автоматов - хорошо, но все же иногда нужно немного и усложнять реализацию.

Объединить? А что тогда мешает объединить все остальные состояния автомата в одно? Если ничего - то и автомат не нужен, так как всего одно состояние осталось. А если есть автомат - значит он для чего-то нужен и нельзя объединить состояния.

А если нужен доплнительный индекс, то как потом возвращаться к основному? А если не один уровень вложенности, а больше? Стек хранения состояний городить?

Share this post


Link to post
Share on other sites
Объединить? А что тогда мешает объединить все остальные состояния автомата в одно? Если ничего - то и автомат не нужен, так как всего одно состояние осталось. А если есть автомат - значит он для чего-то нужен и нельзя объединить состояния.

Почему это нельзя объединить? Ну не будьте уж таким догматиком. Одну и ту же задачу могут выполнять автомат с одной переменной состояния, которое может принимать, допустим 16 значений и фрагмент программы, использующий 16 битовых флагов. И выглядеть они будут похоже, всего вместо case будет if, ну и присвоение чуть по другому.

А между этими двумя реализациями целый диапазон возможных решений.

 

А если нужен дополнительный индекс, то как потом возвращаться к основному? А если не один уровень вложенности, а больше? Стек хранения состояний городить?

Усложняете. Вот кода, описывающего одно состояние с дополнительными промежуточными состояниями проверки индикации.

 void fSelfTest(void)
{    if (old_status-status)
    {    StatusFirstTimeReady("Tst");
        SET_TIMER(N500ms);
    }
    if (event==evTimer)
    {    switch (status_var)
        {    case 0:        OnWorkRed1();     break;
            case 1:        OnChemLed();        break;
            case 2:        OnWaterLed();     break;
            case 3:        ToggleWorkColor();    OffChemWaterLeds();
            case 4:        status=    sWaiting;        break;
            default:    status_var=-1;
        }
        status_var++;
    }
}

 

Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.

Share this post


Link to post
Share on other sites
Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.

Вот и дошли до того, что при создании реальных автоматов стек состояний (как бы Вы его не назвали другими словами ) тоже можно и нужно использовать. Что тоже уменьшает безмерное разрастание состояний. У меня почти уже в привычке использовать в минимальной "базе" три состояния - текущее, предыдущее и то, на которое сейчас текущее будет измененно. Так же огромное знвчение стека в диагностике работы в РЕАЛЬНЫХ условиях - как дошли до ошибки.

 

Share this post


Link to post
Share on other sites
е и то, на которое сейчас текущее будет изменено.

А как Вы заглядываете в будущее оперируете с этим значением ?

У меня обычно просто - присвоил текущему и вышел, а анализ смены состояния в начале вызова обработчика автомата.

Share this post


Link to post
Share on other sites
Что касается стека... Стек, не стек, но что мешает запоминать предыдущее состояние и при необходимости туда возвращаться? Если интерфейс пользователя - один большой автомат, некоторые функции вызываются из разных меню, возвращаться нужно именно в предыдущее состояние. Можно назвать это одноуровневым стеком.

Конечно ничто не мешает. Только код становится уже плохо читаемым, слишком громоздким с такой реализацией на классических автоматах.

В этом случае я делаю псевдозадачу (которую можно считать к.автоматом). Только она не вытесняется принудительно другими задачами как обычная задача ОС, а вытеснение задачи происходит по логике её работы, при переходе к очередному состоянию автомата. А состояния автомата при этом - это значения PC, которые сохраняются в стеке при вытеснении задачи и на которые происходит переход при активации задачи. И код становится читаемым даже при наличии сложных ветвлений и вложенных состояний автомата.

Share this post


Link to post
Share on other sites
А как Вы заглядываете в будущее оперируете с этим значением ?

Хотим изменить текущее состояние автомата - "будущее" это то значение на которое изменим. "Прошлое" это сохраненное котрое было до текущего.

У меня обычно просто - присвоил текущему и вышел...

А присвоение текущему уже в конце обработчика - так и правильнее, ибо состояние сменилось, когда ВСЕ действия сопутствующие смене состояния уже произведены.

Таким образом в процессе переключения типично известны ТРИ состояния прошлое-настояшее-будущее.

Share this post


Link to post
Share on other sites

Тоже согласен, что если состояний больше десятка(а зачастую это штук 5) - значит что-то делаете не так. Это касается также и FPGA.

Задачу надо дробить на более простые, а не сливать все в одну кучу. Вот показали бы реальную задачу реализованную на 100 case-aх, я бы показал как ее реализовать гораздо проще.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this