STM32Cube. Использование портов ввода-вывода (GPIO).

Поскольку инструмент под названием STM32Cube становится все более популярным и интерес к нему постоянно возрастает, на нашем сайте в ближайшее время появится цикл небольших статей, посвященных настройке разных периферийных модулей при помощи Cube. И начнем мы с самого простого — а именно с портов ввода-вывода, так же известных как GPIO 😉

Обязательно просмотрите первую статью про Cubeвот.

STM32 Cube

Я буду использовать отладочную плату STM32F4-Discovery, ну и, соответственно, все проекты будут под STM32F4. В качестве среды разработки — IAR 6.70. Но на самом деле существенной разницы в использовании Cube при работе с STM32F4 или, например, STM32F1 нет )

Итак, сегодня у нас цель запустить GPIO при помощи кода, сгенерированного STM32Cube, поэтому поставим себе какую-нибудь простенькую задачу. На STM32F4-Discovery  у нас есть одна пользовательская кнопка и четыре светодиода. Давайте при нажатой кнопке будем зажигать зеленый и синий диоды, а при не нажатой — красный и оранжевый. К выводам микроконтроллера подключено все следующим образом:

STM32 Gpio

Таким образом, нам необходимо настроить выводы PD12, PD13, PD14 и PD15 на работу в режиме выхода, а PA0 надо настроить как вход. Так и сделаем!

Настройка портов в STM32Cube

Пока ничего сложного =) Идем в Project->Settings и там сохраняем настройки проекта, а именно его название, путь для сохранения сгенерированных файлов, а также выбираем IDE, для которой необходимо создать файлы проекта. В моем случае это IAR 6.70:

STM32Cube Settings

На этом подготовительный этап заканчивается и мы можем переходить к генерации кода. И этот этап также очень прост — Project->Generate Code 😉

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

Проект Cube

Проект успешно собрался!

Таким образом, Cube не просто сгенерировал код, также был создан проект, в котором в настройках уже прописаны все пути ко всем нужный файлам. Более того — Cube даже позаботился о том, чтобы в настройках проекта указать, что в качестве программатора и отладчика будет использоваться ST-Link 😉

Единственное, что в данном случае не может сделать STM32Cube — это за нас решить нашу задачу с мигающими диодами ) Поэтому сейчас мы добавим пару строк кода в файл main.c и проверим наш проект на практике.

Как вы помните, Cube не использует библиотеку SPL, ее место занял HAL_Driver, поэтому функции будут отличаться от тех, которые мы привыкли использовать в проектах с SPL (но отличия там незначительные =) ):

int main(void)
{
 
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration----------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
 
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* USER CODE BEGIN 3 */
  /* Infinite loop */
  while (1)
  {
    uint8_t currentButtonState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
 
    if (currentButtonState == 0)
    {
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
    }
    else
    {
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
    }
  }
  /* USER CODE END 3 */
 
}

Прошиваем программу в микроконтроллер и видим, что все работает именно так как и должно работать) В принципе в такой простой задаче не особо видны преимущества использования такого мощного инструмента как STM32Cube, но нашей целью было, в первую очередь, сделать пример для работы с GPIO, и с этой задачей мы справились на все 100 процентов! Так что на сегодня на этом все, скоро продолжим экспериментировать с Cube )

Понравилась статья? Поделись с друзьями!

STM32Cube. Использование портов ввода-вывода (GPIO).: 18 комментариев
  1. Добрый день, спасибо за уроки! Раньше Вы использовали Кеил, сейчас ИАР. С чем это связанно? Возможно Вы считаете, надо уметь работать во всех средах?

    • Просто с несколькими проектами работал в IAR и в процессе работы сам привык к этой среде. Сейчас иногда Keil, иногда IAR использую. А так по сути своей с точки зрения интерфейса все среды одинаковые.

  2. Понятно, мне тоже думается, что среда не самое главное. Есть ли у Вас опыт подключения stm32 к андроид устройству, типа io ? Странно то, что как бы эта тема мало кому интересна, практически нет информации.

    • Я пока не буду вперед забегать, но очень скоро (в пределах месяца-двух скорее всего) эта тема будет очень активно обсуждаться на сайте ) Физически будет соединение по Bluetooth 4.0, программно — для микроконтроллеров точно будут примеры.

  3. То что нужно. Вообще очень интересны вопросы коммуникации discoveryf4 с внешним миром (тот же Bluetooth, wifi, usb-android и т.д.). Тот же андроид, в принципе не так и сложно сделать программу там, а вот управлять stm-мом из нее — было бы круто. Так что — ждем.

  4. Добрый день. Что может быть, сгенерированый cubeMX проект(keil 5) шьется в чип, а дальше чип виснет(st-link не видит его ). Пробывал на f100 VL discovery и 103с8. Код на основе SPL работает нормально.

    • У STM32CubeMX есть прикол при создании проекта для серии STM32F1 — от отрубает по умолчанию интерфейсы отладки JTAG и SWD. В итоге, генерируешь проект, шьешь из под Keil uVision 5, первый раз прошиваешь, а дальше не шьется.

      ==== Избежание проблемы ====

      Чтобы избежать этой проблемы, при создании проекта в STM32CubeMX нужно сделать следующее: Вкладка Pinout ⇒ Configuration ⇒ Peripherals ⇒ SYS ⇒ Debug ⇒ Из выпадающего списка выбрать подходящее значение (все кроме No Debug)

      ==== Ликвидация последствий ====

      Необходимо сделать очистку чипа (Erase Chip) через режим (Mode) Connect Under Reset (подключение при сбросе / соединение из-под ресета). Этот режим позволяет подключиться к микроконтроллеру до начала выполнения программы. Чтобы прошить микроконтроллер в данном режиме, нужно на вывод сброса микроконтроллера (NRST) подать низкий уровень (или соединить вывод с землей), запустить прошивку и сразу убрать низкий уровень с NRST.

      Это делается через любую внешнюю программу для прошивки программатором ST-LINK, например:
      1) STM32 ST-LINK utility (http://www.st.com/en/embedded-software/stsw-link004.html);
      2) ST Visual Programmer STM32 (http://www.st.com/en/development-tools/stvp-stm32.html);

      PS. Стандартные грабли, на которые все наступают, кто решает начать работать с STM32CubeMX.

  5. странно !?? После включения-выключения отладки во вкладке SYS все заработало нормально.

  6. Супер!!! на Кейл мю4 всё завелось с пол-оборота, года два-три назад всё было намного сложнее. Надеюсь будет много статей конкретно по Кубу — Дискавери4… спасибо за статью.

  7. Здравствуйте. Спасибо за Ваши статьи, очень интересно и познавательно. По использованию Cube возник вопрос. Пытаюсь задействовать freeRTOS сгенерированную с помощью Cube, при попытке создать задачу и запустить шедулер ничего не выходит, никаких действий задача не выполняет (зажечь светодиод в моем случае). Подскажите в чем может быть причина? Я так догадываюсь, что не туда в функции main вставляю код создания задачи и запуска шедулера и возможно саму задачу (функцию). Но без использования Cube таких проблем никогда невозникало.

    • Добрый день!

      Насколько я помню, там просто вызываются функции создания задач:
      xTaskCreate()

      А после создания задач запускается:
      vTaskStartScheduler();

  8. Добрый день. Спасибо за ваши уроки.
    С кнопкой у меня все работает. Теперь стоит задача организовать параллельную передачу данных (8 бит) с мелкосхемы АЦП на PORTB STM32. В HALе есть только прием с одного пина (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);), а как сделать чтение всего порта или половины порта. Подскажите пожалуйста, а то я уже запутался.

    • Добрый день!

      Можно последовательно читать функцией HAL_GPIO_ReadPin(), а потом уже обрабатывать побитно, либо напрямую через регистр (насколько я помню регистр GPIOA->IDR).

      • Спасибо большое. С регистром все работает. А побитно слишком муторно все биты паковать в байт. Придется регистром пользоваться, хотя хотелось бы функцией пользоваться, которой почему-то в HALе нет.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *