05:08
Возвращение к бейсику
При программировании микроконтроллеров применяются конечные автоматы. Это позволяет добиться двух вещей:
-- Избежать миллиона флагов, следящих, что конкретно происходит в программе
-- Выполнять действия асинхронно, не используя при этом многопоточность или прерывания.
Покажу короткий автомат, который посылает запрос, ждёт ответа, а потом возвращается к началу.
Что тут происходит: при каждом вызове автоматной функции она начинает выполнять кусок кода, соответствующий текущему состоянию. В зависимости от состояния происходит переход к следующему куску. Тут куска всего три.
0: перейти к 1
1: если ответ готов, перейти к 2. если не готов, остаться в 1
2: перейти к 0
Можно нарисовать схему, но я этого делать не буду.
Так вот, в чём проблема: в обозначении состояний. Я в своих автоматах состояния просто нумерую 0, 1, 2...
А мой коллега из дружественной организации даёт состояниям названия, например, FSM_INITIAL_STATE.
И оба подхода плохие.
Номера:
-- цифры бессмысленны, без комментариев непонятно, зачем нужен переход и куда мы переходим
-- если необходимо внести промежуточные состояния, то либо приходится их размещать в конце автоматной функции (с бОльшими номерами), либо сдвигать нумерацию
Названия:
-- осмысленные названия состояний получаются очень длинными, могут даже приближаться к длине самого кода, который выполняет данное состояние (например, выше нулевое состояние можно назвать FSM_SEND_REQUEST)
-- видя название состояния, тяжело понять, где его искать в автоматной функции. Выше оно или ниже текущей строки, текущего состояния? Или каждый раз пользоваться поиском?
Однозначного решения у меня нет. Может быть, об этом написано в какой-то книжке про автоматы, но я их не читал. У меня есть решение только одной из проблем.
Все помнят бейсик? Что там строчки нумеровались 10, 20, 30. А зачем они так нумеровались? А как раз для того, чтобы между строчками можно было впихнуть ещё парочку строк не проводя полной перенумерации.
Вот и решение. Состояния можно нумеровать не 0, 1, 2, а 0, 10, 20.
-- Избежать миллиона флагов, следящих, что конкретно происходит в программе
-- Выполнять действия асинхронно, не используя при этом многопоточность или прерывания.
Покажу короткий автомат, который посылает запрос, ждёт ответа, а потом возвращается к началу.
void main(void)
{
for( ;; )
{
//главный цикл микроконтроллера
automaton();//вызов автомата
//таких автоматов в главном цикле могут быть десятки, каждый занимается своим делом
//и друг другу не мешают
}
return 0;
}
void automaton()
{
static int state=0;
switch(state)
{
case 0:
send_request();
state=1;
break;
case 1:
if(answer_ready())
state=2;
break;//если условие не выполнено, state остаётся равным 1
case 2:
read_answer();
state=0;
break;
}
}
Что тут происходит: при каждом вызове автоматной функции она начинает выполнять кусок кода, соответствующий текущему состоянию. В зависимости от состояния происходит переход к следующему куску. Тут куска всего три.
0: перейти к 1
1: если ответ готов, перейти к 2. если не готов, остаться в 1
2: перейти к 0
Можно нарисовать схему, но я этого делать не буду.
Так вот, в чём проблема: в обозначении состояний. Я в своих автоматах состояния просто нумерую 0, 1, 2...
А мой коллега из дружественной организации даёт состояниям названия, например, FSM_INITIAL_STATE.
И оба подхода плохие.
Номера:
-- цифры бессмысленны, без комментариев непонятно, зачем нужен переход и куда мы переходим
-- если необходимо внести промежуточные состояния, то либо приходится их размещать в конце автоматной функции (с бОльшими номерами), либо сдвигать нумерацию
Названия:
-- осмысленные названия состояний получаются очень длинными, могут даже приближаться к длине самого кода, который выполняет данное состояние (например, выше нулевое состояние можно назвать FSM_SEND_REQUEST)
-- видя название состояния, тяжело понять, где его искать в автоматной функции. Выше оно или ниже текущей строки, текущего состояния? Или каждый раз пользоваться поиском?
Однозначного решения у меня нет. Может быть, об этом написано в какой-то книжке про автоматы, но я их не читал. У меня есть решение только одной из проблем.
Все помнят бейсик? Что там строчки нумеровались 10, 20, 30. А зачем они так нумеровались? А как раз для того, чтобы между строчками можно было впихнуть ещё парочку строк не проводя полной перенумерации.
Вот и решение. Состояния можно нумеровать не 0, 1, 2, а 0, 10, 20.
05.03.2023 в 11:19
05.03.2023 в 16:09
05.03.2023 в 17:12
1
2
22
23
3
05.03.2023 в 17:21
Xersareeth, это статическая переменная. Статические переменные размещаются не на стеке, а в глобальной области, но доступ к ним есть только внутри функции. Кстати буквально вчера мне в отладочных целях пришлось такой стейт вывести в глобальное пространство, чтобы видеть, где автомат болтается.
RetXiRT suiR@ttig@$, не понял. То есть, у тебя числа не по порядку получаются?
05.03.2023 в 19:00
zHz00, простите (снова) за флуд!
RetXiRT suiR@ttig@$, а можно почаще этот аватар? концептуально очень)
05.03.2023 в 20:37
А вот у нас в рубях...Я как-то писал похожую штуку, но у меня автомат лежал в ассоциативном массиве в таком виде:Ну и код обработчика:
Приятно когда получается такие штуки писать вместо бесконечных select case =)
05.03.2023 в 23:16
первый
второй
второй 2
второй 3
третий
kshisia fialkina, я уже говорил - выбор аватаров у меня не пашет.
06.03.2023 в 05:46
enum States { state1, state2, state3 };
Для расширения просто добавляешь новое имя:
enum States { state1, state1_1, state1_2, state2, state3 };
Опять же, если имена пронумерованы, по ним всегда можно однозначно определить, в каком они отношении состоят друг с другом - кто выше, кто ниже.
06.03.2023 в 19:31
/в сторону: ну почему ирония никогда не прокатывает?../
06.03.2023 в 23:23
А то, на что вы жалуетесь, называется закон По (Poe's Law).
07.03.2023 в 00:45
smc.sourceforge.net/
Для плюсов есть шаманство на шаблонах, например, в boost.
www.boost.org/doc/libs/1_31_0/libs/mpl/doc/pape...
а ещё пишут библиотеки на макросах.
https://github.com/endurodave/C_StateMachine
Ни в одну из них я не лазил, так что говорить за это не буду.
Я-то человек ленивый, у меня обычно просто были таблички указателей на обработчики и матрица инциндентности.
07.03.2023 в 16:55
да, нос(а) не хватает. у него здорово было просто поприсутствовать...
07.03.2023 в 22:24
korrshun, ого, тема-то насущная. Спасибо, буду изучать.