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

Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 09:00:46

Всем привет. На форуме натолкнулся на статью и в исходниках есть участок кода, который мне не понятен. В https://www.radiokot.ru/forum/viewtopic ... 120написал, но там нет ответа. Создам отдельную тему. Часы, три кнопки: больше, меньше, ок. Кнопки посажены на землю, верх подтянуть резисторами к Uпит. Обработка их была написана следующим образом на все три, кроме управляющих функций, они различаются соответсвенно:
Код:
void read_button(void) {

    static uint8_t count_read_button_ok=0;
    count_read_button_ok++;

    //---------- OK ----------
    static char button, button_old=1;

    button_old=button;
    button=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
    if (((button_old!=button)&&(button==0))) {
        delay_ms(5);
        button=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
        if (((button_old!=button)&&(button==0))) {
            delay_ms(5);
            button=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
            if (((button_old!=button)&&(button==0))) {
                delay_ms(5);
                button=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
                if (((button_old!=button)&&(button==0))) {
                    delay_ms(5);
                    button=GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
                    if (((button_old!=button)&&(button==0))) {

                        second_systick_ms=0;
                        button_second=0;

                        while (((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13)==0)&&(button_second<2))); // зачем это???
                                 
                        if (button_second<2) {
                            button_ok_press(); // управляющая функция.
                        }
                        else {
                            RTC_Counter = RTC_GetCounter();
                            RTC_GetDateTime(RTC_Counter, &RTC_DateTime);
                            RTC_DateTime.RTC_Seconds=0;
                            RTC_SetCounter(RTC_GetRTC_Counter(&RTC_DateTime));
                        }
                    }
                }
            }
        }
    }

Зачем такое количество чтений кнопки каждые 5 мс? Так же в коде не были проинициализированы порты, я добавил в main.
Код:
//PinB 13 - Ok, PinB  14 - Down, PinB  15 - Up
static void button_init(void){
   
   GPIO_InitTypeDef button_ok =
    {.GPIO_Pin = GPIO_Pin_13, .GPIO_Speed = GPIO_Speed_2MHz, .GPIO_Mode = GPIO_Mode_IPU};
    GPIO_InitTypeDef button_down =
    {.GPIO_Pin = GPIO_Pin_14, .GPIO_Speed = GPIO_Speed_2MHz, .GPIO_Mode = GPIO_Mode_IPU};
    GPIO_InitTypeDef button_up =
    {.GPIO_Pin = GPIO_Pin_15, .GPIO_Speed = GPIO_Speed_2MHz, .GPIO_Mode = GPIO_Mode_IPU};

    GPIO_Init(GPIOB, &button_up);
    GPIO_Init(GPIOB, &button_down);
    GPIO_Init(GPIOB, &button_ok);
}

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 09:18:38

Код:
delay_ms(5);

Дальше не читал. Выкинуть это говно в помойку и написать по-человечески!

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 09:23:35

Код:
delay_ms(5);

Дальше не читал. Выкинуть это говно в помойку

Я просто хочу понять, что это? Типо антидребезг ? =)) Несколько вложенностей с чтением через задержку.
и написать по-человечески!

Я не спец в этом типе МК, только разбираюсь. Что значит по-человечески? В таймере задержку организовать?

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 10:02:31

Ох, же-па, как говорят французы :) Задержки - они в принципе там не нужны. Можно считать весь порт за один раз:
port = GPIOB->IDR;
затем методом наложения маски определить, нажата ли кнопка:
if((port & (1 << BTN0_Pin) == 0) { /* кнопка нажата */ };
затем надо сравнить с предыдущим состоянием кнопки в статической переменной и если предыд.состояние было "не нажата", значит выставить флаг "есть нажатие кнопки".
Если в предыдущем сравнении выяснится, что сейчас кнопка не нажата, значит, сбросить предыдущее состояние в "не нажата".
Защита от дребезга выполняется либо установкой интервала считывания кнопок в диапазоне от 5 до 20 мс, либо введением интегрирующего счетчика, инкрементирующегося/декрементирующегося каждый цикл при определении нажатия/отпускания. Но доп.счетчик усложняет функцию и не всегда нужен.

То есть, в простейшем случае будет выглядеть вот так:
Код:
void ReadButtons(void)
{
   static uint16_t old = (1 << BTN0_Pin) | (1 << BTN1_Pin) | (1 << BTN2_Pin);
   uint16_t port = GPIOB->IDR; // однократное чтение порта

   if((port & (1 << BTN0_Pin) == 0) 
   {      /* если состояние кнопки = нажата */
       if((old & (1 << BTN0_Pin) != 0) 
       {  /* если предыдущ.сост.кнопки = не нажата*/
           btn0_flag = 1;        // выставить флаг события нажатой кнопки
           old &= ~(1 << BTN0_Pin); // и обновить предыдущ.состояние кнопки
        }   
   } else
  {  /* если кнопка не нажата, то просто обновить предыдущ.сост.кноп. */
      old |= 1 << BTN0_Pin;
   }

   /* повторить то же самое для BTN1 и BTN2 */

}

вышеприведенный код можно оптимизировать по записи или добавить плюшек, я привел просто для наглядности.

Типо антидребезг ?

Да, попытка сделать повторные чтения состояния кнопки. Хотя дребезг (генерация случайных импульсов) может проявляться до 1-2 мс после первого срабатывания, в зависимости от типа кнопки и её состояния.
И если по уму, то антидребезг надо делать не просто повторными считываниями, а именно интегрирующим счетчиком, фиксирующим степень стабильности логического уровня на входе. Потому что длительность и интервалы импульсов в дребезге - вещь случайная.

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 11:21:48

Jman, при чем здесь тип МК? Сам код написан убогим абдуринщиком, который в конечные автоматы вообще никак не умеет! И даже вместо цикла запилил копипасту. За такое руки отрывать и в жопу засовывать - чтобы видно было, откуда растут!!!11
Вот - пример простой функции опроса кнопок. Вызывать из суперлупа.

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 11:56:34

Ох, же-па, как говорят французы :)

Спасибо большое! Вот теперь вроде все понятно.

Добавлено after 4 minutes 24 seconds:
Jman, при чем здесь тип МК? Сам код написан убогим абдуринщиком, который в конечные автоматы вообще никак не умеет!


Я бы не стал так говорить, ибо каждый могет в силу своих знаний. Я типо тоже такой же по вашим словам ) Но я пытаюсь уловить суть и смысл. Лирика...
По делу. У вас hardware.c в репе реализован на CMSIS на сколько я понимаю?

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 12:10:36

У вас hardware.c в репе реализован на CMSIS, насколько я понимаю?

Конечно, я не пользуюсь калокубами всякими. Да и никакой разработчик, если ему, конечно, не пофиг на свое время, не будет ни этой, ни другой подобной дрянью пользоваться.
На CMSIS все прозрачно, никакого лишнего кода... Конечно, еще лучше было бы на С++ написать на шаблонах всю "подноготную", как некоторые форумчане, но у меня к С++ не очень-то отношение (хотя, конечно, намного лучше, чем к змеюке).

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 14:20:17

Тут в принципе то не важно, как написана хардварная часть. От нее нужно лишь один раз прочитать состояние входов всех распознаваемых кнопок. Дальше - чисто софтовая часть. Причем, сложность и объемность реализации зависит от того, какие события кнопок нужно распознавать - простое нажатие, нажатие с удержанием, отпускание, фильтрация случайных импульсов. Лишнего без нужды наворачивать не следует.
Ну и в самой ф-ции распознавания кнопок не следует выполнять код функционала кнопки, если это только не простой короткий функционал. Как правило, выставляется флаг события кнопки (и/или код события), а по этому флагу извне уже выполняются действия кнопок.
Функция считывания состояния кнопок вызывается с некоторой периодичностью по таймеру, с интервалом 5 - 20 мс. Такой интервал гарантирует в большинстве случаев уверенную и быструю реакцию кнопок.

А еще бывает вариант срабатывания кнопок по внешнему прерыванию по изменению уровня на входах, он используется в основном для вывода микроконтроллера из режима пониженного потребления. Для этого варианта нужно программное подавление дребезга контактов, особенно когда нет подавительных конденсаторов параллельно кнопкам.

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 19:53:20

зачем автор так делал? - оставим этот вопрос ему самому (может у него оплата от кол-ва строк кода) :)

ф. read_button, вероятно, вызывается раз в секунду;
если кнопка нажата - опрашивается еще 4раза через 5мс, если "отпустилась" игнорируется;
если еще нажата попадаем на цикл:
"while (((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13)==0)&&(button_second<2))); // зачем это???"

для выхода из этого цикла - два фактора:
п. button_second, вероятно наращивается в прерывании, когда станет больше 2 - спрыгнем с этого цикла - загрузятся парам. в RTC;
отпустят кнопку раньше - спрыгиваем с цикла - вызываем ф. button_ok_press().

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 21:05:03

Спасибо всем за ответы! У меня еще такой вопрос, у автора задержка реализована следующим образом:
Код:
void delay_ms(uint32_t ms)
{
    volatile uint32_t nCount;
    RCC_ClocksTypeDef RCC_Clocks;
    RCC_GetClocksFreq (&RCC_Clocks);
    nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms;
    for (; nCount!=0; nCount--);
}


Это по вашим словам лучше заменить, и сделать опрос кнопок в таймере. Подойдет для этого SysTick?
Код:
static void init_sys_counter(void) {
    system_counter_init(1000);
    counter = system_counter_ticks();
    SysTick_Config(SystemCoreClock / 1000);
}

volatile uint16_t button_delay;
volatile uint8_t flag = 0;

 void SysTick_Handler(void) {
   
    button_delay ++;

    if (button_delay >=20) {
        button_delay=0;
        flag = 1;
    }
}


И в основном коде типо оперировать флагом. Или опрос прям в SysTick делать, как в примере НовыйДень?
Код:
volatile uint16_t button_delay;

 void SysTick_Handler(void) {
   
    button_delay ++;

    if (button_delay >=20) {
       
        ReadButtons(void);
        button_delay=0;
    }
}

void ReadButtons(void)
{
   static uint16_t old = (1 << BTN0_Pin) | (1 << BTN1_Pin) | (1 << BTN2_Pin);
   uint16_t port = GPIOB->IDR; // однократное чтение порта

   if((port & (1 << BTN0_Pin) == 0)
   {      /* если состояние кнопки = нажата */
       if((old & (1 << BTN0_Pin) != 0)
       {  /* если предыдущ.сост.кнопки = не нажата*/
           btn0_flag = 1;        // выставить флаг события нажатой кнопки
           old &= ~(1 << BTN0_Pin); // и обновить предыдущ.состояние кнопки
        }   
   } else
  {  /* если кнопка не нажата, то просто обновить предыдущ.сост.кноп. */
      old |= 1 << BTN0_Pin;
   }

   /* повторить то же самое для BTN1 и BTN2 */

}


Я еще читая просторы инета, вижу применение задержек на основе DWT. Имеет место быть?

Re: Не могу понять код опроса кнопки STM32

Ср апр 20, 2022 22:13:44

Проще завести переменную Tms и в прерывании SysTick, происходящем каждую условную миллисекунду, его инкрементировать. А везде в своих КА сравнивать внутренние счетчики с этим, оттуда и плясать.
Я ж дал пример кода.
Задержки на основе DWT? А смысл? Разве что если нужно микросекунды — но это тоже дико много. Одно дело - поставить блокирующую задержку в инициализации, там и пару секунд пользователь подождать может, пока все железо проинициализируется. И совсем другое - в рантайме. За абдуринские блокирующие delay'и в рантайме надо бить по рукам. В большинстве случаев их можно элементарным конечным автоматом заменить, не блокируя всю программу.
А блокирующие задержки пусть ставят абдуринщики в своих хеллоуворлдах, где ничего, кроме опроса датчика и вывода данных на экран без динамической индикации, не делается. Если какой-то протокол требует от вас постоянных задержек, либо реализуйте его на таймерах с DMA, либо не пользуйтесь таким говнопротоколом!

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 05:51:52

Автор того "кода" очень любит писать много строчек :) на проф.жаргоне это зовется "индусский код" - когда нужно создать видимость чего-то архисложного и непонятнонавороченного.

Для опроса кнопок лучше делать неблокирующую задержку (которая не блокирует исполнение остального кода) на таймере. Да, SysTick подойдет для этого, можно делать так, как вы написали. Можно выставлять флаг, а потом в основном цикле проверять флаг, а можно и прямо из прерывания вызывать. Но в случае вызова из прерывания систика, опрос кнопок не должен занимать много времени, чтобы не сбить интервалы систика.
А можно и иначе - запустить любой аппаратный таймер типа TIM6, TIM2, TIM1, TIM15, настроив его сразу на нужный интервал счета, например на 10 мс, с генерацией прерывания по событию обновления (Update). И в прерывании вызывать функцию ReadButtons().
Все варианты допустимы, а какой применить - выбирается по конкретной ситуации. Попробовав их все, поймете их плюсы и минусы.

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

Касательно таймеров и задержек. На одном аппаратном таймере (SysTick или TIMx) можно сделать целый набор софтовых таймеров. Эти таймеры представлены в виде массива структур:
Код:
typedef struct{
   uint32_t delay;      ///< Интервал счета (в тиках)
   uint32_t cnt;      ///< Счетная переменная
   uint8_t mode: 1;   ///< Режим однократный/циклический
   uint8_t run: 1;      ///< Бит работы таймера
   uint8_t flag: 1;   ///< Флаг истечения интервала
}utim_t;

и объявлены в виде глобальной переменной
Код:
#define MAX_UTIMERS   5   ///< Максимальное число софтовых таймеров
volatile utim_t utimer[MAX_UTIMERS];


Функция, обеспечивающая счет таймеров выглядит так:
Код:
/** ----------
 * \brief      Счет таймеров.
 * \details      Функция может вызываться из прерывания аппаратного таймера.
 *             Производит декременты счетных переменных и выставляет флаги
 *             окончания счета.
 */
void UserTimer_Count(void)
{
   for(volatile uint8_t n = 0; n < MAX_UTIMERS; n++)
   {
      if(utimer[n].run)
      {
         if(utimer[n].cnt) utimer[n].cnt--;
         else
         {
            utimer[n].flag = 1;

            if(utimer[n].mode == UTIMER_CIRCMODE) utimer[n].cnt = utimer[n].delay;
            else utimer[n].run = 0;
         }
      }
   }
}

она вызывается из прерывания аппаратного таймера, например SysTick.

Для запуска и остановки счета таймера есть ф-ции
Код:
/** ----------
 * \brief      Запуск таймера.
 * \details      Задание значений, запуск
 * @param timer номер таймера
 * @param delay интервал счета в тиках
 * @param mode  режим (однократный/циклический)
 */
void UserTimer_Start(uint8_t timer, uint32_t delay, uint8_t mode)
{
   utimer[timer].cnt = delay - 1;
   utimer[timer].delay = delay - 1;
   utimer[timer].mode = mode;
   utimer[timer].run = 1;
}

/** ----------
 * \brief      Остановка таймера без сброса счетной переменной.
 * @param timer номер таймера
 */
void UserTimer_Stop(uint8_t timer)
{
   utimer[timer].run = 0;
}

Для проверки истечения времени таймера есть ф-ция
Код:
/** ----------
 * \brief Проверка истечения времени таймера.
 * \param timer - номер таймера
 * \return Да/Нет
 */
uint8_t UserTimer_Check(uint8_t timer)
{
   if(utimer[timer].flag)
   {
      utimer[timer].flag = 0;
      return 1;
   }else
      return 0;
}/

либо можно записывать этот участок напрямую по месту проверки, сэкономив немного тактов на вызове ф-ции.

Блокирующая задержка (то есть та, которая задерживает дальнейшее исполнение до истечения заданного интервала) записывается гораздо короче.
Эта функция, реализующая саму задержку в том месте, где вызывается эта ф-ция:
Код:
/**----------
 * \brief      Блокирующая задержка.
 * \details      Функция блокирующей задержки на заданный интервал времени
 *             в тиках.
 * \param   delay - начальное значение счета
 */
void BlockedDelay(volatile uint32_t delay)
{
   bltimer_cnt = delay;
   while(bltimer_cnt) { }
}

А вот эта ф-ция вызывается из прерывания аппаратного таймера, например систика:
Код:
/** ----------
 * \brief      Счет блокирующей задержки.
 * \details      Функция может вызываться из прерывания аппаратного таймера
 *             Производит декременты счетной переменной.
 */
void BlockedDelay_Count(void)
{
   if(bltimer_cnt) bltimer_cnt--;
}


Вот как бы вот так, касательно таймеров и задержек.

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 08:23:53

Jman, небольшой совет по оптимизации кода.
Код:
volatile uint16_t button_delay;
volatile uint8_t flag = 0;

 void SysTick_Handler(void) {
   
    button_delay ++;

    if (button_delay >=20) {
        button_delay=0;
        flag = 1;
    }
}
volatile, вообще говоря, не бесплатная опция. Для переменной button_delay это влечёт за собой два чтения из и две записи в память внутри прерывания. От части из них легко избавиться
Код:
volatile bool flag = false;

void SysTick_Handler(void)
{
  static uint32_t button_delay=0;
   
  if (++button_delay >=20)
  {
    button_delay=0;
    flag = true;
  }
}
Мелочь, но 4 * 1000 тактов в секунду экономите просто на ровном месте. А сколько ещё таких мест будет в программе.


Не говоря уже о том, что SysTick (или любой другой таймер) можно настроить на 10-20 мс и выкинуть вообще весь этот код.
Последний раз редактировалось VladislavS Чт апр 21, 2022 09:41:45, всего редактировалось 3 раз(а).

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 10:21:21

Вот как бы вот так, касательно таймеров и задержек.

Спасибо большое за ликбез и ваше время!!!

Добавлено after 1 hour 55 minutes 27 seconds:
Вот я выбрал таймер 4.
Код:
void timer_init() {
    /*---------- TIM4------------------*/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
  /* По умолчанию частота шины 24 МГц при использовании кварца 8 МГц */
    TIM4->PSC = 24000 - 1; /* Настройка делителя на 1000 "тиков" в секунду */
    TIM4->ARR = 20; /* Отработка прерывания раз в 20мс */
    TIM4->DIER |= TIM_DIER_UIE; /* Разрешения прерывание от таймера */
    TIM4->CR1 |= TIM_CR1_CEN; /* Запуск таймера */
    NVIC_EnableIRQ(TIM4_IRQn); /* Разрешение TIM4_IRQn прерывания */
}



В самом прерывании вызываю функцию.

Код:
 void TIM4_IRQHandler(){
 
  ReadButtons();
}

В мейне разрешил прерывания
__enable_irq();
NVIC_SetPriorityGrouping(0x3);

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 10:39:05

Перырвания немного не так разрешаются. По умолчанию, глобально предывания разрешены и не нужна строчка __enable_irq(), только если раньше специально не запрещали глобально прерывания.
Только включить конкретный ветор прерывания, отвечающий за таймер, через ф-цию NVIC_EnableIRQ(TIM4_IRQn).
Ф-ция NVIC_SetPriorityGrouping(0x3) - это группы приоритетов прерываний. И если уж идете по пути глобального разрешения прерываний после настройки, то настройку приоритетов нужно сделать ранее.

Вообще, по структуре построения программы, включать векторы прерываний желатетьно уже после инициализации всей периферии, перед переходм в нормальный рабочий режим. Потому как несвоевременный переход в прерывание во время подготовительных процедур может привести к нежелательным сбоям, когда еще не всё готово для работы.

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 10:59:26

Незачем опрос кнопок из прерывания делать! Если уж на то пошло, в прерывании выставляете флаг, а в суперлупе его проверяете. И если надо, вызываете опрос... Но таки лучше счетчики заводить, управляемые SysTick'ом - не придется гробить нормальный таймер на такую пустяковую задачу.

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 11:05:08

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

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 12:01:15

то почему бы и нет?

А смысл, если кнопку можно опросить даже миллисекунд позже? Всему свое место. В прерываниях нужно выполнять лишь критический код, который "не ждет".
Таймеров TIMx может быть с избытком

Мне, например, их вечно не хватает! Вот, последняя железка — контроллер шаговиков — не может больше трех осей, т.к. у STM32F072CBT6 слишком мало таймеров, а на каждый шаговик нужно два (один для генерирования STEP, второй - для работы с энкодером, т.е. нужны еще и не абы какие таймеры, а с ногами ШИМ/энкодер).
систик может использоваться для других задач и считать более быстро

systick - на то и systick, чтобы "системное время" отсчитывать. Если он тарахтит не миллисекунды, а, скажем, десяток микросекунд - какая разница? Можно не только инкрементировать системный счетчик, но и счетчик миллисекунд каждое сотое срабатывание.
прежде чем сесть за кодописательство, продумывают стратегию, распределяют ресурсы

Окончательно же ресурсы распределяются на стадии трассировки печатной платы. У меня такое неоднократно было. И в том же примере по ссылке выше, скажем, двигатели 0, 1 и 2 контролируются отнюдь не последовательно пронумерованными таймерами! Да и каналы АЦП, концевики и т.п. зачастую вразнобой размещены - потому что так было удобней разводить печатную плату (иначе пришлось бы вместо недорогой двухслойки заказывать дорогущую четырехслойку).

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 13:10:33

А смысл,

...он в том, что главный цикл может быть долгим, с неравномерным периодом. При задержке между нажатием кнопки и получением отклика более 50-70 мс получается эффект тормознутости.
И более того, есть варианты программ, работающих вообще только в прерываниях. Я же говорю - единого однозначно правильного варианта нет. Есть только подходящие и неподходящие варианты для конкретного случая. Можно пробовать и то, и другое, и третье. И тогда у программиста появится гибкость мышления, способность находить оптимальные варианты.
Предубеждение, что из прерывания нужно выходить как можно быстрее, невзирая ни на что - это наследие старых простейших систем с одним-двумя-тремя векторами прерываний, не позволяющие реализовывать функционал.

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

Re: Не могу понять код опроса кнопки STM32

Чт апр 21, 2022 15:00:28

При задержке между нажатием кнопки и получением отклика более 50-70 мс получается эффект тормознутости.

Это что ж такое нужно в суперлупе делать, чтобы он так медленно выполнялся? Налицо адово рукожопие!!!
Что до нехватки таймеров, то даже не знаю, во сколько обойдется STM32, у которого на борту будут одновременно работающие CAN и USB, при этом с хотя бы шестью таймерами с ШИМ-выходом (кроме движков еще хоть один ШИМ-канал нужен) и пятью таймерами с входом от энкодера... При этом еще могут понадобиться 1-2 таймера (кроме SysTick) для внутренних нужд + 1-2 канала ЦАП…
Ответить