В предыдущих частях мы разобрались как подготовить рабочую среду, и сделали для себя отладочную плату. Настало время применить эти знания, и сделать что-нибудь, что можно будет уже наконец то назвать программой.
Для начала изучения возьмём библиотеку HAL, которая позволит нам немного абстрагироваться от всяких регистров и инициализации периферии. Традиционно для начала изучения - поморгаем светодиодом и освоимся в рабочей среде.
Первым делом сгенерируем проект при помощи STM32CubeMX:
Поскольку у нас светодиоды подключены к ножкам PA0-PA3 МК, настраиваем ножки на выход. Для удобства можно им дать осмысленные имена, в нашем случае - LED1, LED2, LED3 и LED4.

Для того, что бы не сжечь светодиоды, не забываем последовательно с ними добавить резистор 100 Ом.
Важно не забывать включить отладку по Serial Wire, иначе МК залочится.
На этом подготовка проекта в CubeMX закончена, далее обычная процедура генерации кода, и импорт проекта в VS Code. Что подробно расписано в предыдущем занятии.
После импорта в обозревателе решений находим файл main.c

С данного файла начинается выполнение программы, а также в нём находится "главный" цикл.
Но прежде чем начать писать где угодно, если почитать комментарии, то можно заметить, что файл поделен на места, где CubeMX предлагает нам писать свой код. Если мы учтём данные рекомендации, то можно будет изменять настройки в CubeMX, и перегенерировать проект в любое время, без опасений потерять написанный код.
Таким образом все подготовительные действия закончены, и можно наконец поморгать светодиодом.
Для этого у нас есть 2 функции:
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
и
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
Как не трудно догадаться, первая - записывает в пин данные, вторая - просто переключает его с 0 на 1 и обратно. И обе эти функции ничего не возвращают.
Давайте посмотрим на аргументы данных функций:
GPIO_TypeDef *GPIOx - порт микроконтроллера.uint16_t GPIO_Pin - пин, или маска пинов микроконтроллераGPIO_PinState PinState - состояние пина
Мы знаем, для того чтобы зажечь светодиод, необходимо подать напряжение на анод. Говоря на языке микроконтроллера - необходимо записать в пин единицу.
Давайте наконец уже сделаем это - зажжём светодиод!
Для этого в блоке
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
напишем:
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
Данный блок расположен после инициализации всей периферии, но до начала бесконечного цикла. Всё что мы напишем в данном блоке будет выполнено 1 раз.
После чего получившуюся программу можно загрузить в микроконтроллер и убедиться, что светодиод, подключенный к пину A0, который мы назвали LED1, зажегся.
Если мы хотим чтобы светодиод попеременно загорался и гас необходимо:
во первых - переместить наш код в главный цикл,
во вторых - использовать задержку.
Давайте переместимся с кодом в блок
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
как мы видим, здесь имеется бесконечный цикл.
Напишем следующее:
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
и загрузим в МК. В результате у нас светодиод начал мигать, и это мигание с частотой в 1 герц.
Так мы познакомились с ещё одной функцией:
void HAL_Delay(uint32_t Delay)
у которой только 1 аргумент - uint32_t Delay - число миллисекунд, на которое необходимо приостановить выполнение программы.
И в заключение, давайте поморгаем всеми светодиодами по очереди, для этого изменим нашу программу....