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

stm32, тест, непонятка с чтением состояния пина

Вс мар 13, 2022 18:51:22

добрый день

исходные данные:
stm32vldiscovery
STM32VL-Discovery-template
- No CubeX

набросал тест "помограть" с "кнопкой"
- синий св.диод моргает ~ 1Гц
- зеленый св.диод - меняет состояние по нажатию на кнопку

есть непонимание: код чтения пина кнопки "тормозит", точнее
- если код "чтения" заремить - то син.св.диод переключается "правильно", прим. 1Гц
- если код "включить", то син.св.диод переключается прим. в 2 раза медленнее

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

main.c
Спойлер
Код:
#include "stm32f10x.h"

#define TIMER_CNT 0xFFFFE

#define LED_B_SET (GPIO_SetBits  (GPIOC, GPIO_Pin_8))
#define LED_B_CLR (GPIO_ResetBits(GPIOC, GPIO_Pin_8))
#define LED_G_SET (GPIO_SetBits  (GPIOC, GPIO_Pin_9))
#define LED_G_CLR (GPIO_ResetBits(GPIOC, GPIO_Pin_9))

////////////////////////////////////////////////////////////////////////////////
void RCC_init()
////////////////////////////////////////////////////////////////////////////////
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // enable clocking on Port C
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
////////////////////////////////////////////////////////////////////////////////
void Setup(void)
////////////////////////////////////////////////////////////////////////////////
{
GPIO_InitTypeDef GPIOC_init_params;

RCC_init();

/*
http://we.easyelectronics.ru/STM32/rukovodstvo-k-bystromu-startu-po-rabote-s-periferiey-stm32f10x.html

stm32lib/inc/stm32f10x_gpio.h

GPIO_Mode_AIN         — аналоговый вход;
GPIO_Mode_IN_FLOATING — вход без подтяжки, болтающийся (англ. float) в воздухе
GPIO_Mode_IPD         — вход с подтяжкой к земле   (англ. Pull-down)
GPIO_Mode_IPU         — вход с подтяжкой к питанию (англ. Pull-up)
GPIO_Mode_Out_OD      — выход с открытым стоком    (англ. Open Drain)
GPIO_Mode_Out_PP      — выход двумя состояниями    (англ. Push-Pull — туда-сюда)
GPIO_Mode_AF_OD       — выход с открытым стоком для альтернативных функций (англ. Alternate Function). Используется в случаях, когда выводом должна управлять периферия, прикрепленная к данному разряду порта (например, вывод Tx USART и т.п.)
GPIO_Mode_AF_PP       — то же самое, но с двумя состояниями
*/

//
// 2 LED pin's
//
GPIOC_init_params.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // Blue LED PC[8], Green LED PC[9]
GPIOC_init_params.GPIO_Speed = GPIO_Speed_10MHz;
GPIOC_init_params.GPIO_Mode  = GPIO_Mode_Out_PP;  // Push-pull output
GPIO_Init        (GPIOC, &GPIOC_init_params);

//
// Button
//
GPIOC_init_params.GPIO_Pin   = GPIO_Pin_0;        // user button PA0
GPIOC_init_params.GPIO_Speed = GPIO_Speed_10MHz;  // 10-50 по барабану
GPIOC_init_params.GPIO_Mode  = GPIO_Mode_IPD;     // GPIO_Mode_IPD - PD connect GND
GPIO_Init        (GPIOA, &GPIOC_init_params);     //
}
////////////////////////////////////////////////////////////////////////////////
int main(void)
////////////////////////////////////////////////////////////////////////////////
{
int cnt = TIMER_CNT;
int flag_time = 0;
int flag_btn  = 0;

while(1)
  {
  if(!cnt--)
    {
    flag_time = 1;
    cnt       = TIMER_CNT;
    }

  if(flag_time)
    {
    flag_time = 0;

    if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8))    { LED_B_CLR; } // invert Blue Led
    else                                            { LED_B_SET; }

    if(flag_btn)
      {
      flag_btn = 0;

      if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_9))  { LED_G_CLR; } // invert Green Led
      else                                          { LED_G_SET; }
      }   // if(flag_btn)
    }     // if(flag_time)

  //
  // читаем пин-кнопку
  //
  if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
    {
    flag_btn = 1;
    } //*/
  }     // while()
}
////////////////////////////////////////////////////////////////////////////////

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 06:39:58

Так.... окей. Я понимаю, что это тест, но...
Попробуйте иначе.
Код:
#define TIMER_CNT 0xFFFFE / 100


<...>
int main (void) {
   int loop_10ms = 0;
   int flag_time = 0;
   int flag_btn  = 0;
   int is_button_pressed = 0;   // Добавочный флаг, позволяющий создать из переменной flag_btn триггер
   
<...>

   // Тикает 100 раз в секунду
   while (1) {
      if (!(cnt--)) {
         cnt = TIMER_CNT;
         loop_10ms++;
         // Читаем состояние пина.
         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) {
            // Если высокое И ЕСЛИ добавочный флаг НЕ взведён,
            if (!is_button_pressed) {
               // Взводим оба флага - добавочный и сам триггер.
               is_button_pressed = 1;
               flag_btn = 1;
            };
         } else {
            // Если кнопка отпущена И ЕСЛИ был взведён дополнительный флаг
            if (is_button_pressed) {
               // Сбрасываем его. flag_btn не изменяется, потому что он уже в состоянии "0" из-за кода ниже.
               is_button_pressed = 0;
            };
         };
      };
      if (loop_10ms >= 100) {
         // 1 секунда
         loop_10ms = 0;
         flag_time = 1;   // Тикнула секунда
      };
   };
   
   
   
   if (flag_time) {
      flag_time = 0;   // Сбрасываем флаг
      if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8))    { LED_B_CLR; } // invert Blue Led
      else                                            { LED_B_SET; }
   };
   if (flag_btn) {
      flag_btn = 0;
      if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_9))  { LED_G_CLR; } // invert Green Led
      else                                          { LED_G_SET; }
   };
};


Собственно, что я сделал.
Опрос кнопки производится в одном месте, совместно с часто работающим таймером (каждые 10 мс). Таким образом основной цикл, в отличии от кода в Вашем примере, срабатывает чаще. Кстати, в *HDL логике подобный код опроса работал бы, ибо там всё максимально параллельно из-за того, что это аппаратная логика. Но вернёмся к коду.
Так как основной цикл крутится уже 100 раз в секунду, требуются дополнительные счётчики, которые будут делить его тики на более редкие. В частности, секундный флаг вызывается каждые 100 итераций (не могу достоверно сказать что прямо так точно, но счётчкики на переменных имеют место быть).
При этом, пока флаг секунды не взведён - код, проверяющий этот флаг ниже, не заходит в ветку мигания зелёным диодом.
Опрос кнопки так же работает чаще и взводит уже два флага. Первый - для себя, второй - для кода после.
Если не использовать два флага, то флаг "кнопка нажата" будет постоянно выставляться в каждом цикле (100 раз в секунду!) и диод будет так же часто менять своё состояние. Второй флаг - позволяет дождаться перехода логического состояния "1 -> 0" и только после этого позволит поднять флаг кнопки вновь.
Как бы, всё.

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 07:28:00

sunjob, так программировать нельзя. Две примитивных задачи и такая гора переменных, флагов, условий... Что будет если задачи будут реальными?

Как-то так.
Код:
 
volatile bool flag_1Hz=false;

int main()
{
  for(;;)
  {
    if(key.pressed())
     green_led.toggle();

    if(flag_1Hz)
    {
      blue_led.toggle();
      flag_1Hz=false;
    }
  }
}
Всё остальное поведение спрятано в прерывании таймера и методах (функциях, если без плюсов) объектов кнопок и диодов. Иначе 99% времени будете проводить над вопросом "чего это оно работает не так как я хочу".

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 14:33:55

Так.... окей. Я понимаю, что это тест, но...
Попробуйте иначе.

а вы мой кот точно смотрели?! :))
пишу с патифона, ваш код еще не щюпал, но по описанию - все тоже самое :о) и что сразу бросается в глаза
> основной цикл крутится уже 100 раз в секунду
надеюсь, понятно о чем?!

Добавлено after 1 minute 26 seconds:
sunjob, так программировать нельзя. Две примитивных задачи и такая гора переменных, флагов, условий... Что будет если задачи будут реальными?

... то и переменные и флаги будут тоже реальными 8)

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 17:10:08

... то и переменные и флаги будут тоже реальными 8)
А их количество и влияние друг на друга неописуенным?

Добавлено after 1 hour 37 minutes 14 seconds:
- если код "включить", то син.св.диод переключается прим. в 2 раза медленнее
А чего в этом удивительного? Вы же считаете количество циклов. Цикл длиннее - выполняется дольше.

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 17:35:54

> А чего в этом удивительного?
т.е. вас не смущает что "оператор" чтения пина "тормозит" практически пустой while в 2 раза, что реально отражается на прим 100% задержке по сравнению с "пустым циклом задержки"?!

оч. давно, когда разбирался с "avr-мандариной" и работой с портами, набросал примерно такой-же код... и, на ск. я помню, таких проблем не было (если память не изменяет, давно было)

ладушки, доберусь до большой машинки, посмотрим что там да чаво :)))

зы
>А их количество и влияние друг на друга неописуенным?
если вы про "флаги" то это надо быть безмозглым старым пердуно-котом, что-бы запутаться в структурах-флагов и в том, кто их поднимает а кто их обробатывает и сбрасывает :kill:

Re: stm32, тест, непонятка с чтением состояния пина

Пн мар 14, 2022 17:41:55

Не смущает. Все флаги и счётчик легли в регистры процессора. Работать с ними легко и быстро. А пин надо вычитать из порта GPIO и наложить маску. Вполне соизмеримо по времени.

Или, например, счётчик перестал помещаться в регистрах и переехал в стек и доступ к нему стал сильно дольше.

Смотрите листинг - там все ответы.

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 04:15:50

т.е. "мандарина" в данном случае рулит! :о)

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 04:51:46

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

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 06:24:58

а вы мой кот точно смотрели?! :))
пишу с патифона, ваш код еще не щюпал, но по описанию - все тоже самое :о) и что сразу бросается в глаза


У вас основной цикл работает так (псевдокод):
while (1) {
ЗАДЕРЖКА(0xFFFFE); - Калькулятор говорит, что это около 1 миллиона циклов декремента - проверки - повтора. Грубо говоря, ПАУЗА в 1с.
Если (Флаг_ВРЕМЯ) то <...>
Если (ПИН==1) то <...>
};

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

Мой код:
while (1) {
ЗАДЕРЖКА (10мс);
Счётчик_МС ++;
Если (Счётчик_МС >= 100) то { Счётчик_МС = 0, Флаг_ВРЕМЯ = 1 };
Если (ПИН == 1) то {ФЛАГ_ПИН = 1, ФЛАГ_Триггер = 1};


Если (Флаг_ПИН == 1) то {Флаг_ПИН = 0, Пин = НЕ пин};
Если (Флаг_ВРЕМЯ == 1) то { Флаг_ВРЕМЯ = 0, ДИОД = НЕ ДИОД};
};

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

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 08:17:57

AlanDrakes, вы неправильно поняли как там задержка работает. Он считает количество полных циклов, длительность которых зависит от фазы луны. В этом и проблема.

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 08:35:08

> нажатие на кнопку обрабатываться только 1 раз в секунду.
уточнение - переключение св.д от нажатия !!! синхронизируется !!! с морганием 1го св.диода, т.е. это так и задумано :о)

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 16:34:42

AlanDrakes, вы неправильно поняли как там задержка работает. Он считает количество полных циклов, длительность которых зависит от фазы луны. В этом и проблема.


Оу щи~
Действительно. Тогда я что-то не могу найти в коде примера задержку. =]

sunjob писал(а):уточнение - переключение св.д от нажатия !!! синхронизируется !!! с морганием 1го св.диода, т.е. это так и задумано :о)

Тогда опишите логику более подробно, ибо теперь стало ещё менее понятно, чего вы хотите добиться.
Можете нарисовать диаграмму состояний.

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 19:38:47

да в коде все-же понятно :о)
это был тестовый код, хотел проверить "отладочную" плату, набросал тест, залил и... обнаружил что "чтение" пина занимает "львинную" долю...
хотя, до этого, (давно - давно) подобные тестовые скетчи делал в авр-ках, ПРОБЛЕМ НЕ БЫЛО ЗАМЕЧЕНО (ну давно было, не помню тонкости, но вроде как ни чего не "сквозило") :о)

ну вот, поэтому решил у знатоков поинтересоваться

если надо, то, конечно, обьясню "логику мыслей"... но, вроде и так все понятно...
просто с патифона не очень удобно шкрябать когТями... а до большого компа пока не добрался, не успеваю :о)

спасибо, парни, за помидоры :о) но все равно не понятно, как так?!

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 19:50:17

Код:
  if(!cnt--) {flag_time=1; cnt=TIMER_CNT;}

  if(flag_time)
    {
      flag_time = 0;
     if(Read8) {LED_B_CLR;}else{LED_B_SET;}
     if(flag_btn)
      {
        flag_btn = 0;
         if(Read9) {LED_G_CLR;}else{ LED_G_SET;}
      }
   }
  if(Read0) {flag_btn = 1;}

сократил текст просто для наглядности.
но большие задержки методом cnt-- это как отмерять периоды в несколько месяцев посредством распилки н-ного количества бревен, типа если нужно отмерить 32,25 месяца, значит нужно не останавливаясь распилить 3млн. бревен.
для stm32 такой подход - дичь, ведь достаточно просто включить таймер.
а по вопросу - как было сказано - надо смотреть листинг.

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 19:57:11

но все равно не понятно, как так?!
Архитектура. Листинги смотри, там всё видно.

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 20:14:43

> Read9
это макрос?

Re: stm32, тест, непонятка с чтением состояния пина

Вт мар 15, 2022 20:17:47

не не
это Ваш текст
я только буковки потер - чтоб логику было видно, и только

Re: stm32, тест, непонятка с чтением состояния пина

Ср мар 16, 2022 06:30:14

> Архитектура. Листинги смотри, там всё видно.
лааап моих бы не было-бы на форуме, если бы чего... :о)
а то я так тоже могу, бороду отрастить, очки напялить потолще (у хозяина стащить еще и трубку)... и умные слова глаголить налево направо :о)

спасибо за умные роковождения :о) надеюсь без обид?! :о)
было бы лучше, все таки более развернутый ответ, типа ...опа, а у нас тут мыши...

мур...

Re: stm32, тест, непонятка с чтением состояния пина

Ср мар 16, 2022 07:02:01

чтение ножки, наверняка, не причем.
более вероятно - в одном случае cnt ячейка памяти, в другом регистр.
вот cnt-- и дает существенно разные тайминги
Владислав об этом писал.
только чего гадать-то, если можно все увидеть в листинге.

так, порулил я на работу.
Ответить