Современные микроконтроллеры STM, ATMEL AVR, PIC (520 книг) + исходники
Современные микроконтроллеры STM, ATMEL AVR, PIC (520 книг) + исходники Год: 2000-2016 Авторы: разные Издательство: разные Формат: pdf, djvu, chm, iso Язык: русский, английский Размер: Part 1 — 1,95 GB, Part 2 — 1,95 GB, Part 3 — 1,89 GB Подборка книг по микроконтроллерам на русском и английском…
Программирование и отладка C/C++ приложений для микроконтроллеров ARM
Магда Ю.С Программирование и отладка C/C++ приложений для микроконтроллеров ARM Год: 2012 Издательство: ДМК Язык: русский Формат: pdf Страниц: 168 Размер: 5 Мб В книге рассмотрены практические аспекты программирования приложений для популярной микропроцессорной платформы ARM. Материал книги имеет…
Измерение, управление и регулирование с помощью AVR микроконтроллеров (+CD)
Измерение, управление и регулирование с помощью AVR микроконтроллеров (+CD) Автор: Трамперт В. Год: 2006 Издательство: К.: МК-Пресс Язык: русский Формат: DjVu + CD Страниц: 200 Размер: 101,74 Мб Благодаря своей высокой производительности при сравнительно невысокой цене, серия AVR от компании Atmel…
Создаем устройства на микроконтроллерах
Название: Создаем устройства на микроконтроллерах Автор: А. В. Белов Издательство: СПб — Наука и Техника Серия «Радиолюбитель» Данная книга представляет собой практическое пособие по разработке электронных схем с применением микроконтроллеров и управляющих программ к ним. Основа книги — это ряд…
Beginning 8051 Microcontroller projects Handson
Название: Beginning 8051 Microcontroller projects Handson: Edge Avoiding Robot, Attendance System, Line Follower Robot, Stepper Motor and Servo Motor, ESP32 BLE Server, Blinking a LED etc. Автор: Anbazhagan K. Год: 2020 Издательство: Independently published Язык: английский Формат: pdf, azw3, epub…
AVR & ARM7. Programowanie mikrokontrolerow dla kazdego
Jak efektywnie nauczyć się programowania mikrokontrolerów? Jak skonstruować programator lub zdobyć go w inny sposób? Jak obsługiwać wyświetlacz LED w czterech językach? Jeżli nie masz pojęcia o programowaniu mikrokontrolerów, a chcesz się tego nauczyć, ta książka jest właśnie dla Ciebie. Nie musisz…
Системы на микроконтроллерах и БИС программируемой логики
Рассматривается технология проектирования микроэлектронных систем на основе микроконтроллеров и БИС программируемой логики (ПЛИС). Описаны «ядра» MCS-51 и AVR современных микроконтроллеров, микроконвертер ADjaC812 фирмы Analog Devices, семейства ПЛИС на примере изделий фирмы Altera. Рассмотрено…
Getting Started for Internet of Things with Launch Pad and ESP8266
Getting Started for Internet of Things with Launch Pad and ESP8266 provides a platform to get started with the Ti launch pad and IoT modules for Internet of Things applications. The book provides the basic knowledge of Ti launch Pad and ESP8266 based customized modules with their interfacing, along…
Микроконтроллеры AVR. Практикум для начинающих
Название: Микроконтроллеры AVR. Практикум для начинающих, 2-е изд. Автор: Хартов В. Я. Год: 2012 Издательство: М.: МГТУ им. Н. Э. Баумана Язык: русский Формат: djvu, pdf (+ file) Страниц: 280 Размер: 50.8 Мб Практикум содержит материалы для изучения микроконтроллеров AVR с архитектурой RISC….
AVR-RISC микроконтроллеры
AVR-RISC микроконтроллеры. В книге дано исчерпывающее описание базовой серии микроконтроллеров семейства AVR от компании Atmel, построенных на базе прогрессивной архитектуры RISC с применением программируемой флэш-памяти EPROM. Кроме того, подробно рассматривается программирование микроконтроллеров…
Программирование микроконтроллеров. Благодаров А.В., Владимиров Л.Л.
Программирование микроконтроллеров на основе отечественных микросхем семейства 1986ВЕ9x разработки и производства компании Миландр. Рассматриваются основы программирования на языке Си отечественных 32-разрядных микроконтроллеров семейства 1986ВЕ9х разработки и производства компании «Миландр»….
Ibrahim Dogan. The Ultimate Compendium of Sensor Projects
Title: The Ultimate Compendium of Sensor Projects Author: Ibrahim Dogan Year: 2020 Publisher: Elektor International Media English language Format: PDF Pages: 330 Size: 10.9 Mb This book is about developing projects using the sensor-modules with Arduino Uno, Raspberry Pi and ESP32 microcontroller…
John Boxall. AVR Workshop: A Hands-On Introduction with over 60 Projects
Title: AVR Workshop: A Hands-On Introduction with over 60 Projects Author: John Boxall Year: 2022 Publisher: No Starch Press Language: English Format: ePUB Pages: 609 Size: 37.8 Mb AVR Workshop is a comprehensive introduction to working with the Microchip AVR 8-bit family of microcontrollers – made…
PIC Microcontroller Programming & Practical (2nd edition)
This is 2nd edition of PIC microcontroller Programming & Practical and its Medium level Project book with Programmings and circuits in which I have discus Some sensor Interfacing, Programming with Circuits, UART Communication example and lots of programming technique you can fined here in this…
PIC-микроконтроллеры. Архитектура и программирование
Название: PIC-микроконтроллеры: архитектура и программирование Автор: Майкл Предко Издательство: ДМК Пресс Год: 2010 Язык: русский Формат: djvu Страниц: 512 Размер: 31,8 Мб Книга посвящена PIC-микроконтроллерам — одному из самых популярных семейств современных микроконтроллеров. В справочнике…
Кэмерон Н. Электронные проекты на основе ESP8266 и ESP32
Название: Электронные проекты на основе ESP8266 и ESP32 Автор: Кэмерон Н. Год: 2022 Издательство: ДМК Язык: русский Формат: True PDF Страниц: 458 Размер: 14,48 Мб Микроконтроллеры ESP8266 и ESP32 необычайно популярны во всем мире как основа для построения интернета вещей и систем умного дома. Они…
Книги по программированию микроконтроллеров mculab.ru
|
|
В 1980 году компания Intel разработала первый микроконтроллер (8051) с гарвардской архитектурой 8051, и с тех пор микроконтроллеры произвели настоящую революцию в электронике. И в настоящее время мы располагаем целым набором эффективных и сравнительно дешевых микроконтроллеров: AVR, PIC, ARM и др. Данные микроконтроллеры просты в освоении и поддерживают широкий набор современных интерфейсов связи: USB, I2C, SPI, CAN и т.д. Отдельную микро революцию в этой сфере произвели такие платы как Arduino и Raspberry Pi, при этом Raspberry Pi представляет собой не просто микроконтроллер, а целый компьютер внутри.
Данным материалом мы начнем на нашем сайте цикл обучающих статей по микроконтроллерам PIC, которые являются отличным выбором для начинающих освоение микроконтроллерной техники.
В этой статье мы рассмотрим общее устройство микроконтроллеров PIC и программное обеспечение, с помощью которого можно работать с данными микроконтроллерами. Видео в конце данной статьи расскажет вам об установке и настройке таких программ как MPLABX, XC8, Proteus. Также будет рассмотрена быстрая распаковка программатора PICkit 3.
Микроконтроллер PIC впервые был представлен компанией Microchip Technologies в 1993 году. Первоначально эти микроконтроллеры были разработаны как часть компьютеров PDP (Programmed Data Processor), и все периферийные устройства подключались к данному компьютеру с использованием данного микроконтроллера PIC. Отсюда микроконтроллеры PIC и получили свое название – Peripheral Interface Controller (контроллер периферийного интерфейса). Позже компания Microchip разработала множество микросхем серии PIC, которые могут быть использованы для практически любых небольших приложений, таких, к примеру, как освещение, и вплоть до достаточно «продвинутых» устройств.
Каждый микроконтроллер в современном мире построен на основе определенной архитектуры, самый известный сейчас тип архитектуры для микроконтроллеров – это гарвардская архитектура. И микроконтроллеры PIC основаны именно на этой архитектуре, поскольку они принадлежат к классическому семейству 8051. Поэтому давайте рассмотрим основы данной архитектуры.
Микроконтроллер PIC16F877A состоит из встроенного процессора, портов ввода-вывода, нескольких типов памяти, аналого-цифрового преобразователя (АЦП), таймеров/счетчиков, системы прерываний, портов последовательной связи, генератора и модуля CCP, что делает его удобным для применения в большинстве проектов встраиваемой электроники. Структурная схема архитектуры микроконтроллера PIC приведена на следующем рисунке.
Центральный процессор (Central Processing Unit, CPU)
Центральный процессор в микроконтроллерах PIC предназначен для выполнения арифметических и логических операций и операций чтения/записи в память. Также он выполняет функции координатора между оперативной памятью (RAM) и другими периферийными устройствами микроконтроллера.
Центральный процессор состоит из следующих основных компонентов:
- арифметико-логическое устройство (АЛУ), выполняющее арифметические и логические операции;
- блок памяти (Memory unit, MU), хранит инструкции (команды) после их выполнения;
- блок управления, выполняет роль коммуникационной шины между центральным процессором и другими периферийными устройствами микроконтроллера.
Оперативное запоминающее устройство (Random Access Memory, RAM)
Оперативное запоминающее устройство (ОЗУ) – это один из компонентов, который оказывает существенное влияние на скорость работы микроконтроллера. Оно состоит из набора регистров, каждый из которых выполняет свои определенные функции. Данные регистры могут быть классифицированы по двум основным признакам:
- регистры общего назначения (General Purpose Register, GPR);
- специальные регистры (Special Function Register, SFR).
Как следует из их названия, регистры общего назначения (РОН) выполняют такие основные функции как сложение, вычитание и т.д. В микроконтроллерах PIC эти операции ограничены размером 8 бит. Регистры общего назначения доступны как для записи, так и для чтения, и не могут выполнять каких либо специальных функций если это не предусмотрено в программе.
Специальные регистры, в свою очередь, используются для выполнения сложных специальных функций и для них доступны 16-битные операции. Эти регистры доступны для чтения, но записывать в них ничего нельзя. Выполнение специальных функций этими регистрами запрограммировано на заводе-изготовителе микроконтроллеров.
Постоянное запоминающее устройство (Read Only Memory, ROM)
Постоянное запоминающее устройство (ПЗУ) – это место, в котором хранится наша программа. Оно определяет максимальный размер нашей программы, по этой причине его также называют памятью программ (program memory). Для записи ПЗУ доступно только во время программирования микроконтроллера PIC, во время выполнения программы оно представляет собой память, доступную только для чтения (read only memory).
Электрически стираемое программируемое постоянное запоминающее устройство (ЭСППЗУ, EEPROM)
ЭСППЗУ – это еще один вид памяти, который часто присутствует в современных микроконтроллерах. В этой памяти данные хранятся во время исполнения программы. Стереть эти данные можно только электрическим способом, что означает сохранность данных даже в то время, когда микроконтроллер будет выключен.
Флэш память (Flash Memory)
Флэш память представляет собой еще один вид программируемой памяти, доступной только для чтения (Programmable Read Only Memory, PROM), в которую мы можем записывать, считывать и стирать программу тысячу раз.
Порты ввода/вывода
В микроконтроллере PIC16F877A есть пять портов: Port A, Port B, Port C, Port D и Port E. Из этих пяти портов только Port A является 16-битным, а PORT E – 3-битным. Остальные 3 порта являются 8-битными.
Контакты данных портов могут использоваться для ввода и вывода данных, в зависимости от конфигурации регистра TRIS. Кроме функций ввода/вывода контакты портов могут выполнять специальные функции: формирование ШИМ сигнала, обработка прерываний, связь по интерфейсу SPI и др.
Шина
Термин «шина» означает совокупность проводов, которые соединяют входные и выходные устройства с центральным процессором и оперативной памятью. Шина данных используется для передачи или приема данных.
Адресная шина используется для передачи адреса памяти от периферийных устройств к центральному процессору. Контакты ввода/вывода (I/O pins) используются для подключения внешних периферийных устройств. Протоколы последовательной связи UART и USART используются для подключения таких устройств как модули GSM, GPS, Bluetooth, инфракрасной связи и др.
Выбор микроконтроллера PIC для наших проектов
Микроконтроллеры PIC от компании Microchip подразделяются на 4 больших семейства. Каждое семейство отличается своим набором компонентов и характеристик.
- Первое семейство, PIC10 (10FXXX) – называется Low End.
- Второе семейство, PIC12 (PIC12FXXX) – называется Mid-Range.
- Третье семейство – это PIC16 (16FXXX).
- Четвертое семейство – это PIC 17/18(18FXXX).
Поскольку в дальнейшем мы на нашем сайте будем рассматривать достаточно много проектов на основе микроконтроллеров PIC, то для этих проектов мы решили выбрать достаточно универсальный микроконтроллер, относящийся к семейству 16F – это микроконтроллер PIC16F877A. Он способен работать с такими популярными сейчас интерфейсами как SPI, I2C и UART.
После того как вы выбрали микроконтроллер, первым делом необходимо изучить даташит на него. Из данного даташита можно узнать что микроконтроллер PIC16F877A содержит 3 таймера, два из которых являются 8-битными, а третий – с 16-битным предделителем. Данные таймеры также могут использоваться в качестве счетчиков. Также из даташита можно узнать, что микроконтроллер поддерживает CCP опции (Capture Compare и PWM), которые позволяют ему формировать сигналы ШИМ (широтно-импульсной модуляции) и считывать частоту входных сигналов. Для связи с внешними устройствами он обладает интерфейсами SPI, I2C, PSP и USART.
Микроконтроллер PIC16F877A содержит 8-канальный 10-битный АЦП (аналого-цифровой преобразователь), который позволяет производить преобразование аналоговых значений в цифровые с разрешением 10 бит. Это преобразование можно осуществлять на 8 контактах микроконтроллера. Также в составе микроконтроллера есть два встроенных компаратора, которые позволяют непосредственным образом сравнивать значения поступающих напряжений, без считывания их программным способом.
Память программ микроконтроллера поддерживает до 100 тысяч циклов перезаписи, что позволяет его перепрограммировать 100 тысяч раз. Разъем ICSP™ (In-Circuit Serial Programming™) позволяет нам программировать микроконтроллер с помощью PICKIT3. Отладку работы программы можно производить через разъем ICD (In-Circuit Debug). Также в составе микроконтроллера есть и сторожевой таймер (Watchdog Timer, WDT), который позволяет, при необходимости, производить сброс работы программы.
На следующем рисунке представлена распиновка микроконтроллера PIC16F877A, на которой вы можете увидеть все специальные функции, которые могут выполнять определенные контакты микроконтроллера.
Выбор программного обеспечения для наших проектов
Микроконтроллеры PIC могут программироваться с помощью различного программного обеспечения, присутствующего сейчас на рынке. Некоторые энтузиасты до сих пор используют для их программирования язык ассемблера, но мы в нашей серии обучающих статей по микроконтроллерам PIC будем использовать инструменты, разработанные компанией Microchip.
Для программирования микроконтроллеров PIC нам понадобится интегрированная среда разработки (Integrated Development Environment, IDE), в которой мы непосредственно будем писать программы. Также нам будет необходим компилятор, который преобразовывать нашу программу в HEX файл – формат, который понимает наш микроконтроллер. И, наконец, нам понадобится интегрированная среда программирования (Integrated Programming Environment, IPE), которая будет записывать наш HEX файл в микроконтроллер. В качестве всех этих инструментов мы выберем следующие:
- IDE: MPLABX v3.35;
- IPE: MPLAB IPE v3.35;
- Compiler: XC8.
Компания Microchip предоставляет все эти инструменты бесплатно. После скачивания этих программ необходимо установить их на свой компьютер. Более подробно эти процессы вы можете посмотреть на видео, приведенном в конце статьи.
Для моделирования работы схем мы будем использовать программное обеспечение PROTEUS 8 от компании Labcenter, которое можно скачать по следующей ссылке.
Подготовка аппаратного обеспечения
Для загрузки кода программы в микроконтроллер PIC мы будем использовать программатор PICkit 3, купить который на Aliexpress можно по следующей ссылке. Данный программатор прост в освоении, относительно дешево стоит и управляется с помощью программы MPLAB IDE (версии v8.20 или выше), установленный на компьютер с Windows. Кроме данного программатора нам также понадобится перфорированная или макетная плата, паяльная станция, непосредственно сам микроконтроллер, кварцевые генераторы, конденсаторы и т.д.
Видео
Загрузка…
2 071 просмотров
Конспект первой лекции по программированию современных микроконтроллеров на примере STM32 и операционной системы RIOT. Лекции читаются в Институте информационных технологий МИРЭА по субботам, с 12:50 в актовом зале на 4 этаже корпуса Д. В занятиях отводится 1,5 часа на саму лекцию и 3 часа на практические занятия в лаборатории IoT Академии Samsung по теме лекции.
Привет, Гиктаймс! Как мы и обещали, начинаем публикацию конспектов лекций, которые сейчас читаются в Институте ИТ МИРЭА. По результатам первой, вводной лекции мы решили немного изменить структуру курса — вместо планировавшихся двух потоков по 5 занятий будет один поток на 7 занятий. Это позволит в более спокойном темпе разобрать ряд вспомогательных вопросов, а также статьи с конспектом будут появляться на GT каждую неделю в течение всего марта и апреля, а не через неделю, как планировалось раньше.
Тем не менее, в семь лекций невозможно полностью уложить столь обширную тему, поэтому местами изложение будет тезисным — хотя для компенсации этого мы постараемся указывать, в какую сторону смотреть тем, кто хочет самостоятельно глубже разобраться в том или ином вопросе.
Курс рассчитан на студентов второго и третьего курсов, знакомых с языком C и базовыми понятиями электроники и электротехники. Предварительное знакомство с микроконтроллерами не требуется.
Цель курса — освоение навыков, позволяющих свободно работать с микроконтроллерами на ядре ARM Cortex-M на современном уровне и, при наличии такого желания, двигаться в сторону дальнейшего углубления своих знаний.
Сегодняшняя лекция — первая, поэтому на ней будут разбираться общие понятия: что такое вообще микроконтроллер и зачем он нужен, что такое прошивка и как она получается, зачем нам нужна операционная система, и наконец — как работать с git. Результат практического занятия — собственный репозитарий на GitHub с исходными кодами ОС, а также успешно настроенная среда сборки на локальном компьютере.
Микроконтроллер
Если говорить коротко, то микроконтроллер — это классический пример «системы на чипе», включающей в себя как процессорное ядро, так и набор вспомогательных и периферийных устройств, позволяющий микроконтроллеру во многих случаях быть полностью самодостаточным.
В типовом микропроцессоре, подобном тому, что стоит в любом ПК или смартфоне, практически все модули, которые можно отнести к вспомогательным (питание, тактирование, даже базовые периферийные устройства), вынесены за пределы самого чипа, несмотря на то, что работать без них микропроцессор не может.
В микроконтроллере же, наоборот, на одном кристалле с ядром реализованы не только необходимые для его работы подсистемы, но и масса периферийных устройств, которые могут потребоваться в различных практических задачах. Более того, многие производители микроконтроллеров соревнуются друг с другом не по производительности ядра или объёму памяти, а по обилию и функциям периферийных устройств.
Микроконтроллеры уже достаточно давно развиваются параллельно с микропроцессорами — так, до сих пор встречающаяся в промышленных изделиях архитектура Intel 8051 была разработана в 1980 году. В каких-то моментах линии их развития начинают пересекаться с микропроцессорами — так, старшие модели микроконтроллеров имеют интерфейсы для внешнего ОЗУ, а производители микропроцессоров интегрируют на кристалл всё больше периферийных устройств (достаточно вспомнить, что на заре «персоналок» даже кэш-память набиралась внешними микросхемами) — но в любом случае они остаются двумя существенно отличающимися ветвями развития.
Собственно, целью создания микроконтроллеров была возможность удешевления и миниатюризации различных устройств, требующих некоторой небольшой вычислительной мощности: использование одного чипа, на который для его работы достаточно просто подать питание, существенно упрощает разработку и производство печатной платы по сравнению с набором из 4-5 отдельных чипов.
Разумеется, у микроконтроллера есть свои ограничения — технически невозможно упаковать в один кристалл то, что в большом ПК занимает половину немаленькой платы.
- Рабочие частоты редко превышают 200 МГц, а чаще находятся в районе десятков мегагерц.
- Объём оперативной памяти — в пределах мегабайта, а чаще — в районе десятков килобайт.
- Объём памяти программ — в пределах мегабайта, а чаще — в районе десятков-сотен килобайт.
Мы в рамках курса будем работать с микроконтроллерами STM32L151CC, имеющими 32 КБ ОЗУ, 256 КБ ПЗУ и максимальную рабочую частоту 32 МГц (на платах Nucleo-L152RE стоят чуть более серьёзные чипы — 80 КБ ОЗУ и 512 КБ ПЗУ).
Память
В общем случае внутри микроконтроллера может быть четыре вида памяти:
- Постоянная память (флэш-память) используется для хранения пользовательских программ и, иногда, некоторых настроек самого микроконтроллера. Если при указании на характеристики микроконтроллера пишут объём памяти, не указывая, какой именно — как правило, это про флэш. Содержимое флэша не сбрасывается при пропадании питания, срок хранения информации в нём в нормальных условиях обычно не менее 10 лет.
- Оперативная память используется для выполнения пользовательской программы и хранения «сиюминутных» данных. ОЗУ всегда сбрасывается при перезагрузке или выключении питания, а также может не сохраняться при входе в некоторые режимы сна. В микроконтроллерах часто нет чёткого разделения на память программ и память данных — в результате можно встретить термин «выполнение из ОЗУ», означающий, что в ОЗУ находятся не только данные, но и сама программа; впрочем, это достаточно экзотические случаи.
- EEPROM. Тоже относится к постоянной памяти, но существенно отличается от флэш-памяти своими характеристиками. У флэша есть два больших недостатка, делающие его очень неудобным для сохранения из программы каких-то текущих данных — во-первых, у флэша ограниченное число перезаписей одной и той же ячейки, во-вторых, с флэшом часто можно работать только целыми страницами, которые имеют размер в сотни байт, даже если вам надо перезаписать всего один байт. EEPROM этих недостатков лишён — срок его службы обычно вдесятеро больше (от 100 тыс. до 1 млн. перезаписей), и работать в нём можно с каждым байтом по отдельности. По этой причине EEPROM используют для постоянного хранения данных, генерируемых самой программой (архивы измерений, настройки программы и т.п.), его типовой объём составляет единицы килобайт, но есть он не во всех контроллерах.
- Системная память. Области постоянной памяти, недоступные пользователю для записи, а записывающиеся при производстве микроконтроллера. Обычно в них находится исполняемый код загрузчика (о нём ниже), но могут также храниться какие-либо калибровочные константы, серийные номера или даже вспомогательные библиотеки для работы с периферийными устройствами
Посмотреть на организацию памяти конкретного контроллера можно в его даташите. Вот, например, даташит на STM32L151CC, на странице 51 которого представлена карта памяти этого семейства.
Нетрудно заметить, что все четыре вида памяти, о которых мы говорили, занимают очень небольшой кусочек карты — а на большей части картинки расположился перечень всех имеющихся в контроллере периферийных устройств.
Регистры
Дело в том, что всё — вообще всё — общение со всеми периферийными устройствами микроконтроллера и всеми его настройками осуществляется с помощью всего двух операций:
- прочитать значение по заданному адресу
- записать значение по заданному адресу
Всё, что есть внутри микроконтроллера, обязательно отображено на какой-то адрес. Эти адреса называются регистрами (не путайте с регистрами процессора — в регистрах процессорах находятся данные, над которыми процессор производит операции; в регистрах, о которых мы говорим, находятся некие специальные данные, которые специфическим образом отображаются на состояние различных аппаратных блоков микроконтроллера).
Так, например, если мы хотим, чтобы на третьей ножке порта А микроконтроллера (PA2, нумерация идёт с нуля) появилась «1», нам надо записать «1» в третий бит регистра, расположенного по адресу 0x4002014. А если эта ножка настроена как вход и мы, наоборот, хотим узнать, какое на ней значение — нам надо прочитать третий бит регистра по адресу 0x40020010.
Да, чтобы указать контроллеру, входом или выходом является эта ножка — надо записать соответствующие значения в соответствующие биты по адресу 0x40020000.
Это — важный момент в понимании работы микроконтроллера: абсолютно всё, что не является вычислительными операциями, за которые отвечает само ядро процессора, осуществляется с помощью записи или чтения того или иного регистра. Какие бы библиотеки не были наворочены в вашей программе сверху — в конечном итоге всё сводится к регистрам.
Разумеется, работать с числовыми адресами довольно неудобно, поэтому для каждого микроконтроллера на ядре Cortex-M существует библиотека CMSIS (Cortex Microcontroller Software Interface Standard), самый важный компонент которой для нас — заголовочный файл, описывающий имеющиеся в конкретном контроллере регистры и дающий им относительно человекочитаемые имена.
С использованием CMSIS описанные выше операции с ножкой PA будут выглядеть так:
int pin_num = 2; /* PA2*/
GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2 на всякий случай */
GPIOA->MODER |= 0b01 << (pin_num*2); /* установили биты настройки ножки PA2 в 01 — выход */
GPIOA->ODR |= 1 << pin_num; /* установили ножку PA2 в 1 */
GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2, теперь это вход */
uint32_t pa2_value = GPIOA->IDR & (1 << pin_num); /* прочитали состояние ножки PA2 */
Все названия регистров и значения полей в них описаны в документе, который можно считать Библией программиста микроконтроллеров — Reference Manual (он, разумеется, свой для каждого семейства контроллеров, ссылка дана на RM0038, соответствующий семейству STM32L1). Отмечу, что более чем 900 страниц RM0038 — это не очень большой объём информации, легко можно встретить контроллеры с руководствами по 1500-2000 страниц. Вряд ли есть кто-то, помнящий хотя бы треть такого руководства наизусть, но умение быстро в нём ориентироваться — обязательное качество для хорошего программиста.
Разумеется, этот код — лишь условно человекопонятный. Использование буквенных названий вместо адресов радикально снижает процент ошибок в коде и увеличивает его читаемость, но всё ещё крайне далеко от того, что большинство людей назовёт «нормальным» кодом.
Понимая это, производители контроллеров начали выпускать вспомогательные библиотеки, собирающие наборы обращений к регистрам в функции — например, если при работе с регистрами напрямую для включения какого-либо такового генератора вам надо сделать два действия (поставить в 1 бит, включающий генератор, и подождать, пока в 1 встанет флаг, индицирующий, что генератор вышел на режим), то в функции включения генератора в такой библиотеке они будут объединены.
В случае с STM32 основная библиотека называется Standard Peripherals Library, она же StdPeriphLib, она же SPL. Помимо неё, существует выпускаемая ST библиотека LL, и ряд сторонних библиотек — например, LibOpenCM3. Сторонние библиотеки часто поддерживают и контроллеры других производителей, но в силу распространённости STM32 они обычно оказываются на первом месте.
Так, при использовании SPL обращения к регистрам, которые мы совершали, чтобы зажечь светодиод, превратятся в обращения к функциям GPIO_Init и GPIO_Write.
Впрочем, нельзя не заметить, что среди профессиональных разработчиков отношение к SPL — двойственное.
С одной стороны, SPL позволяет значительно быстрее набросать «скелет» проекта, особенно при использовании графических средств конфигурирования контроллера, таких как STM32 CubeMX. При этом код будет довольно хорошо (настолько, насколько у них совпадает набор периферийных устройств и возможностей, которыми вы пользуетесь) переноситься между разными контроллерами семейства STM32.
С другой стороны, как показывает практика, в сложном проекте нет вопроса «что делать, если что-то будет работать не так» — в нём есть вопрос «что делать, когда всё будет работать не так». В SPL, как и в любой библиотеке, могут быть ошибки, кроме того, логика разработчиков SPL может не совпадать с вашим представлением о том, что должно происходить с контроллером при тех или иных действиях — в результате при попадании в такую ситуацию вам всё равно придётся открывать исходники SPL и смотреть, что конкретно там происходит на уровне регистров. На практике это может иногда занять времени не меньше, чем написание нужной вам функциональности с нуля.
Кроме того, библиотеки, выпущенные конкретным производителем чипов, хоть и позволяют в каких-то пределах мигрировать между чипами этого производителя, но перескочить, например, с STM32L1 на ATSAMD21 с кодом, написанным для SPL, у вас не получится при всём желании.
Не всегда помогает SPL и читаемости кода — в программах, написанных с её использованием, нередко можно увидеть простыни размером в полстраницы, состоящие из одних только вызовов SPL.
Наконец, SPL решает лишь одну проблему — абстрагирования от «железа» и работы с регистрами. Однако по мере развития проекта вы столкнётесь ещё с несколькими, например:
- Виртуализация периферийных устройств. Например, в вашем контроллере есть всего один таймер часов реального времени (RTC), на который можно установить два независимых события — и в то же время в серьёзной программе запросто может оказаться пять-шесть функций, который используют таймер регулярно (для периодического выполнения заданий) или разово (например, для отсчёта задержки), причём другие таймеры им не подходят. В этой ситуации вам потребуется функция-менеджер, которая будет организовывать одновременную работу всех этих процедур с единственным имеющимся таймером.
- Многозадачность. Любая достаточно сложная система быстро обрастает большим количеством всевозможных процедур, которым надо срабатывать с различной периодичностью или по различным событиями. Знакомый многим по Arduino цикл loop() уже на полудесятке утрамбованных в него разношёрстных процедур начинает выглядеть уродливым монстром, а попытка организовать в его рамках ещё и приоритизацию задач вселяет ужас в сердца людей. В этот момент вы захотите вынести все задачи из loop() в независимые функции, оставив в цикле только планировщик, который будет к указанным задачам обращаться. Это будет первыми зачатками многозадачности (о полной её реализации, типах планировщиков и общении между разными задачами мы поговорим на следующей лекции).
- Разделение труда. Как только разработка системы выйдет на уровень, на котором её ведут несколько человек, перед вами встанет задача разделения обязанностей — помимо оптимизации разработки, имеющая ещё и чисто практический смысл: в мире довольно мало программистов-универсалов, которые могут с одинаковой эффективностью отлаживать и работу с процессором, и сетевой стек, и пользовательский интерфейс. Со значительно большей вероятностью каждый из членов вашей команды будет лучше других разбираться в какой-то одной области — поэтому вам быстро захочется разделить эти области на уровне кода, чтобы, например, специалист по пользовательскому интерфейсу не был вынужден через строчку сталкиваться с обращением к регистрам контроллера, и наоборот. Это приведёт к разбиению вашего кода на отдельные модули, общающиеся друг с другом через стандартизированные API.
Все эти задачи — и попутно ещё много других — решает операционная система.
Несмотря на то, что ОС требует для своего существования дефицитных ресурсов контроллера (обычно 5-20 КБ постоянной памяти и ещё столько же оперативной), преимущества использования ОС настолько велики, что на данный момент в профессиональной разработке для встраиваемых систем около 70 % проектов используют ту или иную ОС.
Строго говоря, на нижнем уровне ОС может использовать вендорские библиотеки, подобные SPL. Однако в рамках нашего курса мы будем работать с RIOT OS, нижнеуровневый код которой для семейства STM32 написан на регистрах — работу с SPL же мы затрагивать не будем вообще.
Причина этого проста: хотя в целом мы будем изучать работу ОС и контроллера на верхнем уровне, но в тех случаях, когда мы захотим углубиться в детали их функционирования, нам всё равно придётся спускаться на уровень регистров, и прослойка в виде SPL довольно сильно бы этому мешала. Освоив же общие принципы работы с контроллерами, при желании с функционированием SPL вы сможете разобраться самостоятельно, тем более, что абсолютное большинство учебников по STM32, доступных онлайн, построены на её базе.
Операционная система
В виде максимально упрощённой схемы ОС можно представить как набор компонентов, выстроенных в определённую иерархию:
- нижний уровень — код, непосредственно работающий с микроконтроллером;
- средний уровень — компоненты, входящие в саму ОС, но уже не зависящие от конкретного контроллера: драйверы различных внешних устройств, планировщик задач, различные вспомогательные службы;
- верхний уровень — собственно пользовательское приложение.
Одна из причине, почему мы будем работать с RIOT OS и без использования каких-либо средств разработки (IDE) — в получающем в последнее время всё большее распространение магическом мышлении, согласно которому, многие функции реализуются нажатием соответствующих кнопок в IDE, и без этих кнопок невозможны (так, я встречал утверждение, что достоинство Arduino IDE — в возможности собрать один и тот же код под разные аппаратные платформы путём выбора нужной платформы в меню; по мнению рассказчика, другие системы таким функционалом не обладали, так как не имели соответствующего меню).
Точнее, если вспоминать фразу Артура Кларка про технологии, неотличимые от магии, то это мышлении можно скорее назвать псевдомагическим, переформулировав афоризм как «любая технология, достаточно хорошо спрятанная от пользователя, становится неотличима от магии».
На самом деле, разумеется, никакой особенной функции меню в Arduino IDE, как и в любой другой IDE, не несёт — это лишь графическая оболочка для доступа к некоторым совершенно стандартным функциям и особенностям современных программных систем.
Если мы посмотрим на то, как выглядит RIOT OS в виде набора файлов на диске, то без труда опознаем разложенные по папочкам компоненты системы: HAL лежит в папке cpu (и если мы её откроем, то увидим описания для десятков различных микроконтроллеров, от AVR до PIC32), описания построенных на этих контроллерах плат — boards, драйверы внешних устройств — drivers, ядро ОС — core, системные и вспомогательные сервисы ОС — sys, пользовательские приложения — examples.
Один из важных моментов, который отличает микроконтроллеры от больших систем — то, что практически всегда (а в нашем случае совсем всегда) пользовательские приложения существуют не как отдельные файлы, загружаемые независимо от ОС, а компилируются вместе с ОС, всем набором драйверов и модулей в единый файл, загружаемый в память микроконтроллера. Причин этому несколько — начиная с отсутствия необходимости в отдельной загрузке приложений, что позволяет упростить всю систему, и заканчивая наличием необходимости собирать ОС и комплект драйверов и модулей под конкретное устройство ради экономии его отнюдь не бесконечной памяти.
Исходные коды ОС
Мы будем работать с исходными кодами в версии https://github.com/unwireddevices/RIOT/tree/mirea — это ответвление от основной разработки RIOT OS, в котором силами Unwired Devices улучшена поддержка микроконтроллеров STM32L1, а также добавлены некоторые полезные сервисы, например, таймеры на базе часов реального времени, включая миллисекундный таймер.
Исходные коды можно загрузить с Github, выбрав кнопку «Clone/Download» и «Download ZIP», но лучшим вариантом будет создание собственного репозитория. Для этого зарегистрируйтесь на GitHub, после чего вернитесь в указанный выше репозиторий и нажмите кнопку «Fork» — исходные коды будут скопированы в ваш аккаунт, откуда вы сможете уже без проблем работать с ними.
Я не буду описывать здесь детали работы с GitHub и Git — в интернете есть масса отличных пошаговых руководств, повторять которые нет смысла.
Компиляция простейшего приложения
Благодаря тому, что ОС берёт на себя всё взаимодействие с микроконтроллером, простейшее возможное приложение в общем-то ничуть не сложнее, чем традиционный «Hello world» на большом ПК:
#include <stdio.h>
int main(void)
{
puts("Hello World!");
printf("You are running RIOT on a(n) %s board.n", RIOT_BOARD);
printf("This board features a(n) %s MCU.n", RIOT_MCU);
return 0;
}
В структуре нашей ОС это приложение располагается в папке example/hello-world в файле main.c (оно там уже есть).
Однако, очевидно, чтобы его скомпилировать, необходимо сначала настроить среду сборки. Это делается по-разному в разных ОС.
1. Windows 8 и старее. К сожалению, придётся использовать среду MinGW, медленную и неудобную. Процедура установки нужных компонентов достаточно подробно описана здесь. Отмечу, что для работы с Git/GitHub придётся также отдельно поставить Git for Windows, который притащит свою урезанную версию MinGW. При желании всё это можно свести в один терминал MinGW, но проблем с очень низкой скоростью работы MinGW и общим его неудобством это не решит.
В целом, Windows 7 и Windows 8, как можно понять, являются не самым удачным выбором для разработки.
2. Windows 10. Откройте магазин Microsoft Store, найдите в нём Ubuntu и установите. Если при первом запуске Ubuntu будет ругаться на выключенный компонент Windows, откройте системное приложение «Включение или отключение компонентов Windows», найдите там «Поддержка Windows для Linux» и включите.
Вся дальнейшая работа происходит в среде Ubuntu, значительно более комфортной и быстрой, нежели MinGW.
Скачайте компилятор и сопровождающие его утилиты отсюда (внимание: вам нужна 64-битная версия для Linux!), откройте Ubuntu, распакуйте архив и укажите системе пути к нему:
cd /opt
sudo tar xf /mnt/c/Users/vasya/Downloads/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:$PATH
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:$PATH
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:$PATH" >> ~/.bashrc
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:$PATH" >> ~/.bashrc
Последние две команды пропишут установку путей к компилятору и утилитам в файл .bashrc, так что вам не придётся вручную их устанавливать при каждом запуске Ubuntu. Обратите внимание на обратную дробь перед $ и двойную стрелку >> в конце — без первого путь будет записан некорректно, без второго (с одиночной стрелкой) вы сотрёте всё предыдущее содержимое .bashrc.
После этого выполнение в консоли команды arm-none-eabi-gcc —version должно сообщать, что такой компилятор есть, а его версия — 7.2.1 (на текущий момент).
Для работы с Git вам потребуется сгенерировать пару из приватного и публичного ключей командой ssh-keygen, после чего скопировать публичный ключ (в Ubuntu под Windows это можно сделать командой cat ~/.ssh/id_rsa.pub, потом выделить выведенное мышкой и нажать Enter — оно скопируется в буфер обмена) и добавить его в ваш аккаунт GitHub. После этого можно будет работать с GitHub из командной строки командой git.
NB: если вы ранее не работали в командной строке Linux, то обратите внимание на два полезных момента: курсорные стрелки вверх и вниз позволяют листать историю введённых команд, а клавиша Tab дополняет набранный вами путь к файлу или папке до конца (то есть cd /opt/gcc- превратится в строку cd /opt/gcc-arm-none-eabi-7-2017-q4-major). Последнее служит также хорошей проверкой, правильно ли вы набираете путь — если неправильно, дополнен он по очевидной причине не будет. Если возможных вариантов дополнения несколько, то двойное нажатие Tab выведет их все.
NB: в Windows вам будет удобнее работать, если сами исходные коды ОС размещаются в папке, напрямую доступной из Windows, например Documents/git/RIOT. Из-под MinGW она будет доступна по пути /c/Users/vasya/Documents/git/RIOT, из-под Ubuntu — /mnt/c/Users/vasya/Documents/git/RIOT. В этом случае вы сможете свободно пользоваться для работы с кодом, например, текстовыми редакторами, написанными для Windows, такими как Notepad++.
3. Linux. Установка среды сборки ничем не отличается от инструкции для Windows 10, кроме того, что Microsoft Store вам не потребуется. Также не ищите gcc-arm-none-eabi в репозитории вашего дистрибутива — скачайте наиболее свежую версию с его официального сайта.
После установки среды сборки откройте консоль, перейдите в папку с RIOT и в подпапку examples/hello-world, после чего запустите команду make.
Скорее всего, она быстро прервётся ошибкой и сообщением, что у вас не хватает unzip (под Windows 10 по умолчанию он не устанавливается), make или других утилит. В Windows 10 их можно установить командой (перечень недостающего даётся простым списком через пробел):
sudo apt-get install unzip make
После установки попробуйте ещё раз запустить make — точнее, оптимальным вариантом является вызов команды «make clean && make»: первая очищает мусор, оставшийся от предыдущей попытки. Без ней компилятор может ошибочно решить, что какой-то из уже собранных модулей не менялся, и не пересобирать его — в результате вы получите прошивку, собранную из кусков старого и нового кода.
NB: в оригинальном RIOT приложение hello-world собирается для архитектуры native, то есть, в нашем случае ноутбука или десктопа, x86. Однако в нашем коде в параметрах сборки проекта уже указана плата unwd-range-l1-r3, использующая контроллер stm32, поэтому в начале процедуры вы должны увидеть строку
Building application "mirea" for "unwd-range-l1-r3" with MCU "stm32l1".
В случае успеха за ней вы увидите десяток-два строчек, начинающихся с команды make — это сборка отдельных компонентов операционной системы. Закончится всё сообщением об успешном создании файла прошивки mirea.elf с указанием размеров различных типов данных (объёмов используемой флэш-памяти и ОЗУ).
Как-то вот так:
Итак, мы немного разобрались с тем, как выглядит микроконтроллер, скачали исходные коды нашей ОС, настроили среду сборки и убедились, что она работает.
На следующем занятии мы рассмотрим подробнее устройство микроконтроллера, начиная с портов GPIO, и загрузим в него первое приложение — оно, по старой традиции, будет мигать светодиодом — а далее вернёмся к операционной системе и внимательнее изучим, из каких компонентов она состоит и как настраивается её сборка.
P.S. И в качестве дополнения — живая 360-градусная запись лекции (запись семинаров не проводилась по понятной причине: «у доски» там говорится мало, значительная часть работы идёт уже с отдельными студентами, у которых что-то получается или не получается):