Перейти к содержанию
    

STM32, CubeMX, HAL, GPIO_Input <-> GPIO_Output

21 минуту назад, x893 сказал:

Можно сделать

const GPIO_InitTypeDef init_mode_GPIOA = { ... };

и "скармливать" без всяких заполнений

HAL_GPIO_Init(GPIOA, (GPIO_InitTypeDef *) &init_mode_GPIOA);  

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

    GPIO_InitStruct.Alternate

и сложно будет вспомнить, в какое место его добавлять, если структуру инициализировать целиком.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

43 минуты назад, Xenia сказал:

Только так:


  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;  // GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

За чем это делать в runtime (собирать структуру по членам)? Чтобы больше потратить тактов CPU и увеличить размер кода? :wink:

Лучше создать структуру целиком в build-time в const-памяти.

 

10 минут назад, Xenia сказал:

и сложно будет вспомнить, в какое место его добавлять, если структуру инициализировать целиком.

Ничего не понял... :wacko2:  Что именно сложно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

51 минуту назад, jcxz сказал:

Ничего не понял... :wacko2:  Что именно сложно?

Сложно запомнить, в каком порядке следуют поля в этой структуре. Развернутое присваивание само служит подсказкой, а изменение порядка строк там  безвредно.

Тогда как в записи

const GPIO_InitTypeDef GPIO_InitStruct = {  GPIO_PIN_11|GPIO_PIN_9, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_LOW, GPIO_AF1_TIM1 };

не мудрено ошибиться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, Xenia сказал:

Сложно запомнить, в каком порядке следуют поля в этой структуре...

Все еще зависит от продвинутости редактора.

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

Тогда можно использовать код типа

const GPIO_InitTypeDef GPIO_InitStruct =
{
  .Pin  = GPIO_PIN_11 | GPIO_PIN_9,
  .Mode = GPIO_MODE_AF_PP,
  ...
};

:smile:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, Xenia сказал:

Сложно запомнить, в каком порядке следуют поля в этой структуре.

Arlleex уже ответил. Современные компиляторы это понимают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, Xenia said:

Сложно запомнить, в каком порядке следуют поля в этой структуре. Развернутое присваивание само служит подсказкой, а изменение порядка строк там  безвредно.

Тогда как в записи

const GPIO_InitTypeDef GPIO_InitStruct = {  GPIO_PIN_11|GPIO_PIN_9, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_LOW, GPIO_AF1_TIM1 };

не мудрено ошибиться.

Ошибиться при Copy/Paste сложно, но если сильно хочется, то можно.

Рецепт с посте выше написан.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем ответившим.
В особенности - гуру, не видящим себя вне роли поучающего. Это так возвышает в своих же глазах! :biggrin:
 

1 час назад, esaulenka сказал:

Ага. И мышкой же указывать, в какие именно моменты он должен это делать.

Я видел  такие штуки, очень прикольно. Для дошкольников. А те, кому работать надо, по-старинке пишут закат солнца вручную. Без мышки.

Зачем моменты указывать? Пин можно конфигурировать на вывод - один набор установок, на ввод - другой набор, на вывод/ввод - оба набора. Чего проще-то? Ведь альтернативные функции пинам задать мышкой можно. Или это так сложно, что только - ручной закат? 
 

2 часа назад, Xenia сказал:

Только так:


  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;  // GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

т.е. заполнить структуру GPIO_InitTypeDef (целиком!) и скормить ее функции

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

Спасибо, здесь всё в принципе понятно. Пока только пытаюсь с кубом разобраться, в какой степени он полезен или бесполезен. Ради пробы сконфигурировал пин на ввод, посмотрел, порождённый код, сконфигурировал пин на вывод, посмотрел код, слепил гибрид - получилось. Но, спрашивается, нельзя ли было в опциях для пина кроме In и Out добавить еще и In/Out? Ведь само напрашивается. 

 

2 часа назад, HardEgor сказал:

А что вы хотели, если там стремянка с мраморными ступенями :)

Куб это удобный инструмент предварительной конфигурации микроконтроллера и генерации соответствующего кода. Весь остальной функционал только ручками.

Если сконфигурировать можно только от сих до сих, а дальше - ручками, инструмент откровенно слабый, абы как.

В любом случае ответившим спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

58 минут назад, Arlleex сказал:

Тогда можно использовать код типа


const GPIO_InitTypeDef GPIO_InitStruct =
{
  .Pin  = GPIO_PIN_11 | GPIO_PIN_9,
  .Mode = GPIO_MODE_AF_PP,
  ...
};

 

Можно. Но стоит ли экономить на спичках, когда весь HAL в таком стиле написан?

Вы хоть смотрели на его исходники? А если да, то должны понимать, что черного кобеля не отмоешь добела :). На фоне того, как там написан код, экономия, которой вы предлагаете заняться, выглядит просто смешно, если не нелепо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 минут назад, Xenia сказал:

Вы хоть смотрели на его исходники?

Приходилось.

 

Тут привели вариант, который не сделает последствия такого кода хуже для железки.

Зачем способствовать ухудшению кода, итак построенного известным способом, если можно не в ущерб визуальной нагрузке сделать все то же самое максимально эффективно?

 

Впрочем, хозяин барин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

43 минуты назад, Arlleex сказал:

Тут привели вариант, который не сделает последствия такого кода хуже для железки.

Зачем способствовать ухудшению кода, итак построенного известным способом, если можно не в ущерб визуальной нагрузке сделать все то же самое максимально эффективно?

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

 

Главная проблема работы с HAL через CubeMX, как я ее вижу, состоит в том, что что свой код приходится пихать лишь в специально отведенные места (там, где в комментариях написано "USER CODE"). И если эти места оптимизировать так, как вы посоветовали, то в следующий раз CubeMX это место не узнает. Тогда как инициализация портов обычно погружена в файл stm32xxxx_hal_msp.c, где структуры инициализируется последовательным заполнением полей. Более того, структуры там намеренно не константные, а именно - заводится одна структура на всё про всё, заполняется и отправляется на инициализацию, потом она же заполняется по-иному, и отправляется на инициализацию другого пина и т.д.

 

Короче говоря, искусству программирования следует учить в другом месте и в другое время, а не морочить человеку голову, когда его волнует совершено другой вопрос - понять, как работать с HAL.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё просто - меняем состояние одного бита в одном регистре. В топку HAL

bitset(GPIOA->MODER,0); - выход
bitclr(GPIOA->MODER,0); - вход

 

Изменено пользователем piroman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 27.04.2020 в 12:09, kv_addr сказал:

Как это выполнить в установках соответствующих регистров, знаю.

И тут совет:

2 часа назад, piroman сказал:

Всё просто - меняем состояние одного бита в одном регистре. В топку HAL

С таким же успехом я могу сказать: в топку SPL и LL. Только регистры, только хардкор! Вот только вопрос был не про регистры/CMSIS/SPL/LL. Вопрос был про HAL.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 час назад, Darth Vader сказал:

Вот только вопрос был не про регистры/CMSIS/SPL/LL. Вопрос был про HAL. 

Тем не менее, HAL во всю использует LL-макросы внутри своего кода, не пытаясь их подменять своими. Поэтому вполне естественно использовать какие-то LL-макросы при программировании из-под HAL. Однако случаются и разночтения, когда LL- и HAL-функции имеют разные по формату параметры, но имеющие сходные названия и смысл, а потому смешивать оба эти жаргона следует с осторожностью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Xenia сказал:

Тем не менее, HAL во всю использует LL-макросы внутри своего кода, не пытаясь их подменять своими.

Я это знаю.

Но человек спрашивал, как ему сделать именно HALом, а не LL/SPL/CMSIS. И специально подчеркнул, что делать это на регистрах (CMSIS) он и сам умеет, советчики для этого ему не нужны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...