Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 12:54:08

[А чем писать код?

Не знаю, как кто, но я пишу руками. =]

И чем вас смущает эта строка.Нажимаю кнопку выставляется флаг.Когда выставляется флаг в обработчике прерываний по таймеру начинает счёт переменная.

Скорее всего компилятор должен жаловаться на логичнское И, между частью операндов в строке. И что он МОЖЕТ ошибиться, если нет скобок.
Жалоба на неоднозначную трактовку сравнений.

Покажите хоть пример.Кусочек кода моего .Так как нужно писать .

Хойку.
Извините, не сдержался.

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 13:15:57

ivan dimir, просто они тебе ни чего другого не могут предложить.
+2 страницы библиотека обработки кнопок
+6 страниц микроменю, это примерный подсчет
и в итоге >16 страниц "индусокода", в котором только автор может разобраться.

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

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 13:33:18

ivan dimir, просто они тебе ни чего другого не могут предложить.
+2 страницы библиотека обработки кнопок
+6 страниц микроменю, это примерный подсчет
и в итоге >16 страниц "индусокода", в котором только автор может разобраться.

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

Что такое конечный автомат? И как его создать.Обьясните нерусскому электрику.Принцып.Или алгоритм создания этого конечного автомата.Какой ?

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 13:44:55

Это не ко мне вопрос.
Я не постиг этот >16 страничный высоко интеллектуальный код.

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 13:47:56

ivan dimir, а слабо в гугле набить "finite state machine"?
Все очень просто: алгоритм разбивается на этапы, которые можно однозначно охарактеризовать конечным количеством состояний. Все, дальше ты в switch'е проверяешь текущее состояние и выполняешь в зависимости от него какие-то действия.
Например, работа с USB основана на конечном автомате, твои кнопки удобней будет конечным автоматом реализовать и т.д., и т.п.
Я ж тебе давал ссылку на обработку кнопок в конечном автомате:
Код:
switch(e){
                case EVT_NONE: // just pressed
                case EVT_RELEASE:
                    if((k->counter += d) > PRESSTHRESHOLD)
                        k->event = EVT_PRESS;
                break;
                case EVT_PRESS: // hold
                    if((k->counter += d)> HOLDTHRESHOLD)
                        k->event = EVT_HOLD;
                break;
                default:
                break;
            }

(правда, этот пример неудачный. Нельзя так делать. Надо сначала выставить состояние и лишь потом ждать нужное время; а здесь выходит, что событие нажатия система получит лишь через PRESSTHRESHOLD мс, а это около 30 и выше!)

Бывают автоматы иерархические: когда в каждом состоянии есть какие-то подсостояния.

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 17:03:09

AlanDrakes писал(а):или хотя бы обрабатывать кнопки в функции
Ни знаю в чем проблема, и не ужели для каких-то кнопок применять конечный автомат?
Спойлер
Код:
#include <stdbool.h>

bool flag_IDR5;
bool flag_IDR4;
bool flag_IDR8;

#define BTN_TIME   50

void ScanButtons(void) {
static uint8_t ButtonFilter[3] = {0};

   flag_IDR5=0; flag_IDR4=0; flag_IDR8=0;
   
 if (GPIOB->IDR & GPIO_IDR_IDR5) {
  // Отпущена, висит в воздухе, подтяжка к VCC
  if (ButtonFilter[0]) { ButtonFilter[0] = 0; }
 } else {
 // Нажата (притянуто к 0)
  if (ButtonFilter[0] == BTN_TIME) {
    ButtonFilter[0] = (BTN_TIME+1);
    flag_IDR5 = 1;
  } else if (ButtonFilter[0] < BTN_TIME) {
   ButtonFilter[0]++;
   }
 }
 
 if (GPIOB->IDR & GPIO_IDR_IDR4) {
  if (ButtonFilter[1]) { ButtonFilter[1] = 0; }
 } else {
  if (ButtonFilter[1] == BTN_TIME) {
    ButtonFilter[1] = (BTN_TIME+1);
    flag_IDR4 = 1;
  } else if (ButtonFilter[1] < BTN_TIME) {
   ButtonFilter[1]++;
   }
 }
 
 if (GPIOB->IDR & GPIO_IDR_IDR8) {
  if (ButtonFilter[2]) { ButtonFilter[2] = 0; }
 } else {
  if (ButtonFilter[2] == BTN_TIME) {
    ButtonFilter[2] = (BTN_TIME+1);
    flag_IDR8 = 1;
  } else if (ButtonFilter[2] < BTN_TIME) {
   ButtonFilter[2]++;
   }
 }
}


а в цикле что-то вроде
Код:
ScanButtons();

    switch (nastroyki.menu_btn) {
      case 0:
        break;
      case 1:
        if (flag_IDR4) {
            if (danie.a < 4095) danie.a++;
          }
       
        if (flag_IDR8) {
            if (danie.a) danie.a--;
        }
        break;

первые можно в макрос обернуть типа такого
Код:
#define BTN_TIME(port,pin,b_time,flag) do{ flag=0; if(port&(pin)) { if(b_time)b_time=0; } else { if(b_time == BTN_LOCK_TIME) { b_time = (BTN_LOCK_TIME+1);  flag=1; } else if(b_time<BTN_LOCK_TIME) b_time++; } }while(0)

void ScanButtons(void) {
static uint8_t ButtonFilter[3] = {0};
   
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR5, ButtonFilter[0], flag_IDR5);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR4, ButtonFilter[1], flag_IDR4);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR8, ButtonFilter[2], flag_IDR8);
   
}

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 20:12:04

AlanDrakes писал(а):или хотя бы обрабатывать кнопки в функции
Ни знаю в чем проблема, и не ужели для каких-то кнопок применять конечный автомат?
Спойлер
Код:
#include <stdbool.h>

bool flag_IDR5;
bool flag_IDR4;
bool flag_IDR8;

#define BTN_TIME   50

void ScanButtons(void) {
static uint8_t ButtonFilter[3] = {0};

   flag_IDR5=0; flag_IDR4=0; flag_IDR8=0;
   
 if (GPIOB->IDR & GPIO_IDR_IDR5) {
  // Отпущена, висит в воздухе, подтяжка к VCC
  if (ButtonFilter[0]) { ButtonFilter[0] = 0; }
 } else {
 // Нажата (притянуто к 0)
  if (ButtonFilter[0] == BTN_TIME) {
    ButtonFilter[0] = (BTN_TIME+1);
    flag_IDR5 = 1;
  } else if (ButtonFilter[0] < BTN_TIME) {
   ButtonFilter[0]++;
   }
 }
 
 if (GPIOB->IDR & GPIO_IDR_IDR4) {
  if (ButtonFilter[1]) { ButtonFilter[1] = 0; }
 } else {
  if (ButtonFilter[1] == BTN_TIME) {
    ButtonFilter[1] = (BTN_TIME+1);
    flag_IDR4 = 1;
  } else if (ButtonFilter[1] < BTN_TIME) {
   ButtonFilter[1]++;
   }
 }
 
 if (GPIOB->IDR & GPIO_IDR_IDR8) {
  if (ButtonFilter[2]) { ButtonFilter[2] = 0; }
 } else {
  if (ButtonFilter[2] == BTN_TIME) {
    ButtonFilter[2] = (BTN_TIME+1);
    flag_IDR8 = 1;
  } else if (ButtonFilter[2] < BTN_TIME) {
   ButtonFilter[2]++;
   }
 }
}


а в цикле что-то вроде
Код:
ScanButtons();

    switch (nastroyki.menu_btn) {
      case 0:
        break;
      case 1:
        if (flag_IDR4) {
            if (danie.a < 4095) danie.a++;
          }
       
        if (flag_IDR8) {
            if (danie.a) danie.a--;
        }
        break;

первые можно в макрос обернуть типа такого
Код:
#define BTN_TIME(port,pin,b_time,flag) do{ flag=0; if(port&(pin)) { if(b_time)b_time=0; } else { if(b_time == BTN_LOCK_TIME) { b_time = (BTN_LOCK_TIME+1);  flag=1; } else if(b_time<BTN_LOCK_TIME) b_time++; } }while(0)

void ScanButtons(void) {
static uint8_t ButtonFilter[3] = {0};
   
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR5, ButtonFilter[0], flag_IDR5);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR4, ButtonFilter[1], flag_IDR4);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR8, ButtonFilter[2], flag_IDR8);
   
}

Код увеличится.И нет простоты кода.Для меня это сильно заумно.Слишком много событий.И операции.

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 21:05:34

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

Один вопрос: за чем две совершенно одинаковых переменные?
Код:
nastroyki.menu_btn
nastroyki.menu_lcd
если их объединить, то код примет вид
Спойлер
Код:
  while (1) {
 
   ScanButtons();
   
    if (flag_IDR5) {
      if(++nastroyki.menu_btn > 4) nastroyki.menu_btn = 0;
    }
    switch (nastroyki.menu_btn) {
      case 0:
        LCD_SetPos(0, 0);
        LCD_String("Bobr_stm32");    
        break;
      case 1:
      if(flag_IDR4) if(danie.a < 4095) danie.a++;     
      if(flag_IDR8) if(danie.a) danie.a--;

        sprintf(nastroyki.buf, "a=%2d ", danie.a);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf);      
        break;
      case 2:
      if(flag_IDR4) if(danie.b < 4095) danie.b++;
      if(flag_IDR8) if(danie.b) danie.b--;
       
        sprintf(nastroyki.buf2, "b=%2d ", danie.b);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf2);      
        break;
      case 3:
      if(flag_IDR4) if(danie.c < 4095) danie.c++;
      if(flag_IDR8) if(danie.c) danie.c--;
       
        sprintf(nastroyki.buf4, "c=%2d ", danie.c);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf4);      
        break;
      case 4:
      if(flag_IDR4) if(danie.d < 1023) danie.d++;
      if(flag_IDR8) if(danie.d) danie.d--;

        sprintf(nastroyki.buf6, "d=%2d ", danie.d);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf6);      
        break;
      default:   break;
    }
   
  }
ScanButtons() можно объявить как inline функцию.

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 21:57:10

Ну так сравни объем одного и того же кода без КА и с ними!
Я уж молчу о простоте сопровождения кода. С КА воткнуть новое состояние намного проще, чем без оного!

Re: stm32 cubeide два инкремента не совместимы.

Ср янв 19, 2022 22:35:38

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

Один вопрос: за чем две совершенно одинаковых переменные?
Код:
nastroyki.menu_btn
nastroyki.menu_lcd
если их объединить, то код примет вид
Спойлер
Код:
  while (1) {
 
   ScanButtons();
   
    if (flag_IDR5) {
      if(++nastroyki.menu_btn > 4) nastroyki.menu_btn = 0;
    }
    switch (nastroyki.menu_btn) {
      case 0:
        LCD_SetPos(0, 0);
        LCD_String("Bobr_stm32");    
        break;
      case 1:
      if(flag_IDR4) if(danie.a < 4095) danie.a++;     
      if(flag_IDR8) if(danie.a) danie.a--;

        sprintf(nastroyki.buf, "a=%2d ", danie.a);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf);      
        break;
      case 2:
      if(flag_IDR4) if(danie.b < 4095) danie.b++;
      if(flag_IDR8) if(danie.b) danie.b--;
       
        sprintf(nastroyki.buf2, "b=%2d ", danie.b);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf2);      
        break;
      case 3:
      if(flag_IDR4) if(danie.c < 4095) danie.c++;
      if(flag_IDR8) if(danie.c) danie.c--;
       
        sprintf(nastroyki.buf4, "c=%2d ", danie.c);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf4);      
        break;
      case 4:
      if(flag_IDR4) if(danie.d < 1023) danie.d++;
      if(flag_IDR8) if(danie.d) danie.d--;

        sprintf(nastroyki.buf6, "d=%2d ", danie.d);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf6);      
        break;
      default:   break;
    }
   
  }
ScanButtons() можно объявить как inline функцию.

Может можно.Но по памяти в avr .Не совсем работает.С глюком.Но вижу что эклипсе др среда.Ей пофиг атомарные операции.Нужно попробывать ваш вариант.Спасибо.Я кстати подумал об этом.И у меня один маленький вопрос.В каких случаях нужно применять указатели ?

Добавлено after 9 minutes 12 seconds:
Хотя по мне две переменные. Бараны на лево.Козлы на право.Вот принцып.Код увеличился.Ну и структуры тоже код увеличили.Когда слишком много переменных .То структуры в помощь.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 05:44:06

Конечные автоматы очень удобны, быстры при разборе сложных условий, а ещё их очень просто и удобно рисовать. Заметьте, сначала рисуем автомат, а потом его кодируем. Учитесь рисовать и работать с КА, ибо это очень эффективный способ создания ПО! Заумь начинается, когда у вас при анализе получается 100500 if-then-else, а в самой глубине goto.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 07:37:07

AlanDrakes писал(а):или хотя бы обрабатывать кнопки в функции
Не знаю в чем проблема, и неужели для каких-то кнопок применять конечный автомат?
Спойлер<...>
первые можно в макрос обернуть типа такого
Код:
#define BTN_TIME(port,pin,b_time,flag) do{ flag=0; if(port&(pin)) { if(b_time)b_time=0; } else { if(b_time == BTN_LOCK_TIME) { b_time = (BTN_LOCK_TIME+1);  flag=1; } else if(b_time<BTN_LOCK_TIME) b_time++; } }while(0)

void ScanButtons(void) {
static uint8_t ButtonFilter[3] = {0};
   
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR5, ButtonFilter[0], flag_IDR5);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR4, ButtonFilter[1], flag_IDR4);
   BTN_TIME(GPIOB->IDR, GPIO_IDR_IDR8, ButtonFilter[2], flag_IDR8);
   
}


Макрос интересный, согласен. Хотя писать такие не люблю - компилятор любит их разворачивать в inline-функции, а мне привычнее немного иначе оформить код - обработка ввода, фильтры, вызов события.
Когда-то писал функции обработки меню для графического экрана, с курсором (не указателем мыши, а виртуальным, прыгающим по кнопкам) и в какой-то момент понял, что дошёл до копии классического же меню. А потом понадобилось сделать "активную" кнопку, которая ловит хуки событий. Вот там всё стало странным, но решилось небольшой модификацией примитивов обработчиков. Ладно, это другая тема уже.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 07:44:46

Eddy_Em писал(а):Ну так сравни объем одного и того же кода без КА и с ними!
я тебе даю свой рабочий проект, а ты из него делаешь КА, вот тогда и поговорим о размере кода.
Eddy_Em писал(а):С КА воткнуть новое состояние намного проще, чем без оного!
Код:
while (1) {
 
   ScanButtons();
   
   новое_состояние();
tonyk писал(а):Заметьте, сначала рисуем автомат, а потом его кодируем.
под каждую задачу вы будете рисовать свой автомат, а потом его кодировать.
Универсального ни чего нет, как с теми же микроменю.
tonyk писал(а):Учитесь рисовать и работать с КА, ибо это очень эффективный способ создания ПО!
Код:
   КА++
   switch (KA){
      case 0 : опрос_кнопок(); break;
      case 1 : действие(); break;
     case 2 : вывод_лсд(); break;
    
      default : КА=-1
   }
Код:
   while(1){   
   опрос_кнопок();
   действие();
   вывод_лсд();   
   }
Пока что не вижу ни какой эффективности
tonyk писал(а):когда у вас при анализе получается 100500 if-then-else, а в самой глубине goto.
пример в студию, с КА и без КА.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 08:07:13

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

Один вопрос: за чем две совершенно одинаковых переменные?
Код:
nastroyki.menu_btn
nastroyki.menu_lcd
если их объединить, то код примет вид
Спойлер
Код:
  while (1) {
 
   ScanButtons();
   
    if (flag_IDR5) {
      if(++nastroyki.menu_btn > 4) nastroyki.menu_btn = 0;
    }
    switch (nastroyki.menu_btn) {
      case 0:
        LCD_SetPos(0, 0);
        LCD_String("Bobr_stm32");    
        break;
      case 1:
      if(flag_IDR4) if(danie.a < 4095) danie.a++;     
      if(flag_IDR8) if(danie.a) danie.a--;

        sprintf(nastroyki.buf, "a=%2d ", danie.a);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf);      
        break;
      case 2:
      if(flag_IDR4) if(danie.b < 4095) danie.b++;
      if(flag_IDR8) if(danie.b) danie.b--;
       
        sprintf(nastroyki.buf2, "b=%2d ", danie.b);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf2);      
        break;
      case 3:
      if(flag_IDR4) if(danie.c < 4095) danie.c++;
      if(flag_IDR8) if(danie.c) danie.c--;
       
        sprintf(nastroyki.buf4, "c=%2d ", danie.c);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf4);      
        break;
      case 4:
      if(flag_IDR4) if(danie.d < 1023) danie.d++;
      if(flag_IDR8) if(danie.d) danie.d--;

        sprintf(nastroyki.buf6, "d=%2d ", danie.d);
        LCD_SetPos(0, 0);
        LCD_String(nastroyki.buf6);      
        break;
      default:   break;
    }
   
  }
ScanButtons() можно объявить как inline функцию.

Меня заинтересовал ваш код у вас флаги в качестве кнопок?И меня заинтерисовала функция ScanButtons()? Что это ? И с чем его едят.Код ваш похож на мой единственное что переход на ноль при ++ и переход с нуля на 1023 при --.И замедление показаний.Ну а так ваш код лучше.Правда я использовал число 4095 дискретность ацп.1023 у avr.Да и ещё при переключении меню сначала нажимаем кнопку я выставляю флаг потом при ожатии флаг сбрасываю и срабатывает меню.

Добавлено after 2 minutes 23 seconds:
[А чем писать код?

Не знаю, как кто, но я пишу руками. =]

И чем вас смущает эта строка.Нажимаю кнопку выставляется флаг.Когда выставляется флаг в обработчике прерываний по таймеру начинает счёт переменная.

Скорее всего компилятор должен жаловаться на логичнское И, между частью операндов в строке. И что он МОЖЕТ ошибиться, если нет скобок.
Жалоба на неоднозначную трактовку сравнений.

Покажите хоть пример.Кусочек кода моего .Так как нужно писать .

Хойку.
Извините, не сдержался.

Да код написан не правильно.Но работает.Исправлю.Спасибо за замечания.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 08:28:49

ivan dimir, код не мой, код опубликовал AlanDrakes в этой теме 2 сообщение, я просто взял и использовал.
ivan dimir писал(а):И меня заинтерисовала функция ScanButtons()?
AlanDrakes писал(а):или хотя бы обрабатывать кнопки в функции
что и требовалось.
ivan dimir писал(а):что переход на ноль при ++ и переход с нуля на 1023 при --
здесь мне не понятно было, а переспрашивать не стал, в качестве демонстрации.
ivan dimir писал(а):И замедление показаний.
опять не понятно, что значит замедление?
Код:
#define BTN_TIME   50
число 50 взято с потолка, в зависимости от тактовой частоты чипа это число будет меняться, это число больше определяет сколько надо времени держать нажатой кнопку до ее срабатывания, до установки флага.
Попробуйте поиграться от 5-250.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 11:48:50

Dimon456 написал:
Код:
  КА++
   switch (KA){
      case 0 : опрос_кнопок(); break;
      case 1 : действие(); break;
     case 2 : вывод_лсд(); break;
   
      default : КА=-1
   }

Вот сразу видно человека, который не понимает, что такое конечный автомат. Даже книжки не читал.

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 14:28:42

tonyk, я поторопился, надо было так
Код:
   KA = 0;
   while (1) {
     switch (KA) {
       case 0: инит_всего();   KA = 1; break;
       case 1: опрос_кнопок(); KA = 2; break;
       case 2: действие();     KA = 3; break;
       case 3: вывод_лсд();    KA = 1; break;
       default: в пиииии.....();
     }
   }

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 15:04:13

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

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 15:44:56

Eddy_Em, мне что, твои куски коды сюда начать выкладывать?
В любой момент времени мы можем прерваться и прочитать состояние KA и узнать в каком состоянии находится последовательный код.
В своем проекте я хотел использовать совт_таймер, как бы не из ваших КА
Спойлер
Код:
//==================
#ifndef SOFT_TIMERS_H

#define SOFT_TIMERS_H

#include "soft_timers.h"

#include "main.h"
#define SwTimerCount  8   //Количество программных таймеров

/*Режимы работы таймеров*/
typedef enum
   {
      SWTIMER_MODE_EMPTY,
      SWTIMER_MODE_WAIT_ON,
      SWTIMER_MODE_WAIT_OFF,
      SWTIMER_MODE_CYCLE,
      SWTIMER_MODE_SINGLE
} SwTimerMode;


/*Стурктура программного таймера*/
typedef struct
    {
      unsigned LocalCount:32;   //Переменная для отсчета таймера
       unsigned Count:24;      //Переменная для хранения задержки
       unsigned Mode:3;      //Режим работы
       unsigned On:1;         //Разрешиющий бит
       unsigned Reset:1;      //Сброс счета таймера без его выключения
       unsigned Off:1;         //Останавливающий бит
       unsigned Out:1;         //Выход таймера
       unsigned Status:1;      //Состояние таймера
}SW_TIMER;

#if (SwTimerCount>0)
volatile SW_TIMER TIM[SwTimerCount]; //Объявление софтовых таймеров
#endif


void SwTimerWork(volatile SW_TIMER* TIM, unsigned char Count);   //Сама функция для обработки таймеров
void OnSwTimer(volatile SW_TIMER* TIM, SwTimerMode Mode, unsigned int SwCount);   //Подготовливает выбранный из массива таймер
unsigned char GetStatusSwTimer(volatile SW_TIMER* TIM);   //Считывание статуса таймера

#endif
Спойлер
Код:

//==================
//---------- Пример использования ----------
// set_soft_timer (ST_LED_2_BLINK, 50, 50); // Установка таймера.
// if (handle_soft_timer (ST_LED_2_BLINK))  // Проверка таймера.
//==================

//==================
#include "soft_timers.h"
//==================

//Подпрограмма программных таймеров
void SwTimerWork(volatile SW_TIMER* TIM, unsigned char Count){
   unsigned short i=0;
      for (i=0; i<Count; i++){
         if (TIM->Mode==SWTIMER_MODE_EMPTY){
            TIM++;
            continue;
         }

         if (TIM->Mode==SWTIMER_MODE_WAIT_ON){ //Если таймер на задержку включения
            if (TIM->On){
               if (TIM->LocalCount>0) TIM->LocalCount--;
                  else {
                     TIM->Out=1;
                     TIM->Status=1;
                  }
            }
            else {
               TIM->Out=0;
               TIM->LocalCount=TIM->Count-1;
            }
         }
         if (TIM->Mode==SWTIMER_MODE_WAIT_OFF){ //Если таймер на задержку выключения
            if (TIM->On){
               TIM->Out=1;
               TIM->Status=1;
               TIM->LocalCount=TIM->Count-1;
            }
            else {
               if (TIM->LocalCount>0) TIM->LocalCount--;
                  else TIM->Out=0;
            }
         }
         if (TIM->Mode==SWTIMER_MODE_CYCLE){
            if (TIM->Off){
               if (TIM->On){
                  TIM->Off=0;
                  if (TIM->LocalCount>0) TIM->LocalCount--;
               }
            }
            else{
               if (TIM->LocalCount>0) {
                  TIM->LocalCount--;
                  TIM->Out=0;
               }
               else {
                  TIM->Out=1;
                  TIM->Status=1;
                  TIM->LocalCount=TIM->Count-1;
               }
            }
            if (TIM->Reset){
               TIM->LocalCount=TIM->Count-1;
               TIM->Out=0;
               TIM->Status=0;
            }
         }
         if (TIM->Mode==SWTIMER_MODE_SINGLE){
            if (TIM->Off){
               if (TIM->On){
                  TIM->Off=0;
                  if (TIM->LocalCount>0) TIM->LocalCount--;
               }
            }
            else{
               if (TIM->LocalCount>0) {
                  TIM->LocalCount--;
                  TIM->Out=0;
               }
               else {
                  TIM->Out=1;
                  TIM->Status=1;
                  TIM->LocalCount=TIM->Count-1;
                  TIM->Off=1;
                  TIM->On=0;
               }
            }
            if (TIM->Reset){
               TIM->LocalCount=TIM->Count-1;
               TIM->Out=0;
               TIM->Status=0;
            }
         }

         TIM++;
      }
}

void OnSwTimer(volatile  SW_TIMER* TIM, SwTimerMode Mode, unsigned int SwCount){
      TIM->Mode=Mode;
      if (SwCount){
         TIM->Count=SwCount;
         TIM->LocalCount=SwCount-1;
      }
      if (TIM->Mode==SWTIMER_MODE_CYCLE || TIM->Mode==SWTIMER_MODE_SINGLE){
         TIM->Off=1;
      }
}


unsigned char GetStatusSwTimer(volatile SW_TIMER* TIM){
   unsigned char status=0;
   if (TIM->Mode==SWTIMER_MODE_EMPTY) return -1;
   if (TIM->Status){
      TIM->Status=0;
      status=1;
   }
   else {
      status=0;
   }
   return status;
}
но из-за того что мне стало жалко лишние 300-400 байт флеша, обошелся такой конструкцией
Спойлер
Код:
volatile uint32_t currentMillis = 0;

void SysTick_Handler(void)
{ static uint8_t count=0;
   currentMillis++;
}


uint32_t millis (void)
{
   return currentMillis;
}
Код:
   if((millis() - previousMillis) > 500){
      previousMillis = millis();
      blink = !blink;
   }

   LCDI2C_setCursor (10,0);
   if (blink) LCDI2C_write(0x22); else LCDI2C_write(0x20);

   LCDI2C_setCursor (11, 0);
   sprintf (string_out,"%02dV",(uint8_t)table_u);
   LCDI2C_write_String (string_out);

   LCDI2C_setCursor (15,0);
   if (blink) LCDI2C_write(0x22); else LCDI2C_write(0x20);
Так что, будешь дербанить мой код?

Re: stm32 cubeide два инкремента не совместимы.

Чт янв 20, 2022 16:41:48

Dimon456, вот, ты как раз сделал то, о чем я ТСу уже давно пытаюсь вталдычить: SysTick нужно использовать для отсчета условного внутреннего времени. И в конечных автоматах для выставления длинных задержек именно его и использовать, а не как абдуринщики вызывать delay_ms(500)!
Скажем, надо тебе сделать переинициализацию дисплея в процессе работы. А там бывают приличные паузы. Ты процесс разбиваешь на несколько кусков. Как только нужна пауза, у тебя состояние, скажем, WAIT_FOR_SOMETH. В нем тупо проверяешь: если миллисекунды натикали достаточно, то переходишь в следующее состояние, если нет - остаешься в этом.

В общем, не понял ты вообще никак, что такое конечные автоматы и в чем их прелесть. А твой код "софтового таймера" - ад какой-то.
Ответить