Demiurg, это всё классно, если вы проект ТС собираетесь сами и с нуля делать. А ТСу потребуется тонна времени на изучение что это такое и как это программируется. И начинать с нуля. Скорость создания проекта стремиться в бесконечность. Для такого простого проекта как у него надо тупо "blink without delay" допилить и всё.
Показываю как пример. То, о чем просил ТС в конце корневого сообщения. Кнопка триггер. Нажимаем на кнопу, мигает один светодиод, загорается второй. Нажимаем на кнопу еще раз, оба светодиода гаснут. Спойлер
Искреннее спасибо всем участникам! Честно говоря, не думал,что такая вроде бы простенькая задача будет так сложно решаться. Demiurg, персонально 100 баллов в карму за конкретную помощь
Альтернативный и куда более простой в понимании вариант. Просто с миганием по таймеру. Писал в блокноте, не проверял, с нотацией CVAVR не знаком: Спойлер
while (1) { // кнопка-триггер нажимается, пока просто запоминаем включение у нас (флаг = 1) или выключение (флаг = 3) if (!PINC.2 && flag == 0) flag = 1; else if (!PINC.2 && flag == 2) flag = 3;
// кнопку-триггер отжали, теперь можно переключать состояние if (PINC.2 && flag == 1) { TCCR0 = (1 << CS02) | (1 << CS00); // Timer0 запуск, предделитель = /1024 PORTC.0 = 1; // Включаем d9 flag = 2; } else if (PINC.2 && flag == 3) { PORTC.0 = 0; // Включаем d9 PORTC.1 = 0; // и d10 тоже (а вдруг он был включен) flag = 0; // возвращаемся к "состоянию 0" TCCR0 = 0; // Stop Timer0 }
if (flag >= 2 && TCNT0 >= T0VAL) { // если у включеное состояние "триггера" и таймер0 досчитал до 195 (200мс), то мигаем d10 PORTC.1 ^= PORTC.1; // инвертируем состояние PC1 TCNT0 = 0; // Сбросить счетчик таймера }
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Да не сложно на самом деле. Нужно просто почитать какую нибудь книгу по авр микроконтроллерам. И цикл статей Татарчевского. Чтобы понять суть. Когда понимаешь суть, понимаешь, что делать.
Добавлено after 8 minutes: Можно и на флагах. Но код менее читабелен. И каждый флаг добавляет степень двойки состояний. А ещё неучтенные комбинации флагов, состояний. Конечные автоматы этого лишены. Там в принципе не может быть запрещённых состояний.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Ну да, мои 17 строк мигания куда менее читаемы, чем ваша "простыня" для примера ТС ) Ничего не имею против КА как таковых (только предпочитаю табличные реализации, по мне куда "читаемее"), но еще раз - для примера ТС из пушки по воробьям. Вы взяли свою либу, к которой привыкли. Для всех остальных - с ней еще разобраться надо. Даже мне сходу на глаз вся реализация не сразу понятна. Надо читать пачку исходников, чтобы разобраться. А вы предлагаете ТС понять её? Ну-ну.
PS: Поглядел мельком ваш архив - ну у вас банально switch...case, обернутый просто для расширяемости удобной. Таблички переходов, со ссылками на функции обработчиков куда "читабельней" в итоге, но понять их механизм новичку будет еще сложнее.
Добавлено after 1 minute 37 seconds: Или массив структур или полная таблица переходов, как в последнее время стал делать, если оперативки не жалко. Тут еще вкратце писал: https://www.radiokot.ru/forum/viewtopic ... 4#p3826024 Но это всё ТС нафиг не нужно пока что.
switch (m->Signal) { case DSM_SIGNAL_ENTRY: // Здесь код при первом входе в состояние после его смены. // Например, инициализация таймеров, структур, выделение памяти и пр.
break;
case DSM_SIGNAL_NONE: // Здесь код, вызываемый циклически диспетчером break;
case DSM_SIGNAL_EXIT: // Здесь код, когда состояние сменилось // Можно освободить память, остановить таймеры и пр.
Ну да, мои 17 строк мигания куда менее читаемы, чем ваша "простыня" для примера ТС )
Дело не в 17 строчках. Краткость не всегда полезна. При вашем подходе начнёшь что нибудь менять, утонешь в флагах. Программа дальше станет нечитабельной. Без малейших шансов адекватно править, менять логику.
NStorm писал(а):
Вы взяли свою либу, к которой привыкли. Для всех остальных - с ней еще разобраться надо. Даже мне сходу на глаз вся реализация не сразу понятна. Надо читать пачку исходников, чтобы разобраться. А вы предлагаете ТС понять её? Ну-ну.
Дело не в личной либе. И разбираться ТС-у в любом случае. Я дал ссылку на цикл статей. У меня на данном примере сделано практически по такому же подходу, как в статьях. Служба сообщений, в моем случае сообщения-события. При этом не очередь, из за которой свои нюансы всплывают. Программные таймеры. Обычный switch-case, никаких оберток. Ими я как раз не стал пугать ТС.
NStorm писал(а):
Таблички переходов, со ссылками на функции обработчиков куда "читабельней" в итоге, но понять их механизм новичку будет еще сложнее.
Табличный интерпретатор - неплохо. Тоже свои нюансы. Сначала, ТС пусть почитает, что такое КА вообще. Служба сообщений, событий - то есть, взаимодействие программных модулей. А это ключевой момент. Программные таймеры. Потом ТС сам уже будет решать, какими методами ему реализовать КА. А также табличные интерпретаторы.
Данные, структуры, алгоритмы. Чем больше данных, структур, тем меньше программа. И наоборот. В первом случае, в идеале, вся программа сводится к табличному интерпретатору. Таблицы, структуры хороши. Но и тут есть нюанс. Жёстко заданная логика. Универсальности нет, как ни бейся. Пройденный этап. Поэтому, компромиссы. Анализ проекта. Систематизация данных. Синтез подходов. Разные интерпретаторы. Разные таблицы. Есть ещё метод. Подглядел у одного эмбеддера. Делается одна большая таблица, и макросами делаются методы выборки данных под конкретный интерпретатор таблицы. X-Macro.
Добавлено after 9 minutes 36 seconds:
parovoZZ писал(а):
А вот моя вариация на тему КА с диспетчером:
Выложите какой нибудь простой пример проект на вашем подходе. Архив с готовым, скомпилированным, рабочим проектом. Посмотрю на досуге.
При вашем подходе начнёшь что нибудь менять, утонешь в флагах. Программа дальше станет нечитабельной.
Всего-лишь добавить enum для флагов и всё станет читаемей.
Цитата:
Таблицы, структуры хороши. Но и тут есть нюанс. Жёстко заданная логика. Универсальности нет, как ни бейся
Поглядите по ссылке. У меня таблица лишь задает связь (текущее состояние, событие) => переход. Переход - это функция, там можно как угодно обрабатывать ситуацию и потом вернуть любое новое состояние. В т.ч. переход сам может вызвать другой переход и т.д. Универсальности даже больше, чем внутри case'а.
Добавлено after 4 minutes 45 seconds: Простой пример: Спойлер
Одна и та же функция перехода trToggleBypass может быть вызвана из любой комбинации (текущее состояние, событие). Любой переход может вызвать функцию другого перехода, как делает trAcRestoration при наличии определенного условия. Есть обработчики переходов из любого события или независимо от текущего состояния (как в данном случае [ST_ANY] делает). Вот и думайте, где большое гибкости )
Всего-лишь добавить enum для флагов и всё станет читаемей.
Вы сами прекрасно осознаете, что подход на флагах сложнее, нечитабельней, мало того, флаги чреваты неучтенными сочетаниями, состояниями.
NStorm писал(а):
Вот и думайте, где большое гибкости )
А что тут думать, сам активно таблицы применяю. MicroMenu, к примеру, собственной переработки. Но для ТС на данный момент это будет сложно. Работа с указателями, структурами. Если разберётся, гуд. Инфу мы ему предоставили, куда копать.
Одна и та же функция перехода trToggleBypass может быть вызвана из любой комбинации (текущее состояние, событие). Любой переход может вызвать функцию другого перехода, как делает trAcRestoration при наличии определенного условия. Есть обработчики переходов из любого события или независимо от текущего состояния (как в данном случае [ST_ANY] делает). Вот и думайте, где большое гибкости )
Я как-то по результатам одной темы про КА, там и Demiurg был, написал следующий класс: Спойлер
Код:
enum class State : uint8_t { _, A, AC, ACD, ACDA, AB, ABA, ABAD, ABADC }; enum class Event : uint8_t { PressA, PressB, PressC, PressD };
StateMachine<transitions> sm; sm.process(Event::PressB); sm.process(Event::PressD); sm.process(Event::PressA); // A sm.process(Event::PressC); // AC sm.process(Event::PressD); // ACD sm.process(Event::PressA); // ACDA -> greenLed.toggle()
Тут видно в таблице по одной лямбде, на самом деле указателей на функции для каждого состояния может быть два(action/guard), на 32-х битных мк они бы занимали 8 байт, плюс байт состояния(на M0 пришлось бы дополнять до 12 байт), но в данном случае сначала мы проходим по таблице и находим все функции, затем размешаем их в конце таблицы а вместо самих указателей подставится индекс(байт), т.е. на каждое состояние нужно всего 3 байта. Таблица естественно ложится во флеш. А самым большим недостатком оказалось то, что реально я это ни разу не использовал, всегда находятся более простые подходы
Reflector, по ссылке выше что давал, я сначала делал таблицы с проходом. Памяти меньше расход, но больше циклов на проход таблицы для поиска. Компромисс между циклами и памятью. Если памяти хватает, мне указатели показались удобнее в использовании. Ну и речь о чистом Си.
Demiurg, это всё понятно, но я "вангую" что и с вашим вариантом даже ТС не разберется и дальше не допишет. Не тот уровень владения языком пока что еще, судя по его исходнику. Вариант на флаге без сомнения неудобен для развития дальнейшего. Но о развитии в посте ТС речи не шло. А его задачу это решает более просто, "в лоб" и должно быть в рамках возможности понять им смысл.
Dimon456, вопрос не о том, как развести порты, а о том, как сделать "параллельно выполняемый" код, и чтоб эти параллельные ветви друг другу не мешали
_________________ Просто не учи физику в школе, и вся твоя жизнь будет наполнена чудесами и волшебством Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
"параллельно выполняемый" код возможен только в много поточных системах, как вариант DMA в stm32, даже windows у вас на компе не относится к "системе реального времени". Остальное все - последовательно исполняемый код, как можно говорить о какой-то параллельности.
Вы просто завернули последовательность if else или switch case в красивую не понятную обертку. Универсальности это не дает.
Dimon456, поэтому "параллельно выполняемый" видимо в кавычках и был. И DMA - это не "параллельно выполняемый". И параллельность и ОСРВ - совсем разные вещи. Что-то вы всё в кучу намешали.
Псевдопараллельность. Те принципы которые применяются в диспетчерах, ртос. Дробление выполнения программных модулей на куски либо временными отрезками (вытеснение).
у меня уместится ... код.... блин, код наверно только в понедельник....
_________________ Просто не учи физику в школе, и вся твоя жизнь будет наполнена чудесами и волшебством Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
"Dimon456". Мне не нравится ваша позиция. Одна страничка. Свой подход я обьяснял. Проект делится на логические модули. Если я распишу все в одной странице, я утону в этой странице. Если вам это не нравится, то не проецируйте этот одностраничный подход на мои сообщения. Это ваше личное предпочтение. Вы одной вещи не понимаете. Главный модуль, пример которого я показал, он как раз уместился в страничку. И уместится, если ТС покажет полное ТЗ. Не суть. Готовь сани летом, телегу зимой. Приготовь свое рабочее пространство. И работай на одной страничке. Другие странички считайте ножовкой, болгаркой ну и так далее.
Сейчас этот форум просматривают: AQ29, Varlakotam и гости: 29
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения