sonyps4.ru

Что такое ll библиотека для stm32. Подключение стандартной библиотеки периферии к любому семейству STM32

Список статей который поможет изучить микроконтроллер STM32 даже начинающему. Подробно обо всем с примерами начиная от мигания светодиодом до управления бесколлекторным двигателем. В примерах используется стандартная библиотека SPL (Standard Peripheral Library).

Тестовая плата STM32F103, ST-Link программатор, и программное обеспечение для прошивки под Windows и Ubuntu.

VIC (Nested vectored interrupt controller) – модуль контроля прерываний. Настройка и использование прерываний. Приоритеты прерываний. Вложенные прерывания.

АЦП (аналого-цифровой преобразователь). Схема питания и примеры использования АЦП в различных режимах. Regular и Injected каналы. Использование АЦП вместе с DMA. Внутренний термометр. Аналоговый watchdog.

Таймеры общего назначения. Генерирование прерывания через равные промежутки времени. Измерение времени между двумя событиями.

Захвата сигнала таймером на примере работы с ультразвуковым датчиком HC-SR04

Использование таймера для работы с энкодером.

Генерация ШИМ. Управление яркостью светодиода. Управление сервоприводом (сервомашинками). Генерация звука.

До этого момента мы использовали стандартную библиотеку ядра - CMSIS. Для настройки какого-либо порта на нужный режим работы нам приходилось обращаться к , чтобы найти отвечающий за определенную функцию регистр, а также искать по большому документу другую связанную с этим процессом информацию. Дело примет еще большие мучительные и рутинные обороты, когда мы приступим к работе с таймером или АЦП. Количество регистров там значительно больше, чем у портов ввода-вывода. Ручная настройка отнимает немало времени и повышает шанс допустить ошибку. Поэтому многие предпочитают работать со стандартной библиотекой периферии - StdPeriph. Что же она дает? Всё просто - повышается уровень абстракции, вам не нужно лезть в документацию и думать о регистрах в большинстве своеём. В этой библиотеке все режимы работы и параметры периферии МК описаны в виде структур. Теперь для настройки периферийного устройства необходимо лишь вызвать функцию инициализации устройства с заполненной структурой.

Ниже приведена картинка со схематичным изображением уровней абстракции.

Мы работали с CMSIS (которая находится «ближе» всего к ядру), чтобы показать, как устроен микроконтроллер. Следующим шагом является стандартная библиотека, пользоваться которой мы научимся сейчас. Дальше идут драйвера устройств. Под ними понимаются *.c \ *.h -файлы, которые обеспечивают удобный программный интерфейс для управления каким-либо устройством. Так, например, в этом курсе мы предоставим вам драйверы для микросхемы max7219 и WiFi-модуля esp8266.

Стандартный проект будет включать в себя следующие файлы:


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

Файлы библиотеки можно найти на странице, посвященной целевому МК (для нас это stm32f10x4), в разделе Design Resources (в среде CooCox IDE эти файлы скачиваются из репозитория среды разработки). Каждой периферии соответствуют два файла - заголовочный (*.h) и исходного кода (*.c). Детальное описание можно найти в файле поддержки, который лежит в архиве с библиотекой на сайте.

  • stm32f10x_conf.h - файл конфигурации библиотеки. Пользователь может подключить или отключить модули.
  • stm32f10x_ppp.h - заголовочный файл периферии. Вместо ppp может быть gpio или adc.
  • stm32f10x_ppp.c - драйвер периферийного устройства, написанный на языке Си.
  • stm32f10x_it.h - заголовочный файл, включающий в себя все возможные обработчики прерываний (их прототипы).
  • stm32f10x_it.c - шаблонный файл исходного кода, содержащий сервисные рутинные прерывания (англ. interrupt service routine , ISR) для исключительных ситуаций в Cortex M3. Пользователь может добавить свои ISR для используемой периферии.

В стандартной библиотекии периферии есть соглашение в наименовании функций и обозначений.

  • PPP - акроним для периферии, например, ADC.
  • Системные, заголовочные файлы и файлы исходного кода - начинаются с stm32f10x_ .
  • Константы, используемые в одном файле, определены в этом файле. Константы, используемые в более чем одном файле, определены в заголовочных файлах. Все константы в библиотеке периферии чаще всего написаны в ВЕРХНЕМ регистре.
  • Регистры рассматриваются как константы и именуются также БОЛЬШИМИ буквами.
  • Имена функций, относящихся к периферии, содержат акроним, например, USART_SendData() .
  • Для настройки каждого периферийного устройства используется структура PPP_InitTypeDef , которая передается в функцию PPP_Init() .
  • Для деинициализации (установки значения по умолчанию) можно использовать функцию PPP_DeInit() .
  • Функция, позволяющая включить или отключить периферию, именуется PPP_Cmd() .
  • Функция включения/отключения прерывания именуется PPP_ITConfig .

С полным списком вы опять же можете ознакомиться в файле поддержки библиотеки. А теперь давайте перепишем мигание светодиода с использованием стандартной библиотеки периферии!

Перед началом работы заглянем в файл stm32f10x.h и найдем строчку:

#define USE_STDPERIPH_DRIVER

Если вы будете настраивать проект с нуля, используя файлы библиотеки из скачанного архива, то вам будет необходимо раскомментировать данную строчку. Она позволит использовать стандартную библиотеку. Данное определение (макрос) скомандует препроцессору подключить файл stm32f10x_conf.h:

#ifdef USE_STDPERIPH_DRIVER #include "stm32f10x_conf.h" #endif

В этом файле подключаются модули. Если вам нужны только конкретные - отключите остальные, это сэкономит время при компиляции. Нам, как вы уже могли догадаться, нужны модули RTC и GPIO (однако в будущем потребуются также _bkp.h , _flash , _pwr.h , _rtc.h , _spi.h , _tim.h , _usart.h):

#include "stm32f10x_flash.h" // for init_pll() #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h"

Как и в прошлый раз, для начала нужно включить тактирование порта B. Делается это функцией, объявленной в stm32f10x_rcc.h:

Void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

Перечисление FunctionalState определено в stm32f10x.h:

Typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;

Объявим структуру для настройки нашей ножки (найти её можно в файле stm32f10x_gpio.h):

GPIO_InitTypeDef LED;

Теперь нам предстоит её заполнить. Давайте посмотрим на содержание этой структуры:

Typedef struct { uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; } GPIO_InitTypeDef;

Все необходимые перечисления и константы можно найти в этом же файле. Тогда переписанная функция init_leds() примет следующий вид:

Void led_init() { // Включаем тактирование RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Объявляем структуру и заполняем её GPIO_InitTypeDef LED; LED.GPIO_Pin = GPIO_Pin_0; LED.GPIO_Speed = GPIO_Speed_2MHz; LED.GPIO_Mode = GPIO_Mode_Out_PP; // Инициализируем порт GPIO_Init(GPIOB, &LED); }

Перепишем функцию main() :

Int main(void) { led_init(); while (1) { GPIO_SetBits(GPIOB, GPIO_Pin_0); delay(10000000); GPIO_ResetBits(GPIOB, GPIO_Pin_0); delay(10000000); } }

Главное - прочувствовать порядок инициализации: включаем тактирование периферии, объявляем структуру, заполняем структуру, вызываем метод инициализации. Другие периферические устройства обычно настраиваются по подобной схеме.

Я указывал, что к системе подключается стандартная библиотека. На самом деле, подключается CMSIS - система обобщенного структурного представления МК, а также SPL - стандартная библиотека периферии. Рассмотрим каждую из них:

CMSIS
Представляет собой набор заголовочных файлов и небольшого набора кода для унификации и структурировании работы с ядром и периферией МК. По сути, без этих файлов невозможно нормально работать с МК. Получить библиотеку можно на странице к МК.
Эта библиотека если верить описанию создавалась для унификации интерфейсов пр работе с любым МК семейства Cortex. Однако, на деле выходит, что это справедливо только для одного производителя, т.е. перейдя на МК другой фирмы вы вынуждены изучать его периферию почти с нуля.
Хотя те файлы которые касаются процессорного ядра МК у всех производителей идентичны (хотя бы потому, что модель процессорного ядра у них одна - предоставленная в виде ip-блоков компанией ARM).
Поэтому работа с такими частями ядра как регистры, инструкции, прерывания и сопроцессорные блоки стандартна для всех.
Что касается периферии то у STM32 и STM8 (внезапно) она почти похожа, также частично это справедливо и для других МК выпущенных компанией ST. В практической части, я покажу насколько просто использовать CMSIS. Однако трудности в его использовании связаны с нежеланием людей читать документацию и разбираться в устройстве МК.

SPL
Standard Peripheral Library - стандартная библиотека периферии. Как следует из названия, назначение этой библиотеки - создание абстракции для периферии МК. Библиотека состоит из заголовочных файлов где объявлены человеко-понятные константы для конфигурирования и работы с периферией МК, а также файлы исходного кода собираемые собственно в саму библиотеку для операций с периферией.
SPL является абстракцией над CMSIS представляя пользователю общий интерфейс для всех МК не только одного производителя, но и вообще всех МК с процессорным ядром Cortex-Mxx.
Считается, что она более удобна новичкам, т.к. позволяет не думать как работает периферия, однако качество кода, универсальность подхода и скованность интерфейсов накладывают на разработчика определенные ограничения.
Также функционал библиотеки не всегда позволяет точно реализовать настройку некоторых компонентов таких как USART (универсальный синхронный-асинхронный последовательный порт) в определённых условиях. В практической части, я также опишу работу с этой частью библиотеки.

При создании первого приложения на микроконтроллере STM32 можно пойти несколькими путями. Первый, классический, берём точное описание контроллера на сайте www.st.com , которое фигурирует под названием «Reference Manual» и читаем описание регистров периферии. Дальше пробуем записывать их и смотрим, как работает периферия. Чтение этого документа очень полезно, но на первом этапе освоения микроконтроллера от этого можно отказаться, как это не странно. Инженеры STMicroelectronics написали библиотеку драйверов стандартной периферии. Более того, они написали множество примеров использования данных драйверов, что может свести программирование вашего приложения к нажатию клавиш Ctrl+C и Ctrl+V, с последующей небольшой правкой примера использования драйвера под свои потребности. Таким образом, подключение библиотеки драйверов периферии к вашему проекту является вторым методом построения приложения. Кроме скорости написания есть и другие достоинства этого метода: универсальность кода и применение других фирменных библиотек, таких как USB, Ethernet, управление приводом и т.д., которые предоставляются в исходниках и использующих стандартный драйвер периферии. Недостатки данного метода тоже есть: Там где можно обойтись одной строкой кода стандартный драйвер периферии STM32 напишет 10. Сама библиотека периферии также предоставляется в виде исходных файлов, так что можно проследить какой бит какого регистра меняет та или иная функция. При желании можно будет перейти от второго метода написания программы к первому, закомментировав часть кода, использующего стандартную библиотеку на свою, управляющую непосредственно регистром периферии. В результате такого действия вы выиграете в скорости управления, объёме ОЗУ и ПЗУ, а потеряете в универсальности кода. В любом случае, инженеры компании "Промэлектроника" рекомендуют использовать библиотеку стандартной периферии хотя бы на первом этапе.

Наибольшие трудности ожидают разработчика при подключении библиотеки к своему проекту. Если не знать, как это делать, можно потратить много времени на это мероприятие, что противоречит самой идее использования готового драйвера. Материал посвящён подключению стандартной библиотеки к любому семейству STM32.

Каждое семейство STM32 имеет свою библиотеку стандартной периферии. Это связано с тем, что сама периферия разная. Например, периферия контроллеров STM32L в качестве одной из задач имеет функцию энергосбережения, что тянет за собой добавление функций управления. Классическим примером, можно считать АЦП, который в STM32L имеет возможность аппаратного отключения, при длительном отсутствии команды преобразования – одно из следствий задачи энергосбережения. АЦП контроллеров семейств STM32F не имеют такой функции. Собственно говоря, в силу наличия аппаратной разницы периферии имеем разные библиотеки драйверов. Кроме очевидного различия функций контроллера имеет место улучшение периферии. Так, периферия контроллеров семейств, которые были выпущены позже, может быть более продуманной и удобной. Например, периферия контроллеров STM32F1 и STM32F2 имеет различия по управлению. На взгляд автора управление периферией STM32F2 более удобное. И это понятно почему: STM32F2 семейство было выпущено позже и это позволило разработчикам учесть некоторые нюансы. Соответственно, для данных семейств – индивидуальные библиотеки управления периферией. Идея вышесказанного проста: на странице микроконтроллера, который вы собираетесь использовать, находится подходящая ему библиотека периферии.

Несмотря на различие периферии в семействах драйверы скрывают 90% различий внутри себя. Например, функция настройки, упомянутого выше АЦП, для всех семейств выглядит одинаково:

void ADC_Init(ADC_Nom, ADC_Param) ,

где ADC_Nom – номер АЦП в виде ADC1, ADC2, ADC3 и т. д.

ADC_Param – указатель структуры данных, каким образом надо настроить АЦП (от чего запускаться, сколько каналов оцифровывать, выполнять ли это циклически и т.д.)

10% различий семейств, в данном примере, которые придётся поправить при переходе с одного семейства STM32 на другое, спрятаны в структуре ADC_Param. В зависимости от семейства количество полей этой структуры может быть разным. Общая же часть, имеет одинаковый синтаксис. Таким образом, перевод приложения для одного семейства STM32, написанного на базе стандартных библиотек периферии на другое, весьма прост. В части универсализации решений на микроконтроллерах STMicroelectronics неотразим!

Итак, мы скачали библиотеку для применяемого STM32. Что дальше? Далее, нам надо создать проект и подключить к нему требуемые файлы. Создание проекта рассмотрим на примере среды разработки IAR Embedded Workbench. Запускаем среду разработки и заходим на вкладку “Project”, выбираем пункт создания проекта “Create project”:

В появившемся новом проекте вводим настройки, наведя курсор на название проекта, нажав правую клавишу мыши и выбрав в выпавшем меню «Options»:

Области памяти ОЗУ и ПЗУ:

При нажатии кнопки “Save” среда предложит записать новый файл описания контроллера в папку проекта. Автор рекомендует создавать каждому проекту индивидуальный файл *.icp и хранить его в папке с проектом.

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

На вкладке выбранного отладчика указываем интерфейс подключения отладчика (в нашем случае выбран ST-Link) к контроллеру:



С этого момента наш проект без библиотек готов к компиляции и загрузке в контроллер. В других средах, таких как Keil uVision4, Resonance Ride7 и т. п. потребуется выполнить эти же действия.

Если в файле main.c написать строку:

#include "stm32f10x.h" или

#include "stm32f2xx.h" или

#include "stm32f4xx.h" или

#include "stm32l15x.h" или

#include "stm32l10x.h" или

#include "stm32f05x.h"

с указанием расположения данного файла, либо копированием данного файла в папку проекта, то произойдёт ассоциация некоторых областей памяти с регистрами периферии соответствующего семейства. Сам файл находится в папке библиотеки стандартной периферии в разделе: \CMSIS\CM3\DeviceSupport\ST\STM32F10x (или похожее по названию для других семейств). С этого момента вы заменять адрес регистра периферии в виде числа его названием. Даже если вы не собираетесь использовать функции стандартной библиотеки, рекомендуется сделать такое подключение.

Если вы собираетесь использовать в своём проекте прерывания, то рекомендуется подключить стартовый файл с расширением *.s, который находится по пути \CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\iar, или подобном, для других семейств. Важно отметить, что для каждой среды файл свой. Соответственно, если мы используем IAR EWB, то должны взять файл из папки IAR. Это обусловлено небольшим различием синтаксиса сред. Поэтому, чтобы проект запустился сразу, инженеры STMicroelectronics написали несколько вариантов стартовых файлов для нескольких наиболее популярных сред разработки. Большинство семейств STM32 имеют один файл. Семейство STM32F1 имеет несколько запускающих фалов:

  • startup_stm32f10x_cl.s – для микроконтроллеров STM32F105/107
  • startup_stm32f10x_xl.s - для микроконтроллеров STM32F101/STM32F103 768кб и более
  • startup_stm32f10x_hd.s - для микроконтроллеров STM32F101/STM32F103 c памятью Flash 256-512 кб
  • startup_stm32f10x_md.s - для микроконтроллеров STM32F101/ STM32F102/STM32F103 c памятью Flash 64-128 кб
  • startup_stm32f10x_ld.s - для микроконтроллеров STM32F101/ STM32F102/STM32F103 c памятью Flash менее 64кб
  • startup_stm32f10x_hd_vl.s для микроконтроллеров STM32F100 c памятью Flash 256-512 кб
  • startup_stm32f10x_md_vl.s для микроконтроллеров STM32F100 c памятью Flash 64-128 кб
  • startup_stm32f10x_ld_vl.s для микроконтроллеров STM32F100 c памятью Flash 32кб и менее

Итак, в зависимости семейства, подсемейства и среды разработки добавляем запускающий файл в проект:

Именно здесь оказывается микроконтроллер при старте программы. Прерывание последовательно вызывает функцию SystemInit(), а затем __iar_program_start. Вторая функция обнуляет либо записывает заранее заданные значения глобальных переменных, после чего осуществляет переход в программу пользователя main(). Функция SystemInit() настраивает тактирование микроконтроллера. Именно она даёт ответы на вопросы:

  • Надо ли переключаться на внешний кварц (HSE)?
  • Как умножить частоту от HSI/HSE?
  • Требуется ли подключение очереди загрузки команд?
  • Какая требуется задержка при загрузке команды (из-за низкой скорости работы Flash памяти)
  • Как поделить тактирование шин периферии?
  • Требуется ли разместить код во внешней ОЗУ?

Функцию SystemInit() можно прописать вручную в своём проекте. Если оформить эту функцию как пустую, то контроллер будет работать на внутреннем RC-генераторе с частотой порядка 8МГц (в зависимости от типа семейства). Вариант 2 – подключить к проекту файл system_stm32f10x.c (либо похожий по названию в зависимости от типа используемого семейства), который расположен в библиотеке по пути: Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x. В этом файле имеется функция SystemInit(). Обратите внимание на частоту внешнего кварца HSE_VALUE. Данный параметр выставляется в заголовочном файле stm32f10x.h. Стандартное значение 8 и 25МГц, в зависимости от семейства STM32. Основная задача функции SystemInit() – переключить тактирование на внешний кварц и умножить определённым образом данную частоту. Что произойдёт, если значение HSE_VALUE указано 8МГц, ядро должно тактироваться частотой 72МГц, а по факту на плате стоит кварц 16МГц? В результате таких некорректных действий ядро получит тактирование 144МГц, которые могут оказаться за пределами гарантированной работы системы на STM32. Т.е. при подключении файла system_stm32f10x.c потребуется указать значение HSE_VALUE. Всё это означает, что файлы system_stm32f10x.c, system_stm32f10x.h и stm32f10x.h (или похожие по названию для других семейств) должны быть индивидуальными для каждого проекта. И

нженеры STMicroelectronics создали инструмент Clock Configuration Tool, который позволяет правильно настроить тактирование системы. Это файл Excel, генерирующий файл system_stm32xxx.c (похожий по названию для заданного семейства семейств), после задания входных и выходных параметров системы. Рассмотрим его работу на примере STM32F4 семейства.

Варианты: внутренний RC-генератор, внутренний RC-генератор с умножением частоты, либо внешний кварц с умножением частоты. После выбора источника тактирования вводим параметры желаемой конфигурации системы, такие как входную частоту (при использовании внешнего кварца), частоту тактирования ядра, делители частоты тактирования шин периферии, работу буфера выборки команд и другие. Нажав на кнопку “Generate”, получаем окно


Подключение файла system_stm32f4xx.c и его аналогов потребует подключение ещё одного файла стандартной библиотеки периферии. Для управления тактированием имеется целый набор функций, которые вызываются из файла system_stm32xxxxxx.c. Эти функции расположены в файле stm32f10x_rcc.c и его заголовке. Соответственно, подключая к проекту файл файла system_stm32xxxxxx.c требуется подключить stm32f10x_rcc.c, иначе линкер среды сообщит об отсутствии описания функций с именем RCC_xxxxxxx. Указанный файл находится в библиотеке периферии по пути: Libraries\STM32F10x_StdPeriph_Driver\src, а его заголовок \Libraries\STM32F10x_StdPeriph_Driver\inc.

Подключение заголовочных файлов драйвера периферии происходит в файле stm32f10x_conf.h, на который ссылается stm32f10x.h. Файл stm32f10x_conf.h – это просто набор заголовочных файлов драйверов конкретных периферий контроллера, подлежащих включению в проект. Изначально все заголовки «#include» отмечены как комментарии. Подключение заголовочного файла периферии заключается в снятии комментария с соответствующего названия файла. В нашем случае – это строка #include "stm32f10x_rcc.h". Очевидно, что файл stm32f10x_conf.h индивидуален для каждого проекта, т.к. разные проекты используют разную периферию.

И последнее. Надо указать несколько директив препроцессору компилятора и пути к заголовочным файлам.



Пути к заголовочным файлам могут быть иными, в зависимости от расположения библиотеки периферии относительно папки проекта, а вот наличие “ USE_STDPERIPH_DRIVER” – обязательно при подключении драйверов периферии стандартной библиотеки.

Итак, мы подключили стандартную библиотеку, к проекту. Более того, мы подключили один из стандартных драйверов периферии к проекту, выполняющих управление тактированием системы.

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



Таким образом, подключение заголовочного файла stm32f10x.h в приложении тянет за собой подключение других заголовочных файлов и файлов кода. Некоторые из представленных на рисунке описаны выше. Несколько слов об остальных. Файлы STM32F10x_PPP.x – это файлы-драйверы периферии. Пример подключения такого файла показан выше, это RCC – периферия управления тактированием системы. Если мы хотим подключить драйверы другой периферии, то название подключаемых файлов получается заменой «PPP» названием периферии, например АЦП - STM32F10x_ADC.с, или порты ввода-вывода STM32F10x_GPIO.с, или ЦАП - STM32F10x_DAC.с. В целом интуитивно понятно какой файл нужно подключить при подключении заданной периферии. Файлы «misc.c», «misc.h» - это по большому счёту те же STM32F10x_PPP.x, только выполняют управление ядром. Например настройку векторов прерываний, который встроен в ядро или управление таймером SysTick, который является частью ядра. Файлы xxxxxxx_it.c описывают вектора немаскируемых прерываний контроллера. Они могут быть дополнены векторами прерываний периферии. Файл core_m3.h описывает ядро CortexM3. Данное ядро стандартизовано и может встречаться в микроконтроллерах других производителей. Для кросс-платформенной универсализации компания STMicroelectronics провела работу по созданию отдельной библиотеки ядра CortexM, после чего компания ARM стандартизировала её и распространила на других производителей микроконтроллеров. Так что переход на STM32 с контроллеров других производителей с ядром CortexM будет чуть проще.

Итак, мы можем подключить библиотеку стандартной периферии к любому семейству STM32. Того, кто научился это делать ждёт приз: очень простое программирование микроконтроллеров. Библиотека кроме драйверов в виде исходных файлов содержит множество примеров применения периферии. Для примера, рассмотрим создание проекта с участием выходов сравнения таймера. При традиционном подходе мы будем внимательно изучать описание регистров данной периферии. Но сейчас мы можем изучить текст работающей программы. Заходим в папку примеров стандартной периферии, которая находится по пути ProjectSTM32F10x_StdPeriph_Examples. Здесь находятся папки примеров с названием применяемой периферии. Заходим в папку «TIM». Таймеры в STM32 имеют множество функций и настроек, поэтому одним примером возможности контроллера продемонстрировать невозможно. Поэтому внутри указанного каталога имеется множество примеров применения таймеров. Нас интересует генерация ШИМ сигнала таймером. Заходим в папку «7PWM_Output». Внутри имеется описание работы программы на английском языке и набор файлов:

main.c stm32f10x_conf.h stm32f10x_it.h stm32f10x_it.c system_stm32f10x.c

Если проект не имеет прерываний, то содержательная часть полностью расположена в файле main.c. Копируем эти файлы в каталог проекта. Скомпилировав проект, мы получим программу для STM32, которая настроит таймер и порты ввода-вывода на генерацию 7-ми ШИМ сигналов от таймера 1. Далее, мы можем приспособить уже написанный код под свою задачу. Например, уменьшить число ШИМ сигналов, изменить скважность, направление счёта и т.п. Функции и их параметры хорошо описаны в файле stm32f10x_stdperiph_lib_um.chm. Названия же функций и их параметров легко ассоциируются с их назначением для тех, кто немного знает английский язык. Для наглядности приводим часть кода взятого примера:

/* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; // предделение счётных импульсов отсутствует (16-битный регистр) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // направление счёта вверх TIM_TimeBaseStructure.TIM_Period = TimerPeriod; // счёт выполнять до значения TimerPeriod (константа в программе) TIM_TimeBaseStructure.TIM_ClockDivision = 0; // предделение счётных отсутствует TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // счётчик переполнений для генерации событий (не используется в программе) TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // ввод значений TimeBaseStructure в регистры таймера 1 (ввод данных в эту // переменную - выше) /* Channel 1, 2,3 and 4 Configuration in PWM mode */ // настройка ШИМ выходов TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // режим работы ШИМ2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // разрешитьвыход ШИМ сигналов таймера TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // разрешить комплиментарный выходШИМтаймера TIM_OCInitStructure.TIM_Pulse = Channel1Pulse; // ширина импульс Channel1Pulse – константа в программе TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // настройка полярности выхода TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // настройка полярности комплиментарного выхода TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; // установка безопасного состояния выхода ШИМ TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; // установка безопасного состояния комплиментарного выхода ШИМ TIM_OC1Init(TIM1, &TIM_OCInitStructure); // ввод значений переменной TIM_OCInitStructure в регистры ШИМ канала 1 // таймера1 TIM_OCInitStructure.TIM_Pulse = Channel2Pulse; // меняем ширину импульса в переменной OCInitStructure и вводим её в TIM_OC2Init(TIM1, &TIM_OCInitStructure); // регистры ШИМ канала 2 таймера1 TIM_OCInitStructure.TIM_Pulse = Channel3Pulse; // меняем ширину импульса в переменной OCInitStructure и вводим её в TIM_OC3Init(TIM1, &TIM_OCInitStructure); // регистры ШИМ канала 3 таймера1 TIM_OCInitStructure.TIM_Pulse = Channel4Pulse; // меняем ширину импульса в переменной OCInitStructure и вводим её в TIM_OC4Init(TIM1, &TIM_OCInitStructure); // регистры ШИМ канала 4 таймера1 /* TIM1 counter enable */ TIM_Cmd(TIM1, ENABLE); // запускаем таймер1 /* TIM1 Main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); // разрешаем работу выходов сравнения таймера 1

В правой части автор оставил комментарий на русском языке к каждой строке программы. Если открыть этот же пример в описании функций библиотек stm32f10x_stdperiph_lib_um.chm, то мы увидим, что все используемые параметры функций имеют ссылку на собственное описание, где будут указаны их возможные значения. Сами функции тоже имеют ссылку на собственное описание и исходный код. Это очень полезно, т.к. зная, что функция делает, мы можем проследить, каким образом она это делает, на какие биты регистров периферии и как она воздействует. Это, во-первых, ещё один источник информации для освоения контроллера, основанный на практическом использовании контроллера. Т.е. вы сначала решите техническую задачу, а потом изучите само решение. Во-вторых, это поле для оптимизации программы тому, кого библиотека не устроит по скорости работы и объёму кода.



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

Ниже представлен рисунок платы STM32F3 Discovery , где: 1 — MEMS датчик. 3-осевой цифровой гироскоп L3GD20. 2 — МЕМС система-в-корпусе, содержащая 3-осевой цифровой линейный акселерометр и 3-осевой цифровой геомагнитный сенсор LSM303DLHC. 4 – LD1 (PWR) – питание 3.3V. 5 – LD2 – красный/зеленый светодиод. По умолчанию красный. Зеленый означает связь между ST-LINK/v2 (or V2-B) и ПК. У меня ST-LINK/v2-B, а также индикации пользовательского порта USB. 6. -LD3/10 (red), LD4/9 (blue), LD5/8 (orange) and LD6/7 (green). В прошлой записи мы с Вами мигали светодиодом LD4. 7. – Две кнопки: пользовательская USER и сброса RESET. 8. — USB USER with Mini-B connector.

9 — USB отладчик/программатор ST-LINK/V2. 10. — Микроконтроллер STM32F303VCT6. 11. — Внешний высокочастотный генератор 8 Мгц. 12. – Здесь должен быть низкочастотный генератор, к сожелению не запаян. 13. – SWD – интерфейс. 14. – Джемперы для выбора программирования внешних контроллеров или внутреннего, в первом случае должны быть удалены. 15 – Джемпер JP3 – перемычка, предназначена для подключения амперметра, что б измерить потребление контроллера. Понятно если она удалена, то наш камушек не запустится. 16. – STM32F103C8T6 на нем находится отладочная плата. 17. — LD3985M33R Регулятор с низким падением напряжения и уровнем шума, 150мА, 3.3В.

Теперь познакомимся поближе с архитектурой микроконтроллера STM32F303VCT6. Его техническая характеристика: корпус LQFP-100, ядро ARM Cortex-M4, максимальная частота ядра 72МГц, объём памяти программ 256 Кбайт, тип памяти программ FLASH, объём оперативной памяти SRAM 40 кбайт, RAM 8 кбайт, количество входов/выходов 87, интерфейсы (CAN, I²C, IrDA, LIN, SPI, UART/USART, USB), периферия (DMA, I2S, POR, PWM, WDT), АЦП/ЦАП 4*12 bit/2*12bit, напряжение питания 2 …3.6 В, рабочая температура –40 …...+85 С. На рисунке ниже распиновка, где видим 87 портов ввода/вывода, 45 из них Normal I/Os (TC, TTa), 42 5-volt tolerant I/Os (FT, FTf) – совместимые с 5 В. (на плате справа 5В выводы, слева 3,3В). Каждая цифровая линия ввода-вывода может выполнять функцию линии ввода-вывода общего
назначения или альтернативную функцию. По ходу продвижения проектов мы с Вами будем последовательно знакомится с периферией.

Рассмотрим блок диаграмму ниже. Сердцем является 32-битное ядро ARM Cortex-M4, работающее до 72 МГц. Имеет встроенный блок с плавающей запятой FPU и блок защиты памяти MPU, встроенные макро-ячейки трассировки — Embedded Trace Macrocell (ETM), которые могут быть использованы для наблюдения за процессом выполнения основной программы внутри микроконтроллера. Они способны непрерывно выводить данные этих наблюдений через контакты ETM до тех пор, пока устройство работает. NVIC (Nested vectored interrupt controller) – модуль контроля прерываний. TPIU (Trace Port Interface Unit). Содержит память FLASH –256 Кбайт, SRAM 40 кбайт, RAM 8 кбайт. Между ядром и памятью расположена Bus matrix (Шинная матрица), которая позволяет соединить устройства напрямую. Также здесь видим два типа шинной матрицы AHB и APB, где первая более производительная и используется для связи высокоскоростных внутренних компонентов, а последняя для периферии (устройств ввода/вывода). Контроллер имеет 4 –ри 12-разрядных ADC (АЦП) (5Мбит/с) и датчик температуры, 7 компараторов (GP Comparator1 …7), 4-ри программируеммых операционных усилителя (OpAmp1…4) (PGA (Programmable Gain Array)), 2 12 разрядных канала DAC (ЦАП), RTC (часы реального времени), два сторожевых таймера — независимый и оконный (WinWatchdog and Ind. WDG32K), 17 таймеров общего назначения и многофункциональные.

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

1). CMSIS (Cortex Microcontroller Software Interface Standard) - стандартная библиотека для Cortex®-M. Обеспечивает поддержку устройств и упрощает программные интерфейсы. CMSIS предоставляет последовательные и простые интерфейсы для ядра, его периферии и операционных систем реального времени. Ее использования является профессиональным способом написания программ, т.к. предполагает прямую запись в регистры и соответственно необходимо постоянное чтение и изучение даташитов. Независим от производителя аппаратного уровня.
CMSIS включает в себя следующие компоненты:
— CMSIS-CORE: Consistent system startup and peripheral access (Постоянный запуск системы и периферийный доступ);
— CMSIS-RTOS : Deterministic Real-Time Software Execution (Детерминированное исполнение программного обеспечения реального времени);
— CMSIS-DSP: Fast implementation of digital signal processing (Быстрая реализация цифровой обработки сигналов);
— CMSIS-Driver: Generic peripheral interfaces for middleware and application code (Общие периферийные интерфейсы для промежуточного программного обеспечения и кода приложения);
— CMSIS-Pack : Easy access to reusable software components (Легкий доступ к многократно используемым программным компонентам);
— CMSIS-SVD: Consistent view to device and peripherals (Согласованное представление устройства и периферийных устройств);
— CMSIS-DAP: Connectivity to low-cost evaluation hardware (Возможность подключения к недорогому оборудованию для оценки). ПО для отладки.

Для примера напишем программу – мигаем светодиодом. Для этого нам понадабится документация описывающая регистры. В моем случае RM0316 Reference manual STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC, STM32F398xE advanced ARM ® -based MCUs , а также описние конткретной ножки за что отвечает DS9118 : ARM®-based Cortex®-M4 32b MCU+FPU, up to 256KB Flash+ 48KB SRAM, 4 ADCs, 2 DAC ch., 7 comp, 4 PGA, timers, 2.0-3.6 V. Для начала в программе затактируем порт, т.к. по умолчанию все отключено чем достигается уменьшенное эрергопотребление. Открываем Reference manual и смотрим раздел Reset and clock control далее RCC register map и смотрим что за включение IOPEEN отвечает регистр

Перейдем в описание тактирования перефирии данного регистра AHB peripheral clock enable register (RCC_AHBENR) , где видим что данный порт находится под 21-м битом. Включаем его RCC->AHBENR|=(1<<21) . Далее сконфигурируем регистры GPIO. Нас интересует три: GPIOE_MODER и GPIOx_ODR . C помощью них повторим программу с предыдущей статьи, затактируем PE8. Первый отвечает за конфигурацию входа выхода, выбираем 01: General purpose output mode. GPIOE->MODER|=0×10000 . Второй за включение низкого/высокого уровня на ножке. Ниже программа:

#include "stm32f3xx.h" //Заголовочный файл микроконтроллера
unsigned int i;
void delay () {
for (i=0;i<500000;i++);
}
int main (void) {
RCC->AHBENR|=(1<<21);
GPIOE->MODER|=0×10000;
while (1){
delay ();
GPIOE->ODR|=0×100;
delay ();
GPIOE->ODR&=~(0×100);
} }

2). SPL (Standard Peripherals Library) - данная библиотека предназначена для объединения всех процессоров фирмы ST Electronics. Разработана для урощения преносимости кода и в первую очередь расчитана на начинающег разаработчика. ST работала над заменой SPL под названием «low layer», которая совместима с HAL. Драйверы Low Layer (LL) разработаны для обеспечения почти легкого экспертно-ориентированного уровня, который ближе к оборудованию, чем HAL. В дополнение к HAL также доступны LL API . Пример тойже программы на SPL.

#include
#include
#include
#define LED GPIO_Pin_8
int main() {
long i;
GPIO_InitTypeDef gpio;
// Blue LED is connected to port E, pin 8 (AHB bus)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
// Configure port E (LED)
GPIO_StructInit(&gpio); //объявляем и инициализируем переменную структуры данных
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Pin = LED;
GPIO_Init(GPIOE, &gpio);
// Blinking LEDS
while (1) {
// On
GPIO_SetBits(GPIOE, LED);
for (i = 0; i < 500000; i++);
// All off
GPIO_ResetBits(GPIOE, LED);
for (i = 0; i < 500000; i++);
} }

Каждая функция описывается в технической документации UM1581 User manual Description of STM32F30xx/31xx Standard Peripheral Library . Здесь подключаем три заголовочных файла которые содержат необходимоые данные, структуры, функции управления сбросом и синхронизацией, а также для конфигурации портов ввода/вывода.

3). HAL - (Hardware Acess Level , Hardware Abstraction Layer) - Еще одна общая библиотека для разработки. С которой вышла и программа CubeMX для конфигурации, которую мы с Вами использовали в прошлой статье. Там же мы написали программу мигания светодиодом используя данную библиотеку. Как видим на рисунке, ниже, куб генерирует драйвера HAL and CMSIS. Что ж опишем основные используемые файлы:
— system_stm32f3x.c и system_stm32f3x.h - предоставляют минимальные наборы функций для конфигурации системы тактирования;
— core_cm4.h – предоставляет доступ к регистрам ядра и его периферии;
— stm32f3x.h - заголовочный файл микроконтроллера;
— startup_system32f3x.s — стартовый код, содержит таблица векторов прерываний и др.

#include «main.h»
#include «stm32f3xx_hal.h»
void SystemClock_Config (void); /*Объявляем функции конфигурации тактирования*/
static void MX_GPIO_Init (void); /*Инициализация ввода/вывода*/
int main (void) {
/*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 ();
while (1) {
HAL_GPIO_TogglePin (GPIOE, GPIO_PIN_8);//Переключаем состояние ножки
HAL_Delay (100); }
}
void SystemClock_Config (void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig (&RCC_OscInitStruct) != HAL_OK) {

}
/**Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig (&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
_Error_Handler (__FILE__, __LINE__);
}
/**Configure the Systick interrupt time*/
HAL_SYSTICK_Config (HAL_RCC_GetHCLKFreq ()/1000);
/**Configure the Systick */
HAL_SYSTICK_CLKSourceConfig (SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority (SysTick_IRQn, 0, 0);
}
/** Configure pins as Analog Input Output EVENT_OUT EXTI */
static void MX_GPIO_Init (void) {
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE ();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configure GPIO pins: PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init (GPIOE, &GPIO_InitStruct);
}
void _Error_Handler (char * file, int line) {
while (1) {
} }
#ifdef USE_FULL_ASSERT

Void assert_failed (uint8_t* file, uint32_t line) {
}
#endif
Здесь также как и в предыдущем примере можем просмотреть описание каждой функции в документации, например UM1786 User Manual Description of STM32F3 HAL and low-layer drivers.

Можем подвести итог, что первый выриант, используя CMSIS, является менее громоздким. Для каждой библиотеки есть документация. В последующих проектах, мы будем использовать HAL и CMSIS, используя программу для конфигурации STCube и по возможности использовать регистры напрямую, без программных оберток. На этом сегодя и остановимся. В следующей статье мы с Вами рассмотрим основные принципы построения умного дома. Всем пока.



Загрузка...