Например TDA7294

Форум РадиоКот • Просмотр темы - Как поместить цикл в case оператора switch
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Пн авг 18, 2025 23:22:38

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 252 ]     ... , , , 7, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вс окт 09, 2022 19:01:58 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Все таки ты больной. Ты закусился на мои слова о шаблонности. Как же ты подчеркиваешь свою якобы исключительность. Расписал применяемые тобой сокращения? Спасибо.
Я писал на аасеблере несколько лет, потом перешёл на си. На ассемблере я при написании проектов держал в уме все переменные. А когда указатели на указатели на указатели, да ещё адреса. Это ммм. Жёстко. На си стало проще. Переход с обычного программирования на автоматное тоже дало слом мышления. И что?
Ты все таки так и не понял, что я тебе говорил. У тебя болезненное самолюбие. Засрал всю тему. Доказывай свой профессионализм примерами, ответами. А не своей якобы исключительностью. Повторяю, не впечатлил. Не знаю, чем ты там занимаешься, какие устройства у тебя в активе. Я общался со специалистами у которых в активе серийные устройства. Тысячи. Десятки и сотни тысяч тиражи. Видел их примеры. И они не выеживались, как ты.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вс окт 09, 2022 19:03:37 
Опытный кот
Аватар пользователя

Карма: 2
Рейтинг сообщений: 164
Зарегистрирован: Ср авг 03, 2022 05:22:56
Сообщений: 848
Рейтинг сообщения: 2
Demiurg, причем тут ВЫ и ваш жизненный путь? По делу темы есть что написать? Вон топикстартер ПРОСИЛ переделать ЕГО код так, чтобы светики замигали. Ну. У вас есть что по делу, кроме воспоминаний о вашем хероическом прошлом на ассемблере? :)

Заметка по ходу дела: на ассемблере НЕТ указателей. Это прерогатива Си-подобных языков. На асемблере есть косвенная адресация. Возможно, есть какие-то надстройки над ассемблером с некоторым подобием указателей. Но это уже не чистый ассемблер.

Demiurg, вот серьезно - УСПОКОЙСЯ. Уймись. Перестань переводить стрелки, это НЕ мужское поведение. Бабское. Склочная бабка на базаре какая-то, один-в-один. Это уже перешло все рамки приличий - переход на личности, оскорбления, флуд и срач. Скажи спасибо, что я просто не воспринимаю эти выпады от хрен знает какого поцыка из инета, без роду и племени, без образования и вообще от дырки от бублика.
Топикстартер просил внести изменения в ЕГО код. Вот и займитесь этим. Остальное - ересь.

И вообще. Demiurg-у настоятельная рекомендация - следить за базаром и не толкать фуфло, по-русски говоря. Чел, видимо, в табло никогда не отхватывал, что распоясался тут и приборзел, начал переводить стрелки, передергивать, придумывать того, чего не было. С ним тут цацкаются, не обращают внимания на его оскорбления и переходы на личности, а эта тварь совсем наглость потеряла и просто охренела вконец. Это че ваще за срань такая? Кто такой этот Demiurg и кто ему позволял так разговаривать? Это ваще че за баба тут базарная завелась то? С ним по-человечьи, на "вы", сюси-пуси тут с ним, а эта дрянь берега попутала. Смотри-ка, нашелся хрен с горы. Насочинял тут, переврал всё и вся, и еще, дрянь такая, огрызается. Мало его били наверно, что попутал бабское базарное хайло и диалог специалистов. Смотри-ка, вылез тут. Понакалякал херни непристойной, а еще смеет, дрянь такая, людей осуждать тут. Ишь ты, мелкая сошка, а какой форс давит. Тьху, млин. Не матерился бы, так если ему позволить, эта дрянь так и на шею сядет.


Последний раз редактировалось MLX90640 Вс окт 09, 2022 21:03:44, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Вс окт 09, 2022 19:17:03 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Это ты повел себя неадекватно. Я тоже хорош, купился на твое недостойное поведение.


Последний раз редактировалось Demiurg Пн окт 10, 2022 02:32:54, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 00:28:10 
Друг Кота
Аватар пользователя

Карма: 96
Рейтинг сообщений: 1472
Зарегистрирован: Вт мар 16, 2010 22:02:27
Сообщений: 15136
Откуда: ДОНЕЦК
Рейтинг сообщения: 0
А что с моим кодом?

Вариант для адуринки (нанки)...
Схема
Изображение
собственно код:
Спойлер
Код:
const byte Sn0 = 7; // линия D7
const byte Sn1 = 8; // линия D8
const byte Sn2 = 9; // линия D9
const byte LED0 = 4; // линия D4
const byte LED1 = 5; // линия D5
const byte LED2 = 6; // линия D6
volatile byte tmp0 = 0; // временный буфер 0
volatile byte tmp1 = 0; // временный буфер 1
volatile byte Flag = 0; // контрольный флаг
void wait0();
void wait1();


void setup() {
  // put your setup code here, to run once:
 digitalWrite(LED0, HIGH); digitalWrite(LED1, HIGH); digitalWrite(LED2, HIGH);
 pinMode(Sn0, INPUT_PULLUP); pinMode(Sn1, INPUT_PULLUP);
 pinMode(Sn2, INPUT_PULLUP); pinMode(LED0, OUTPUT);
 pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT);
 
}

void loop() {
  // put your main code here, to run repeatedly:
// ожидание нажатия
  while (!Flag)
  {
   wait0();
   if (tmp0==tmp1){Flag=1;}
    else {Flag=0; tmp1=tmp0;}
   delay(35);
  }
  switch (tmp1){
    case 6:
     wait0();
     if (tmp1==tmp0)
      { // выполнять, если нажатие подтверждено
       digitalWrite(LED0, LOW); digitalWrite(LED1, HIGH);
       digitalWrite(LED2, HIGH); Flag=0;
      }
     break;
    case 5:
     wait0();
     if (tmp1==tmp0)
      { // выполнять, если нажатие подтверждено
       digitalWrite(LED0, HIGH); digitalWrite(LED1, LOW);
       digitalWrite(LED2, HIGH); Flag=0;
      }
     break;
    case 3:
     wait0();
     if (tmp1==tmp0)
      { // выполнять, если нажатие подтверждено
       digitalWrite(LED0, HIGH); digitalWrite(LED1, HIGH);
       digitalWrite(LED2, LOW); Flag=0;
      }
     break;
    default:
      // if nothing else matches, do the default
      // default is optional
    break;
  }
/*
 * ожидание отпускания всех кнопок после того, как был завершен
 * хотя бы один из обработчиков
 * если при входе в селектор имело место отсутствие нажатий
 * или неразрешенная комбинация контроль отпускания игнорируется
 */
 while(!Flag)
 {
  wait1();
  if (tmp0==0)
  { //ожидание подтверждения отпускания
    delay(35); wait1();
    if (tmp0==0){Flag=1; tmp1=0;}
  }
 }
 Flag=0;
}

//----------

void wait0()
{
 tmp0=((digitalRead(Sn0) << 0) | (digitalRead(Sn1) << 1) | (digitalRead(Sn2) << 2)) & 0x07;
}
void wait1()
{
 tmp0 = ~(((digitalRead(Sn0) << 0) | (digitalRead(Sn1) << 1) | (digitalRead(Sn2) << 2)) | 0xF8);
}

архив проекта
Вложение:
sled.zip [13.41 KiB]
Скачиваний: 31

версия IDE 1.8.19 версия платформы ардуино нано 1.8.3
В данном случае все обьявления и описания/инициализации в одном файле(для адуринки это главный файл проекта *.ino).
собственно та же структура селектора на основе switch/case, но захват данных с интервалами антидребезга вынесены до и после селектора. Отрабатывается последовательность
обнаружение нажатия
подтверждение нажатия
исполнение задачи команды(кнопки)
ожидание полного отпускания всех кноп
подтверждение полного отпускания всех кноп
далее с начала(возврат к началу сканирования).
Алгоритм работы устройства -
исходно все индикаторы погашены
нажатие любой клавиши зажигает соответствующий кнопе светик и одновременно гасит остальные.
прожка проверена на симуляторе ардуино UNO - UnoArduSim 2.9.2
(https://www.sites.google.com/site/unoardusim/)
Относительно большой объем кода после компиляции обусловлен установленной в программе "по умолчанию" обработкой УАРТ - специфика ардуиноIDE, к данному проекту не относящаяся (скрыто от пользователя).
А вот для одновременного обеспечения еще и мигания светика с определенной частотой уже потребуется аппаратный таймер.
Так как мигалка действует параллельно исполнению основной программы. В данном случае в каждом исполнительном фрагменте нужно будет добавить перезагрузку параметров таймера и разрешение его работы вместо включения светика. Сигнал прерывания от таймера будет инвертировать соответствующий выход.
Делать программный вариант также возможно, но его надо ставить за пределами селектора(подобно обработчику захвата нажатия/отпускания кнопок), а не внутри (в блоках case - исполнителя команды) так как необходимо одновременно и сканировать кнопы и выдавать меандр на активный выход.
:write:


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 07:00:47 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 0
BOB51, это пример, как из простого сделать сложное. Ты так окончательно запутаешь начинающего.)
При нажатии кнопки чего хотелось бы делать со светодиодами?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 08:56:59 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Можно так. :)
Спойлер
Код:
//==================
#include "proc_device.h"
//==================

//==================
void proc_device (void)
{
   static u08 _proc_device;

   switch (_proc_device)
   {
      case 0: // Init IO
         io_init ();
         _proc_device = 1;
         break;

      case 1:
         if (Get_Event (EV_ID_INPUTS_CHANGE))
         {
            switch (get_inputs ())
            {
               case (IN_1_BIT):
                  if (get_proc_led_1_state () == 0)
                  {
                     set_proc_led_2_off ();
                     set_proc_led_3_off ();

                     set_proc_led_1_run ();
                  }
                  else
                     set_proc_led_1_off ();
                  break;

               case (IN_2_BIT):
                  if (get_proc_led_2_state () == 0)
                  {
                     set_proc_led_1_off ();
                     set_proc_led_3_off ();

                     set_proc_led_2_run ();
                  }
                  else
                     set_proc_led_2_off ();
                  break;

               case (IN_3_BIT):
                  if (get_proc_led_3_state () == 0)
                  {
                     set_proc_led_1_off ();
                     set_proc_led_2_off ();

                     set_proc_led_3_run ();
                  }
                  else
                     set_proc_led_3_off ();
                  break;
            }
         }
         break;

      default:
         set_proc_led_1_off ();
         set_proc_led_2_off ();
         set_proc_led_3_off ();
         break;
   }

   proc_led_1 ();
   proc_led_2 ();
   proc_led_3 ();
}
//==================

//==================
void io_init (void)
{
   set_bit (OUT_1_DDR, OUT_1); // Пин OUT_1 - выход
   set_bit (OUT_2_DDR, OUT_2); // Пин OUT_2 - выход
   set_bit (OUT_3_DDR, OUT_3); // Пин OUT_3 - выход
}
//==================

//==================
void out_1_on (void)
{
   __out_1_on ();
}

void out_2_on (void)
{
   __out_2_on ();
}

void out_3_on (void)
{
   __out_3_on ();
}
//----------
void out_1_off (void)
{
   __out_1_off ();
}

void out_2_off (void)
{
   __out_2_off ();
}

void out_3_off (void)
{
   __out_3_off ();
}
//----------
void out_1_switch (void)
{
   __out_1_switch ();
}

void out_2_switch (void)
{
   __out_2_switch ();
}

void out_3_switch (void)
{
   __out_3_switch ();
}
//----------
void all_outs_off (void)
{
   out_1_off ();
   out_2_off ();
   out_3_off ();
}
//==================

//==================
static soft_timer ST_PROC_LED_1;
static soft_timer ST_PROC_LED_2;
static soft_timer ST_PROC_LED_3;

static u08 _proc_led_1;

void set_proc_led_1_run (void)
{
   led_1_off ();
   _proc_led_1 = 1;
}

void set_proc_led_1_off (void)
{
   led_1_off ();
   _proc_led_1 = 0;
}

u08 get_proc_led_1_state (void)
{
   return _proc_led_1;
}

void proc_led_1 (void)
{
   switch (_proc_led_1)
   {
      case 0:
         break; // Idle.

      case 1:
         #ifdef __ST_PERIOD__
         set_soft_timer (ST_PROC_LED_1, 0, 100);
         #else
         set_soft_timer (ST_PROC_LED_1, 0); // !!!!!!!!!!!!!!!!!!!!!!!!!!!
         #endif
         _proc_led_1 = 2;
         break;

      case 2:
         if (handle_soft_timer (ST_PROC_LED_1))
         {
            if (!check_led_1_state ())
               led_1_on ();
            else
               led_1_off ();

            #ifdef __ST_NO_PERIOD__
               set_soft_timer (ST_PROC_LED_1, 100); // !!!!!!!!!!!!!!!!!!!!!!!!!!!
            #endif
         }
         break;
   }
}
//==================


На этом я пока заканчиваю. Написано со смартфона. Вечером, если получится, скомпилирую, покажу видео работы.
В моих примерах показывается псевдопараллельная работа программных модулей. Выполнение основного цикла выполняется с запасом за системный тик. Скажем, в моих примерах это 1 мс. Распараллеливание процессов достигается проверкой условий, состояниями конечных автоматов. Никаких долгих циклов. Правило: основной цикл выполняется с запасом за системный тик. Показал программные таймеры. Взаимодействие программных модулей.
Как опрашивать кнопки, в этом топике показаны несколько примеров.
Если у тс есть вопросы, задавайте.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 10:39:01 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 2
Офигеть! Кто сложнее? https://wokwi.com/projects/345112496512696914


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 10:58:50 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Баловство. :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 11:15:50 
Друг Кота
Аватар пользователя

Карма: 96
Рейтинг сообщений: 1472
Зарегистрирован: Вт мар 16, 2010 22:02:27
Сообщений: 15136
Откуда: ДОНЕЦК
Рейтинг сообщения: 0
BOB51, это пример, как из простого сделать сложное. Ты так окончательно запутаешь начинающего.)
При нажатии кнопки чего хотелось бы делать со светодиодами?

Ничего там сложного.
Для мех. кноп стандартно:
ожидание нажатия
подтверждение нажатия и захват комбинации с линий возврата клавиатуры с установкой флага запроса обработки
выполнение обработчика команды
ожидание полного отпускания всех кноп
подтверждение полного отпускания всех кноп
и повтор...
Единственно можно еще чуток "причесать" - цикл ожидания не while(условие), а do {обработчик}while(условие)
и оба анализатора с их антидребезгом перенести в конец прожки (за селектором switch/case).
Да еще добавить исходную хотелку топикстартера - програмо модифицируемую мигалку для каждого из включенных светиков.
Причем, как я понял, мигалка также с изменяемыми параметрами и по частоте и по картинке в зависимости от главной задачи в данный момент для данного индикатора...
(...Необходимо при переключении кнопкой с помощью оператора switch включать мигание светодиода с различной частотой на каком либо выводе...
...необходимо зациклить ее в теле case,но невозможно переключить switch в следующий case.Просто невозможно выйти из бесконечного цикла...)
Вот и соорудил "универсальну трехкнопку"...
:roll:
Кыстати...
У АВРки (для ардуино) при инициализации вывода как OUTPUT желательно предварительно добавлять вывод в PIN того уровня, что должен появиться сразу после инициализации, а уж потом разворачивать вывод как OUTPUT...
Иначе есть вероятность "иголок" т.е.
digitalWrite(pin, уровень по умолчанию) и затем
pinMode(pin, OUTPUT)...
8)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 12:20:51 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 2
Баловство. :)

"Толи дело у меня. Ну ведь солидно же!") А на.уеверчено...( Так ещё уметь надо!

Добавлено after 3 minutes 45 seconds:
У АВРки (для ардуино) при инициализации вывода как OUTPUT желательно предварительно добавлять вывод в PIN того уровня, что должен появиться сразу после инициализации, а уж потом разворачивать вывод как OUTPUT...
Иначе есть вероятность "иголок" т.е.
digitalWrite(pin, уровень по умолчанию) и затем
pinMode(pin, OUTPUT)...
8)

Дядя, не смеши. При чём здесь Ардуино? И особенно "иголки" опасны для светодиодов.)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 13:02:56 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
OKF, Мои примеры кажутся сложными, усложненными. На самом деле это не так. Тут уже шел разговор про алгоритмы, графы. Я ещё когда писал на асме, увидел ощутимый плюс такого подхода. Все собирается, как конструктор. И алгоритм легко просчитывается умственно. Не всегда, смотря что делать.
Пример. Один светодиод. Нужно реализовать индикацию питания (постоянно включен), дежурный режим (мигание). Индикация ошибок, аварии. При этом кол-во ошибок может быть больше 10. И подобная индикация очень легко реализуется. Без флагов, на состояниях. Единицы короткие вспышки, десятки более длительные.

По поводу иголок. Сам лично встречал в приборах ошибочные срабатывания сдвиговых регистров, как раз из за неправильной инициализации выходов. Также был случай, так и не смог победить при использовании стороннего реле времени. При включении реле выдавало иголку. Для катушек реле, пускателей это не критично. А для меня это стало проблемой. Выход реле времени шел на дискретный вход блока управления.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 13:27:05 
Друг Кота
Аватар пользователя

Карма: 62
Рейтинг сообщений: 879
Зарегистрирован: Вт апр 24, 2007 07:45:40
Сообщений: 6068
Откуда: Minsk
Рейтинг сообщения: 0
При чём здесь Ардуино? И особенно "иголки" опасны для светодиодов.)

Ну если Ардуньку использовать только для "помигать светодиодами" - то ахерн с ними, с иголками, тогда BOB51 действительно усложняет. :)

_________________
Изображение


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 14:19:09 
Друг Кота
Аватар пользователя

Карма: 96
Рейтинг сообщений: 1472
Зарегистрирован: Вт мар 16, 2010 22:02:27
Сообщений: 15136
Откуда: ДОНЕЦК
Рейтинг сообщения: 0
Вообще-то это правило для всех АВРок, независимо от того, в каком виде их потреблять.
Уж такова природа(структура) их портов.
Исходно по reset лапки в Z состоянии, а дальше - как программа решит (и как внешняя схемотехника укажет).
В том числе и при перезапуске после возможного сбоя.
8)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:03:51 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 0
Вот и я говорю, при чём здесь Ардуино, когда это правило для всех.)
Да и дело не в иголках, а в том кому они могут мешать. В данном задании кому? Как и дребезг. И при чём здесь Ардуино вообще, а, Jack_A!
А из говна накрутить "супер" - это да, это мы можем, правда, Demiurg?
Я изменил Ардуино на AVR, найдите отличия.
Там же: https://wokwi.com/projects/345112496512696914


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:14:01 
Опытный кот
Аватар пользователя

Карма: 2
Рейтинг сообщений: 164
Зарегистрирован: Ср авг 03, 2022 05:22:56
Сообщений: 848
Рейтинг сообщения: 0
Кстати... Раз уж писать "небрежно" и "топорно", то вот совершенно топорный код, написанный левой ногой и с наплеванием на все принцЫпы "инкапсуляхцыи". Но! С одной мааааленькой вишенкой на торте :) Таблица состояний и переходов конечного автормата. Я еще в прошлом примере хотел так написать, да не стал, дабы сильно не пугать некоторых "учителей" :)
Вобщем... ну, это, как всегда - работает.



Спойлер
Код:
/* Макросы чтения входов от кнопок */
#define READ_IN1()      (GPIOB->IDR & (1<<2) )
#define READ_IN2()      (GPIOB->IDR & (1<<13))
#define READ_IN3()      (GPIOA->IDR & (1<<7) )

/* Макросы переключения светодиодов на противоп.сост. */
#define LED1_SWICHT()   GPIOA->ODR ^= 1<<5
#define LED2_SWICHT()   GPIOA->ODR ^= 1<<3
#define LED3_SWICHT()   GPIOB->ODR ^= 1<<1

/* Макросы выключения светодиодов */
#define LED1_OFF()      GPIOA->BSRRH = 1<<5
#define LED2_OFF()      GPIOA->BSRRH = 1<<3
#define LED3_OFF()      GPIOB->BSRRH = 1<<1

/* Периоды счета таймеров */
#define PERIOD_1   30000
#define PERIOD_2   60000
#define PERIOD_3   90000
#define PERIOD_BTN   10000

/** ----------
 */
int main(void)
{
   /* счетчики для таймеров мигания и опроса кнопок */
   uint32_t cnt1 = PERIOD_1, cnt2 = PERIOD_2, cnt3 = PERIOD_3;
   uint32_t cntbtn = PERIOD_BTN;

   /* переменные для разрешения мигания светодиодов */
   uint8_t en1 = 0, en2 = 0, en3 = 0;

   int8_t mode = 0;   // переменная режима работы
   uint8_t read_btn;   //переменная чтения входов
   uint8_t fsm_s = 0;   // переменная текущего номера состояния КА

   /* таблица переходов КА */
   const uint8_t fsm_ts[][8] = {
   /* s  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 */
   /* s0*/{0,  1,  2,  0,  3,  0,  0,  0},

   /* s1*/{4,  1,  1,  1,  1,  1,  1,  1},
   /* s2*/{5,  2,  2,  2,  2,  2,  2,  2},
   /* s3*/{6,  3,  3,  3,  3,  3,  3,  3},

   /* s4*/{4,  7,  2,  4,  3,  4,  4,  4},
   /* s5*/{5,  1,  7,  5,  3,  5,  5,  5},
   /* s6*/{6,  1,  2,  6,  7,  6,  6,  6},

   /* s7*/{0,  7,  7,  7,  7,  7,  7,  7} };


   /* таблица выходного алфавита КА */
   const int8_t fsm_out[] =
   /* s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7 */
     {-1,   1,   2,   3,  -1,  -1,  -1,  0};


   /*---- [Main Loop] ----------*/
   while(1)
   {
      /*---- Получение состояний кнопок ----*/
      if(cntbtn == 0)  // если цикл полностью отсчитан
      {
         read_btn = 0; // обнуление переменной

         /* чтение входов и формирование входного символа КА */
         if(READ_IN1() == 0) read_btn |= 1<<0;
         if(READ_IN2() == 0) read_btn |= 1<<1;
         if(READ_IN3() == 0) read_btn |= 1<<2;

         /* алгоритм переходов КА */
         fsm_s = fsm_ts[fsm_s][read_btn];
         mode = fsm_out[fsm_s];

         /*---- Выбор режима работы -----*/
         switch(mode){
         case 0:   // все выключено
            en1 = 0; en2 = 0; en3 = 0;
            break;
         case 1:   // разрешено мигание светика 1
            en1 = 1; en2 = 0; en3 = 0;
            break;
         case 2:   // разрешено мигание светика 2
            en1 = 0; en2 = 1; en3 = 0;
            break;
         case 3:   // разрешено мигание светика 3
            en1 = 0; en2 = 0; en3 = 1;
            break;
         default:
            break;
         }

         cntbtn = PERIOD_BTN; // перезапустить счетчик с нового цикла
      }


      /*---- Мигание светодиода 1 ----*/
      if(cnt1 == 0)   // если цикл полностью отсчитан
      {
         /* проверка, разрешено ли мигать */
         if(en1 == 1)
            LED1_SWICHT(); // переключить светодиод 1 на противоположное состояние
         else
            LED1_OFF();    // принудительно выключить светодиод

         cnt1 = PERIOD_1;   // перезапустить счетчик с нового цикла
      }

      /*---- Мигание светодиода 2 ----*/
      if(cnt2 == 0)   // если цикл полностью отсчитан
      {
         /* проверка, разрешено ли мигать */
         if(en2 == 1)
            LED2_SWICHT(); // переключить светодиод 2 на противоположное состояние
         else
            LED2_OFF();    // принудительно выключить светодиод

         cnt2 = PERIOD_2;   // перезапустить счетчик с нового цикла
      }

      /*---- Мигание светодиода 3 ----*/
      if(cnt3 == 0)   // если цикл полностью отсчитан
      {
         /* проверка, разрешено ли мигать */
         if(en3 == 1)
            LED3_SWICHT(); // переключить светодиод 3 на противоположное состояние
         else
            LED3_OFF();    // принудительно выключить светодиод

         cnt3 = PERIOD_3;   // перезапустить счетчик с нового цикла
      }

      /*---- Декременты счетных переменных ----*/
      cnt1--;
      cnt2--;
      cnt3--;
      cntbtn--;

   }/* while() */
}/*---- main() ----------*/


А это граф работы конечного автомата чтения кнопок. Допускающие последовательности: 1-0-1-0, 1-0-2-0, 2-0-3-0 ну и так далее...
Изображение
Итого. Блягодаря табличному методу переходов и состояний, вся долбаная процедура switch-case в кнопках заменена на две долбаные строчки :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:25:04 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 0
MLX90640, "небрежно" и "топорно" - это былокод. И это сплошь и рядом.( Ну ладно, если ты пишешь для себя, но если ты показываешь людям, неужто нельзя привести к удобочитаемому виду, дабы не позориться? Что бы это было понятно не только тебе самому... Это я не про вас, это я обобщённо.)
Касательно графов - ну сложно это для начинающих, это уж больше для серьёзных людей, для профи, типа, Demiurg. ) Куда уж нам то...)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:30:42 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Давай без эпитетов. Посмотри на последние сообщения, пока тебя не было. Предложены разные примеры. Никто никого не цепляет, не задевает. Мы можем высказать свое мнение. Зацепило, не зацепило. А ТС учится на этих примерах. Ему предлагается выбор.

Один из первых интерпретаторов таблиц я увидел в одном из первых примеров. В 2007 или 8 году. Притом я начал изучать AVR, а пример был для пиков. На асме. И с тех пор я сделал много табличных интерпретаторов. Как асм так и си.

Многие здесь присутствующие тоже знают, что такое табличные методы. Прикинь?

Щас пороюсь, найду один из примеров, один коллега скидывал...


Последний раз редактировалось Demiurg Пн окт 10, 2022 17:39:46, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:39:16 
Опытный кот
Аватар пользователя

Карма: 2
Рейтинг сообщений: 164
Зарегистрирован: Ср авг 03, 2022 05:22:56
Сообщений: 848
Рейтинг сообщения: 0
Ну вот :) до этого написал по уму - сказали небрежно и запутанно. Щас написал примитивно и линейно - сказали быдлокод. :) вас, граждане, хер поймёшь - одному не нравится так, другом сяк. Хехе, тяжко жить на свете пионеру Пете.
Вобщем, быдло или не быдло, но оно работает и поставленные задачи выполняет прозрачно и ясно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:45:09 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Ты правила программирования озвучил, обвинил, что не соблюдаются правила. Твой код понимаешь только ты. И дело не в шаблонах, разрыве шаблонов. А в том, чтобы после тебя смогли прочитать код, понять его. У тебя это хромает. Ты не для нас пишешь. Мы и сами можем примеров накидать. Для новичков. Но, также мы смотрим. Чтобы перенять понравившиеся фишки.

Нашел. Один из примеров, на которых я учился. 2013 год.

Спойлер
Код:
//MLMESSAGE(   ChangePrice      ,   "==CHANGE PRICE=="   ,   "PREISE VER"AUML"NDERN"   ,   "=CAMBIO PRECIO=="   ,   "==CHANGER PRIX=="   ,   "==ИЗМЕНИТЬ ЦЕНЫ="   )   //0
//MLMESSAGE(   Configuration   ,   "=CONFIGURATION=="   ,   "=KONFIGURATION=="      ,   ""               ,   ""               ,   "==КОНФИГУРАЦИЯ=="   )   //1
//MLMESSAGE(   Service         ,   "====SERVICE====="   ,   "====SERVICE====="      ,   "====SERVICIO===="   ,   "====SERVICE====="   ,   "=====СЕРВИС====="   )   //2
//MLMESSAGE(   ConfigCode      ,   "--Config.-code--"   ,   "--Konfig.-code--"      ,   "--Config.-code--"   ,   "--Config.-code--"   ,   "Код кофигурации"   )   //
MLMESSAGE(   Light         ,   "=====LIGHT======"   ,   ""                  ,   ""               ,   ""               ,   "===СВЕТ========"   )   //3
//MLMESSAGE(   SystemConfig   ,   "--System-config-"   ,   "-System-Konfig.-"      ,   "Config. sistema-"   ,   "config. Systфme-"   ,   "Система"         )   //4
//MLMESSAGE(   LineConfig      ,   "--Line-config---"    ,   "-Zeilen-Konfig.-"      ,   "Configurar lфnea"   ,   "-config. Ligne--"   ,   "Строки"          )   //5
//MLMESSAGE(   SignConfig      ,   "--Sign-config---"   ,   "Anzeigen-Konfig."      ,   "Configurar se al"   ,   "config.Afficheur"   ,   "Табло"            )   //6


В этих примерах X-macro применяется.

Лично у меня применяется что-то типа такого.
Спойлер
Код:
//==================
typedef enum _proc_device
{
#define STATE(name, func) name,
#include "_proc_device.h"
#undef STATE

PROC_DEVICE_STATES,
} proc_device_t;


//==================
__flash FUNC proc_device_func [PROC_DEVICE_STATES] =
{
#define STATE(name, func) func,
#include "_proc_device.h"
#undef STATE
};
//----------
static proc_device_t _proc_device;
static u08 _proc_device_slave;
//----------
void proc_device (void)
{
//   proc_meter (); // Важно!!! Инициализация!

   proc_fsm_func (proc_device_func, _proc_device);
}
//==================

//************************************************************************
//************************ Главный автомат *******************************
//************************************************************************

//==================
STATE (PROC_DEVICE_INIT,             proc_device_init)
STATE (PROC_DEVICE_WEIGHT_MODE,      proc_device_weight_mode)
STATE (PROC_DEVICE_DOSER_IDLE_MODE,  proc_device_doser_idle_mode)
STATE (PROC_DEVICE_DOSER_MODE,       proc_device_doser_mode)
STATE (PROC_DEVICE_IDLE,             proc_device_idle)
STATE (PROC_DEVICE_EMERG_MODE,       proc_device_emerg_mode)
//==================


Update


Последний раз редактировалось Demiurg Пн окт 10, 2022 17:03:54, всего редактировалось 2 раз(а).

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Как поместить цикл в case оператора switch
СообщениеДобавлено: Пн окт 10, 2022 16:57:17 
Сверлит текстолит когтями

Карма: 12
Рейтинг сообщений: 124
Зарегистрирован: Вт июн 07, 2011 08:03:18
Сообщений: 1235
Рейтинг сообщения: 0
Ну вот :) до этого написал по уму - сказали небрежно и запутанно. Щас написал примитивно и линейно - сказали быдлокод. :) вас, граждане, хер поймёшь - одному не нравится так, другом сяк. Хехе, тяжко жить на свете пионеру Пете.

"Вас Петровых не понять - ей нравиться, тебе нет...")
Не, не, не, это я не относительно вас. Я же пояснил (кажется).)
Речь о ком? Правильно, о начинающем. Так зачем ему, раньше времени, пудрить мозги? Пущай осилит что попроще, или нет? Считаю, всё должно быть для него максимально понятно.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 252 ]     ... , , , 7, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 435


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y