STM32F4 — pinMode(), digitalRead() и digitalWrite()

Попробуем решить простую задачу на Arduino. Если кнопка нажата, то зажечь светодиод: если на цифровом пине 4 уровень сигнала соответствует логической единице, то на цифровом пине 5 установить нулевой уровень.

Arduino предоставляет нам готовые функции для чтения и установки уровней сигналов — функции digitalRead() и digitalWrite() соответственно.

Решение задачи выше будет иметь следующий вид

Попробуем решить такую задачу на STM32F4. Считывать сигнал будем с A0 (там кнопка висит), а отображать на D15 (там диод).

Одно из решений может быть таким:

Сразу видим ключевое отличие STM и Arduino — очень тонкая но громоздкая настройка портов.

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

Arduino STM32F4
GIF
GIF

Когда вы программируете Arduino, вы основной код размещаете в setup() и loop(). Мне эта идея не очень понравилась,  но тут, скорее всего это сделано для новичков, чтобы те меньше думали о том, как это работает и уделяли больше времени на разработку и программирование самих алгоритмов.

В Arduino обращение к пинам идет через его числовой номер или же через названия A0, A1…. . Давайте пропишем такие же константы для STM. Также необходимо прописать режимы работы (Input, Output и др.) и сами названия портов (A, B, C, D, E, H). Все это сделаем в файле vdefine.h

В языке «Си» из коробки отсутствует тип данных bool — когда я об этом узнал, то мягко говоря немного подофигел и хорошо посмеялся с этого языка. Но это не проблема,  в коде выше можно также заметить имитацию bool:

Используя этот фокус мы не заметим разницы при написании программ.

Теперь Давайте разобьем код решения задачи под STM, который мы написали в начале, на функции.

Это код начальной настройки контроллера — включение тактирования портов, если его не прописать, то мы не сможем управлять портами A и D. Это можно отнести к функции pinMode(), но мне кажется это не самая хорошая идея — вызов функции включения тактирования портов при установке режима работы конкретного пина. Лучше это дело вынести в отдельную функцию, например функцию v_init(), и запускать единожды в начале функции main(). В этом есть и минус, мы включим сразу все порты и всю остальную периферию, даже если не будем её использовать. Как правильней сделать, сказать не могу, за неимением опыта. Возможно в комментариях кто-то даст совет или поправит в репозитории. Итак, функция v_init().

Обратите внимания что необходимые для работы библиотеки я подключил в h файле.

Мы включили тактирование портов. Теперь займемся реализацией остальных функций. Все, что шло до цикла while, это настройка портов. Давайте вынесем это в функцию pinMode(). Для удобства использования будем передавать функции названия пина и режим работы, которые мы задефайнили в файле vdefine.h. Пример того, чего я хочу: pinMode(A0, Input). Но перед этим нам необходимо написать две вспомогательных функции. Первая должна по названию пина (A0, A1, D5, C3….) возвращать порт (A, B, C, D, E, H — мы их задефайнили) — это для удобства. Вторая — по названию пина возвращать значение понятное для функций заложенных в библиотеки stm — GPIO_Pin_xx. Напишем функцию v_getPort() и v_getPin(), которым будем отдавать название пина:

Теперь, наконец-то сам pinMode():

При режиме «Input» подключаем подтягивающий к «земле» резистор, чтобы убрать шум при отсутствии сигнала.

И последнее — digitalWrite(), digitalRead(). Тут все просто:

Теперь попробуем решить задачу включения диода по нажатию на кнопку с использованием новых фунций:

Все, готово!

В следующей статьи будет описана функция analogWrite().

В репозитории приведена библиотека VSTM, в которой большинство функций уже реализованы.

Статьи серии про STM:

  1. STM32F4 — Вводная статья. Библиотека VSTM
  2. STM32F4 — pinMode(), digitalRead() и digitalWrite()
  3. STM32F4 — analogWrite() — получение PWM/ШИМ сигнала

 

 


  • Ян Штундер

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

    И еще чуть не по теме:
    В стмках вообще не советую с нуля садится за cubeMX. Лучше все ручками прописывать. Да тяжело. Иногда не взлетают простые вещи. Уходит на это много времени. Но поверьте, это в будущем окупится,если, конечно, вы захотите этим и дальше заниматься.