| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ARM это просто (часть 3)
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hello World по микроконтроллеровскиИтак, на ноги мы уже встали, в смысле на выводы микроконтроллера на плате STM32VL Discovery у нас подключено все что надо, говорить мы научились, на языке программирования Си, пора бы и Как уже говорилось в первой части, в качестве инструмента для написания программ на языке Си мы будем использовать среду разработки [IAR Embedded Workbench for ARMk (далее просто IAR), надеюсь, Вы уже скачали и установили её на свой компьютер. Также нам потребуется библиотека для работы с периферией микроконтроллеров серии STM32 [STM32F10x standard peripheral libraryk и драйвер внутрисхемного JTAG/SWD отладчика [ST-LINK USBk. Если у Вас еще не установлен драйвер для отладчика ST-LINK, то в таком случае необходимо произвести его установку. Структура файлов библиотеки
Рис. 1. Структура папок архива STM32F10X STDPERIPH LIB Рассмотрим подробнее, что содержится в данных папках. В корневой папке архива находится файл [stm32f10x_stdperiph_lib_um.chmk, представляющий из себя руководство пользователя библиотекой [STM32F10x Standard Peripherals Firmware Libraryk. В этом файле описана структура всех содержащихся файлов в архиве, а также в нем можно прочесть описание всех используемых в библиотеке функций и макроопределений. В папке [LibrariesSTM32F10x_StdPeriph_Driverinck содержатся заголовочные файлы библиотек для работы с периферийными модулями микроконтроллера. Рассмотрим подробнее назначение каждого содержащегося файла. Таблица 1. Список и краткое описание заголовочных файлов библиотек периферийных модулей
В папке [LibrariesSTM32F10x_StdPeriph_Driversrck содержатся файлы с исходными кодами настройки и работы с соответствующими периферийными модулями. В папке [LibrariesCMSISCM3CoreSupportk содержится файл исходного кода и соответствующий ему заголовочный файл [core_cm3k, данные файлы представляют собой файлы поддержки ядром периферийных модулей. Файлы с параметрами конкретного микроконтроллера содержатся в папке [LibrariesCMSISCM3DeviceSupportSTSTM32F10xk. Имеющиеся файлы [system_stm32f10xk описывают функции начальной инициализации периферии, и в них задается тактовая частота работы микроконтроллера. Файл [stm32f10x.hk содержит:
В папке [LibrariesCMSISCM3DeviceSupportSTSTM32F10xstartupk содержится ассемблерный код начальной инициализации микроконтроллера для различных компиляторов. В папке с именем нашего компилятора имеется несколько файлов для разных серий микроконтроллеров, для нашего микроконтроллера подходит файл [startup_stm32f10x_md_vl.sk. Помимо файлов с библиотеками, в скачанном архиве также имеются папки [Utilitiesk с примерами исходных кодов для платы STM32_EVAL и папка [Projectk. В папке [Projectk находятся папкиP[STM32F10x_StdPeriph_Examplesk с примерами использования библиотеки и [STM32F10x_StdPeriph_Templatek с шаблоном проекта для различных компиляторов. Создание проектаИтак, приступим к созданию своего первого проекта в среде программирования IAR на микроконтроллере STM32. Процесс создания и настройки шаблона проекта показан на видео. После того как мы создали свой проект, необходимо произвести настройку файлов библиотеки. Рассмотрим еще раз, более детальнее, содержимое файлов библиотеки и их назначение. Для этого открываем для редактирования файл [stm32f10x.hk, предварительно сняв атрибут [только чтениеk. Находим в файле место, где определяется линейка используемого нами микроконтроллера и раскомментируем строку с используемой нами линейкой микроконтроллеров. Подсказка, как определить какая линейка соответствует какому микроконтроллеру, расположена сразу после выбора линейки микроконтроллера. Поскольку мы иcпользуем микроконтроллер серии STM32F100 с 128кБайтами флеш памяти, то нам подходит линейка [Medium-density value linek, таким образом необходимо расскоментировать макроопределение STM32F10X_MD_VL.
После выбора линейки используемого микроконтроллера, идет указание частоты источника тактирования. По умолчанию для всех микроконтроллеров, за исключением линейки STM32F10X_CL, установлена частота работы кварцевого резонатора 8МГц, поскольку именно на такую частоту у нас и установлен кварц, то нам не требуется изменять это значение. Помимо частоты работы установленного кварцевого резонатора, возможно также указание частоты работы встроенного RC генератора, это делается изменением макроса HSI_VALUE. Более никаких изменений вносить в данный файл не требуется.
После данных настроек в файле расположены определения имен векторов прерываний, переопределения типов переменных (на более короткую форму записи, для удобства написания программ), после следуют структуры, содержащие имена регистров периферии, макросы, задающие адреса расположения структур с именами регистров и затем определения битов в регистрах. В файле [system_stm32f10x.ck также содержатся некоторые настройки, необходимость изменения которых также может возникнуть. В частности там задается рабочая тактовая частота системной шины:
При включении, микроконтроллер начинает свою работу с тактированием от встроенного RC генератора, во время выполнения кода инициализации, программа производит переключение системы тактирования, на тактирование от внешнего кварцевого резонатора, если кварцевый резонатор окажется неисправным или не подключенным, то микроконтроллер аппаратно изменит выбор источника тактирования на встроенный RC генератор. Если кварцевый резонатор является исправным, то после его запуска производится умножение его частоты модулем [PLLk, полученная частота является частотой системного тактирования (тактирования ядра микроконтроллера), и она не должна превышать максимальной частоты для данного микроконтроллера, в нашем случае 24МГц. Для тактирования периферийных модулей, эта частота может быть поделена модулем [AHB Prescalerk. Для линеек микроконтроллеров STM32F10X_LD_VL, STM32F10X_MD_VL и STM32F10X_HD_VL доступны только три возможных варианта тактирования, это работа на тактовой частоте 24МГц (при установленном кварцевом резонаторе на 8МГц), работа на частоте кварцевого резонатора (для этого необходимо закомментировать SYSCLK_FREQ_24MHz и раскомментировать SYSCLK_FREQ_HSE) либо от встроенного RC генератора (для этого необходимо закомментировать все строки). На этом все основные настройки файлов библиотеки можно считать выполненными. Для того чтобы в дальнейшем при создании новых проектов не приходилось выполнять повторно все эти настройки, сохраним данный проект как наш шаблон, для быстрого создания новых проектов. Скачать архив с файлами данного проекта можно по ссылке. Написание программыЗакончив с созданием и настройкой проекта, можно приступить к написанию реальной программы. Как повелось у всех программистов, первой программой написанной для работы на компьютере, является программа, выводящая на экран надпись [HelloWorldk, так и у всех микроконтроллерщиков первая программа для микроконтроллера производит мигание светодиода. Мы не будем исключением из этой традиции и напишем программу, которая будет управлять светодиодом LD3 на плате STM32VL Discovery. После создания пустого проекта в IAR, он создает минимальный код программы:
Поскольку наша функция main не должна завершаться, и возвращать каких либо значений (она будет работать в бесконечном цикле), то изменим данный код, убрав тип возвращаемой функцией переменной, оператор возврата из функции return и добавим цикл while, сделав его бесконечным.
Теперь наша программа будет всегда [крутитьсяk в цикле while. Для того, чтобы мы могли управлять светодиодом, нам необходимо разрешить тактирование порта к которому он подключен и настроить соответствующий вывод порта микроконтроллера на выход. Как мы уже рассматривали ранее в первой части, за разрешение тактирования порта С отвечает битIOPCEN регистра RCC_APB2ENR. Согласно документу [RM0041 Reference manual.pdfk для разрешения тактирования шины порта С необходимо в регистре RCC_APB2ENR установить бит IOPCEN в единицу. Чтобы при установке данного бита, мы не сбросили другие, установленные в данном регистре, нам необходимо к текущему состоянию регистра применить операцию логического сложения (логического [ИЛИk) и после этого записать полученное значение в содержимое регистра. В соответствии со структурой библиотеки ST, обращение к значению регистра для его чтения и записи производится через указатель на структуру RCC->APB2ENR. Таким образом, вспоминая материал со второй части, можно записать следующий код, выполняющий установку бита IOPCEN в регистре RCC_APB2ENR:
Как можно убедиться, из файла [stm32f10x.hk, значение бита IOPCEN определено какP0x00000010, что соответствует четвертому биту (IOPCEN) регистра APB2ENR и совпадает со значением указанным в даташите. Теперь аналогичным образом настроим вывод 9 порта С. Для этого нам необходимо настроить данный вывод порта на выход в режиме push-pull. За настройку режима порта на вход/выход отвечает регистр GPIOC_CRH, мы его уже рассматривали в первой статье, его описание также находится в разделе [7.2.2 Port configuration register highk даташита. Для настройки вывода в режим выхода с максимальным быстродействием 2МГц, необходимо в регистре GPIOC_CRH установить MODE9[1] в единицу и сбросить бит MODE9[0] в нуль. За настройку режима работы вывода в качестве основной функции с выходом push-pull отвечают биты CNF9[1] и CNF9[0], для настройки требуемого нам режима работы, оба эти бита должны быть сброшены в ноль.
Теперь вывод порта, к которому подключен светодиод, настроен на выход, для управления светодиодом нам необходимо изменить состояние вывода порта, установив на выходе логическую единицу. Для изменения состояния вывода порта существует два способа, первый это запись непосредственно в регистр состояния порта измененного содержимого регистра порта, так же как мы производили настройку порта. Данный способ не рекомендуется использовать в виду возможности возникновения ситуации, при которой в регистр порта может записаться не верное значение. Данная ситуация может возникнуть если во время изменения состояния регистра, с момента времени когда уже было произведено чтение состояния регистра и до момента когда произведется запись измененного состояния в регистр, какое либо периферийное устройство или прерывание произведет изменение состояния данного порта. По завершению операции по изменению состояния регистра произойдет запись значения в регистр без учета произошедших изменений. Хотя вероятность возникновения данной ситуации являетсяPочень низкой, все же стоит пользоваться другим способом, при котором описанная ситуация исключена. Для этого в микроконтроллере существует два регистра GPIOx_BSRR и GPIOx_BRR. При записи логической единицы в требуемый бит регистра GPIOx_BRR произойдет сброс соответствующего вывода порта в логический ноль. Регистр GPIOx_BSRR может производить как установку, так и сброс состояния выводов порта, для установки вывода порта в логическую единицу необходимо произвести установку битов BSn, соответствующих номеру необходимого бита, данные биты располагаются в младших регистрах байта. Для сброса состояния вывода порта в логический нуль, необходимо произвести запись битов BRn соответствующих выводов, эти биты располагаются в старших разрядах регистра порта. Светодиод LD3 подключен к выводу 9 порта С. Для включения данного светодиода, нам необходимо подать на соответствующем выводе порта логическую единицу, чтобы [зажечьk светодиод.
Добавим код настройки вывода порта светодиода в нашу программу, а также добавим функцию программной задержки, для уменьшения частоты переключения светодиода:
Скачать архив с исходным кодом программы, написанной с использованием непосредственного управления регистрами микроконтроллера можно по ссылке. Наша первая работоспособная программа написана, при её написании, для работы и настройки периферии, мы пользовались данными из официального даташита [RM0041 Reference manual.pdfk, данный источник информации о регистрах микроконтроллера является самым точным, но для того чтобы им пользоваться приходится перечитывать много информации, что усложняет написание программ. Для облегчения процесса настройки периферии микроконтроллера, существуют различные генераторы кода, официальной утилитой от компании ST представлена программа Microxplorer, но она пока еще малофункциональна и по этой причине сторонними разработчиками была создана альтернативная программа [STM32 Генератор программного кодаk. Данная программа позволяет легко получить код настройки периферии, используя удобный, наглядный графический интерфейс (см. рис. 2).
Как видно из рисунка 2, сгенерированный программой код настройки вывода светодиода совпадает с кодом написанным нами ранее. Для запуска написанной программы, после выполнения компиляции исходного кода, необходимо загрузить нашу программу в микроконтроллер и посмотреть, как она выполняется. Видео режима отладки программы мигания светодиодом Видео работы программы мигания светодиодом на плате STM32VL Discovery Библиотечные функции работы с перифериейДля упрощения работы с настройкой регистров периферии микроконтроллера, компания ST разработала библиотеки, благодаря использованию которых, не требуется так досконально читать даташит, поскольку при использовании данных библиотек, работа по написанию программы станет более приближена к написанию программ высокого уровня, в виду того, что все низкоуровневые функции реализуются на уровне функций библиотеки. Однако не следует полностью отказываться от использования непосредственной работы с регистрами микроконтроллера, в виду того, что библиотечные функции требуют больше процессорного времени на свое исполнение, как следствие их использование в критичных по времени выполнения участках программы не оправдано. Но все же, в большинстве случаев, такие вещи как инициализация периферии, не критичны ко времени выполнения, и удобство использования библиотечных функций оказывается более предпочтительным. Теперь напишем нашу программу с использованием библиотеки ST. В программе требуется произвести настройку портов ввода/вывода, для использования библиотечных функций настройки портов, необходимо произвести подключение заголовочного файла [stm32f10x_gpio.hk (см. табл. 1). Подключение данного файла можно произвести расскоментированием соответствующей строки в подключенном заголовочном конфигурационном файле [stm32f10x_conf.hk. В конце файла [stm32f10x_gpio.hk имеется список объявлений функций для работы с портами. Подробное описание всех имеющихся функций можно прочитать в файле [stm32f10x_stdperiph_lib_um.chmk, краткое описание наиболее часто применяемых приведено в таблице 2. Таблица 2.Описание основных функций настройки портов
Как видно из описания функций, в качестве параметров настроек порта и т.п., в функцию передают не множество различных отдельных параметров, а одну структуру. Структуры - это объединенные данные, у которых есть некоторая логическая взаимосвязь. В отличие от массивов, структуры могут содержать данные разных типов. Другими словами, структура представляет набор различных переменных с различными типами, объединенными в одну своеобразную переменную. Переменные, находящиеся в данной структуре называются полями структуры, а обращение к ним производится следующим образом, сперва пишется имя структуры, затем пишется точка и имя поля структуры (имя переменной в этой структуре). Список переменных, включенных в структуры для функций работы с портами, описаны в том же файле несколько выше описания функций. Так, например, структура [GPIO_InitTypeDefk имеет следующую структуру:
Первое поле данной структуры содержит переменную [GPIO_Pink типа unsigned short, в данную переменную необходимо записывать флаги номеров соответствующих выводов, для которых предполагается произвести необходимую настройку. Можно произвести настройку сразу несколько выводов, задав в качестве параметра несколько констант через оператор побитовое ИЛИ (см. часть 2). Побитовое ИЛИ [соберётk все единички из перечисленных констант, а сами константы являются маской, как раз предназначенной для такого использования. Макроопределения констант указаны в этом же файле ниже. Второе поле структуры [GPIO_InitTypeDefk задает максимально возможную скорость работы выхода порта. Список возможных значений данного поля перечислен выше:
Последнее, третье поле, [GPIOMode_TypeDefk отвечает за режим работы выводов порта. Данное поле представляет из себя перечисляемый тип enum и выглядит следующим образом:
Описание возможных значений:
Аналогичным образом можно посмотреть структуру переменных других структур, необходимых для работы с библиотечными функциями. Для работы со структурами, их также как и переменные, необходимо объявить и присвоить им уникальное имя, после чего можно обращаться к полям объявленной структуры, по присвоенному ей имени.
Практически вся периферия настраивается примерно таким же образом, различия имеются только в специфических для каждого устройства параметрах и командах. Теперь напишем нашу программу мигания светодиодом с использованием только библиотечных функций.
Пример рабочего проекта программы мигания светодиода с использованием прерывания можно скачать по ссылке. Из приведенного выше примера видно, что использование библиотечных функций работы с периферией позволяет приблизить написание программ для микроконтроллера к объектно-ориентированному программированию, а также снижает необходимость в частом обращению к даташиту для чтения описания регистров микроконтроллера, но использование библиотечных функций требует более высоких знаний языка программирования. В виду этого, для людей не особо близко знакомых с программированием, более простым вариантом написания программ будет являться способ написания программ без использования библиотечных функций, с прямым обращением к регистрам микроконтроллера. Для тех же, кто хорошо знает язык программирования, но плохо разбирается в микроконтроллерах, в частности STM32, использование библиотечных функций существенно упрощает процесс написания программ. Данное обстоятельство, а также тот факт, что компания ST позаботилась о высокой степени совместимости, как в аппаратном, так и в программном плане, различных своих микроконтроллеров, способствует более простому их изучению, в виду того, что не требуется углубляться на особенности строения различных контроллеров серии STM32 и позволяет в качестве микроконтроллера для изучения выбрать любой из имеющихся в линейке STM32 микроконтроллер. Обработчик прерыванияМикроконтроллеры имеют одну замечательную способность останавливать выполнение основной программы по какому-то определенному событию, и переходить к выполнению специальной подпрограммы обработчику прерывания. В качестве источников прерывания могут выступать как внешние события прерывания по приему/передаче данных через какой либо интерфейс передачи данных, или изменение состояния вывода, так и внутренние переполнение таймера и т.п.. Список возможных источников прерывания для микроконтроллеров серии STM32 приведен в даташите [RM0041 Reference manualk в разделе [8 Interrupts and eventsk. Поскольку обработчик прерывания также является функцией, то и записываться она будет как обычная функция, но чтобы компилятор знал, что данная функция является обработчиком определенного прерывания, в качестве имени функции следует выбрать заранее определенные имена, на которые указаны перенаправления векторов прерывания. Список имен этих функций с кратким описанием находится в ассемблерном файле [startup_stm32f10x_md_vl.sk. На один обработчик прерывания может приходиться несколько источников вызывающих прерывания, например функция обработчик прерывания [USART1_IRQHandlerk может быть вызвана в случае окончания приема и окончания передачи байта и т.д.. Для начала работы с прерываниями следует настроить и проинициализировать контроллер прерываний NVIC. В архитектуре Cortex M3 каждому прерыванию можно выставить свою группу приоритета для случаев, когда возникает несколько прерываний одновременно. Затем следует произвести настройку источника прерывания.
В поле NVIC_IRQChannel указывается, какое именно прерывание мы хотим настроить. Константа USART1_IRQn обозначает канал, отвечающий за прерывания, связанные с USART1. Она определена в файле [stm32f10x.hk, там же определены другие подобные константы. В следующих двух полях указывается приоритет прерываний (максимальные значения этих двух параметров определяются выбранной приоритетной группой). Последнее поле, собственно, включает использование прерывания. В функцию NVIC_Init, также как и при настройке портов передается указатель на структуру для применения внесенных настроек и записи их в соответствующие регистры микроконтроллера. Теперь в настройках модуля необходимо установить параметры, по которым данный модуль будет генерировать прерывание. Для начала следует произвести включение прерывания, это делается вызовом функции name_ITConfig(), которая находится заголовочном файле периферийного устройства.
Описание параметров, передаваемых функции, можно посмотреть в файле исходного кода периферийного устройства, чуть выше расположения самой функции. Данная функция разрешает или запрещает прерывания по различным событиям от указанного периферийного модуля. Когда данная функция будет исполнена, микроконтроллер сможет генерировать прерывания на требуемые нам события. После того как мы попадем в функцию обработки прерывания, нам необходимо проверить от какого события произошло прерывание, и затем сбросить взведенный флаг, иначе по выходу из прерывания микроконтроллер решит, что мы не обработали прерывание, поскольку флаг прерывания все еще установлен.
Для выполнения различных, небольших, повторяющихся с точным периодом действий, в микроконтроллерах с ядром Cortex-M3 имеется специально предназначенный для этого системный таймер. В функции данного таймера входит только вызов прерывания через строго заданные интервалы времени. Как правило, в вызываемом этим таймером прерывании, размещают код для измерения продолжительности различных процессов. Объявление функции настройки таймера размещено в файле «core_cm3.h». В качестве передаваемого функции аргумента указывается число тактов системной шины между интервалами вызова обработчика прерывания системного таймера.
Теперь разобравшись с прерываниями, перепишем нашу программу, используя в качестве времязадающего элемента системный таймер. Поскольку таймер «SysTick» является системным и им могут пользоваться различные функциональные блоки нашей программы, то разумным будет вынести функцию обработки прерывания от системного таймера в отдельный файл, из этой функции вызывать функции для каждого функционального блока по отдельности. Пример файла «main.с» программы мигания светодиода с использованием прерывания:
Часть исходного кода в файле «stm32f10x_it.c»:
Пример рабочего проекта программы мигания светодиода с использованием прерывания можно скачать по ссылке. На этом мой рассказ об основах разработки программ для микроконтроллера STM32 можно считать завершенным. Я предоставил всю информацию, необходимую для возможности дальнейшего самостоятельного изучения микроконтроллеров STM32. Предоставленный материал является лишь стартовым, поскольку полное описание работы с микроконтроллерами невозможно описать в рамках какой либо статьи. Помимо этого, изучение микроконтроллеров без получения практического опыта невозможно, а настоящий опыт приходит постепенно с годами работы, экспериментами, с накоплением различных программных и аппаратных наработок, а также чтении различных статей и документации по микроконтроллерам. Но пусть это Вас не пугает, поскольку предоставленной в статье информации вполне достаточно для создания своего первого устройства на микроконтроллере, а дальнейшие знания и опыт Вы сможете приобрести самостоятельно, разрабатывая с каждым разом все более сложные и лучшие устройства и совершенствуя свое мастерство. Надеюсь, я смог заинтересовать Вас заняться изучением микроконтроллеров и разработкой устройств на них, и мои труды будут Вам полезны и интересны. Часть 1. ARM – это просто. Введение.
Добавил: Павел (Admin) Автор: Сторожев Денис Вас может заинтересовать:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|