четверг, 9 декабря 2021 г.

Мигалка на микроконтроллере stm32f103c8t6, языке си и библиотеке CMSIS

 Создание светодиодной мигалки на микроконтроллере является аналогом созданию "Hello World!" при написании первой программы выполняемой на компьютере при изучении какого нибудь нового языка программирования, библиотеки, фреймворка или чего то подобного. Т.к. это обычно самое простое устройство которое можно сделать а чтобы подключить дисплей к микроконтроллеру и вывести на нем "Hello World!" нужно уже неплохо разбираться в программировании данного микроконтроллера. Микроконтроллеры STM32 неплохо продуманны и весьма популярны поэтому уроков по их программированию в сети интернет очень много. Особенно много уроков по мигалкам т.к. это, по традиции, первое с чего следует начать. Тем не менее, это не повод отказаться от изучения данных микроконтроллеров и поделиться опытом с другими по тому что любой опыт может оказаться полезным. О том как установить и настроить среду разработки для STM32 а также о том как откомпилировать и загрузить программу в микроконтроллер есть отдельная статья -> https://electe.blogspot.com/2019/06/stm32.html. Однако не обязательно использовать именно такую среду разработки как в той статье т.к. со времени её создания появились более новые и такие же бесплатные как Coocox CoIDE среды, например STM32CubeIDE. Есть также платные среды вроде Keil, IAR и т.д. Также есть возможность адаптировать Arduino IDE для работы с STM32F103C8T6, использовать генератор кода для инициализации STM32CubeMX. Что даст более быстрый результат но меньшее понимание микроконтроллера и работы с ним. Помимо этого можно также выбрать более продуманный путь и не использовать IDE или написать свою IDE однако такой путь, в данном случае, будет весьма трудоемким и выбрав его есть риск "увязнуть" в подготовке и не начать программировать микроконтроллер никогда или не скоро. STM32CubeIDE и STM32CubeMX - это возможно лучшие варианты которые стоит использовать для постоянной работы с микроконтроллерами STM32. Однако Coocox CoIDE не изобилует большим количеством открытых окон (от которых рябит в глазах) после запуска и имеет системные требования подходящие для не крутых компьютеров а также про его установку уже есть статья. Также для лучшего изучения микроконтроллера желательно уметь настраивать его в коде по тому что это основной обычный способ настройки для большинства микроконтроллеров и в случае возникновения бага к нему непременно придется вернуться. Конечно это будет проблематично и возможно не оправданно для сложной периферии вроде USB но для простой мигалки и подобных вещей генератор кода не дает существенных преимуществ (если конечно вообще их дает). В качестве языка для создания первой программы на новом микроконтроллере конечно более предпочтителен Си т.к. на ассемблере простая мигалка уже будет не такой простой чтобы не вызвать затруднения отбивающие желание продолжать обучение. Ассемблер, само собой, очень важный язык к которому приходиться обращаться для оптимизации, устранения багов или реверс иженеринге (возможно есть и другие причины о которых можно написать в комментариях) но в большинстве случаев такой необходимости нет. В качестве библиотеки для первой программы выбрана CMSIS т.к. она делает минимальные начальные настройки и доступ к регистрам без сложных высокоуровневых "оберток отделяющих программиста от этих регистров". Чтобы подключить CMSIS при создании проекта в среде Coocox CoIDE нужно поставить галочку в чекбоксе с надписью "CMSIS_Boot" (или с аналогичной надписью) галочка с надписью "CMSIS_Core" при этом, установиться автоматически.


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


Чтобы писать программу для микроконтроллера нужен документ с описанием всех его регистров. Для stm32f103c8t6 есть reference manual -  https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf.

В микроконтроллерах STM32, в отличии от AVR, прежде чем использовать какое либо периферийное устройство, нужно включить его тактирование. В данном микроконтроллере для этого есть два регистра APB1 и APB2. Чтобы помигать светодиодом нужно его сначала правильно подключить к какому нибудь пину на порту ввода-вывода общего назначения. Т.к. в микроконтроллерах STM32 есть замечательная возможность настроить пин как выход с открытым стоком то стоит испытать данный вариант. Его преимуществом перед обычным пушпульным выходом можно также назвать то что он более безопасен в случае например короткого замыкания между пинами (хотя если второй пин будет пушпульным и выдавать лог.1 то это не поможет) или пином и землей. Подключить светодиод к такому выходу можно например способом показанным на рисунке:


Можно также подключить светодиод между пином и землей а резистор между пином и плюсом питания и так он будет загораться при лог.1 на выходе но такой способ более энергозатратный и менее безопасный в случае случайного конфигурирования пина как пушпульный выход. Из рисунка выше видно что светодиод подключен к пину 9 порта B следовательно надо настроить тактирование порта B. Данная настройка осуществляется через регистр APB2:


-Это картинка из reference manual (см. ссылку выше) с выделенным (красным прямоугольником со скругленными краями) битом конфигурации тактирования порта B.

Т.е. для того чтобы включить тактирование порта B нужно записать 1 в бит 3. По умолчанию в этом бите находиться 0 но так бывает не всегда поэтому за этим надо следить чтобы делать правильные настройки. Чтобы сделать это в коде, можно использовать операцию присвоения с логическим или |= так в тех битах в которых уже установлена единица она останется а те в которых её нет она запишется. Можно также использовать простое присвоение и учитывать все единицы и нули сразу в 32ух разрядных микроконтроллерах это это делать проблематично ввиду большого количества битов за которыми надо следить не игнорируя те которые для решения текущей задачи не важны. После присвоения с логическим или можно использовать простые и наглядные двоичные числа например так:


Но из за того что битов 32 числа получаются длинными. Для сокращения можно использовать оператор побитового сдвига влево например так:


Это, всё ещё, не последний способ записать единицу в нужный бит но именно такой способ используется чаще всего, когда нужно видеть какой по счету бит устанавливается, из за его наглядности. В  строке после комментария "включить тактирование порта B" RCC - это указатель на структуру а APB2ENR - это поле данной структуры. Теперь чтобы настроить пин 9 порта B на выход с открытым коллектором нужен регистр GPIOB_CRH. В reference manual он обозначен как GPIOx_CRH где x - это буква порта (в нашем случае B):


Есть также регистр GPIOB_CRL где буква L указывает на то что этот регистр относиться к пинам с 0 по 7. Регистр же GPIOB_CRH относиться к пинам с 8 по 15 поэтому мы настраиваем его. Из мануала видно какие биты надо установить в единицу чтобы пин был с выходом с максимальной частотой 2МГц и открытым стоком (эти биты указаны стрелочками на картинке выше). При этом следует учитывать что не все биты по умолчанию установлены в 0. Это можно использовать и например не делать установку единицы бит 6 но если например нужно сделать пушпульный выход то нужно не забыть затереть этот бит записав в него ноль. В коде настройка выглядит так:


Теперь осталось сделать собственно мигание светодиодом. Т.е. установку в 1 пина 9 порта B (при этом светодиод гаснет т.к. верхний транзистор кмоп полумоста не работает и всегда закрыт а нижнему закрытым быть положено). Потом задержку. Специальной функции для задержки в библиотеке CMSIS нет, поэтому задержку нужно делать самому, для этого можно использовать пустой цикл. После чего сброс до 0 пина 9 порта B (светодиод при этом светиться т.к. нижний транзистор кмоп полумоста открывается). Для управления пином, в режиме выхода, есть три регистра, первые два из них можно использовать для установки в 0 или 1 а последний нужен только для сброса до 0 поэтому он не интересен. Первый называется GPIOx_ODR где x-буква порта (в нашем случае B). В этом регистре номер бита соответствует номеру пина (что очень удобно) поэтому для управления пиами можно даже не смотреть в мануал:


В коде мигалка будет выглядеть так:

Для сброса до нуля используется присвоение с логическим и которое выглядит так 
&=
также сдвиг в лево но на этот раз все биты инвертируются оператором "волнистая черта"
~
Можно также сделать это простым присваиванием но на, первых порах, важно рассмотреть базовый вариант установки конкретного бита. 
Второй регистр для управления пинами порта B называется GPIOB_BSRR. С ним работу следует вести по другому. Биты от 0 по 15 нужны для установки в 1 а оставшиеся для сброса до 0. Для установки 1 на пине 9 нужно в 9й бит записать единицу а если нужно установить лог. 0 на пине 9 то нужно в пин по номером 9+16=25 записать 1. Управление пином через данный регистр происходит быстрее чем через предыдущий. Мигалка, с использованием данного регистра, в коде может выглядеть так:

Полный код мигалки приведен в текстовом поле:



Видео по теме данной мигалки:



Комментариев нет:

Отправить комментарий