Text
                    С. Ю. ДОБДИН,
А. В. СКРИПАЛЬ

ОСНОВЫ ЦИФРОВОЙ
ЭЛЕКТРОНИКИ
И МИКРОПРОЦЕССОРНЫХ
СИСТЕМ:
ОТ ТЕОРИИ К ПРАКТИКЕ
УЧЕБНОЕ ПОСОБИЕ

САНКТ-ПЕТЕРБУРГ • МОСКВА • КРАСНОДАР
2026


УДК 621.38 ББК 32.85я73 Д 55 Добдин С. Ю. Основы цифровой электроники и микропроцессорных систем: от теории к практике : учебное пособие для вузов / С. Ю. Добдин, А. В. Скрипаль. — Санкт-Петербург : Лань, 2026. — 340 с. : ил. — Текст : непосредственный. ISBN 978-5-507-53863-8 В учебном пособии подробно изложены теоретические основы электроники, электронных устройств и микропроцессорных систем. Рассмотрены основные определения и вопросы, которые касаются проектирования схем с помощью элементов аналоговой и цифровой электроники. Особое внимание уделено изучению устройства микропроцессора и микропроцессорных систем. В приложении представлено несколько разделов по программированию микроконтроллеров, контроллеров и микрокомпьютеров. Для программирования последних использован высокоуровневый язык программирования Python. Для закрепления изученного материала приведены лабораторные практикумы, которые выполняются на компьютере и с использованием реальных устройств. Предназначено для студентов, аспирантов и преподавателей инженерных и естественно-научных специальностей, интересующихся аналого-цифровой схемотехникой и программированием микропроцессорных систем. Издание предназначено для изучения следующих дисциплин: «Основы аналого-цифровой схемотехники», «Микропроцессорные системы», «Программирование микроконтроллеров» и «Автоматизированные системы в научных исследованиях». УДК 621.38 ББК 32.85я73 Обложка П. И. ПОЛЯКОВА © Издательство «Лань», 2026 © С. Ю. Добдин, А. В. Скрипаль, 2026 © Издательство «Лань», художественное оформление, 2026
ОГЛАВЛЕНИЕ Предисловие ............................................................................................................... 8 Глава 1. Основы электроники .............................................................................. 10 1.1. Электронная природа атома, изотопы и ионы, статическое электричество ...................................................... 10 1.2. Электрические величины: напряжение, ток, мощность и закон Ома ........ 13 1.3. Электрические цепи и их виды ...................................................................... 14 1.4. Элементы электрических цепей .................................................................... 15 1.4.1. Резисторы при параллельном и последовательном подключении ...... 15 1.4.2. Конденсаторы при параллельном и последовательном подключении .................................................................... 18 1.4.3. Индуктивность .......................................................................................... 20 1.4.4. Преобразователь напряжения (трансформатор) .................................... 21 1.4.5. Другие пассивные элементы .................................................................... 21 1.4.6. Элементы индикации (светодиоды и индикаторы) ............................... 22 1.5. Полупроводниковая электроника .................................................................. 25 1.5.1. Интегральные микросхемы ...................................................................... 25 1.5.2. Полупроводниковая электроника ............................................................ 27 1.5.3. Проводники p-типа и n-типа .................................................................... 29 1.5.4. Диод ............................................................................................................ 30 1.5.5. Транзистор ................................................................................................. 32 1.6. Системы проектирования, моделирования и прототипирования электрических схем ............................................................ 36 1.6.1. Проектирование схем в программе Multisim ......................................... 36 1.6.2. Разработка печатных плат в программе Ultiboard ................................. 54 Глава 2. Аналоговая схемотехника ..................................................................... 62 2.1. Проектирование аналоговых фильтров ........................................................ 62 2.1.1. Фильтр нижних частот ............................................................................. 63 2.1.2. Фильтр верхних частот ............................................................................. 64 2.1.3. Полосовой частотный RC-фильтр ........................................................... 65 2.1.4. Мост Вина — Робинсона.......................................................................... 65 2.2. Проектирование схем на операционных усилителях .................................. 66 2.2.1. Инвертирующий усилитель ..................................................................... 69 2.2.2. Неинвертирующий усилитель ................................................................. 69 2.2.3. Сумматор на операционном усилителе .................................................. 70 2.2.4. Интегратор на операционном усилителе ................................................ 71 2.2.5. Дифференциатор на операционном усилителе ...................................... 71 Глава 3. Цифровая схемотехника ........................................................................ 73 3.1. Физические основы работы устройств ......................................................... 73 3.2. Триггеры........................................................................................................... 78 3.3. Дешифраторы и шифраторы .......................................................................... 80 3
3.4. Мультиплексоры ............................................................................................. 82 3.5. Сумматоры ....................................................................................................... 84 3.6. Регистры ........................................................................................................... 86 3.7. Счетчики .......................................................................................................... 87 3.8. Аналого-цифровой преобразователь ............................................................. 90 3.9. Цифро-аналоговый преобразователь ............................................................ 94 Глава 4. Микропроцессорные системы .............................................................. 96 4.1. Построение микропроцессорных систем ...................................................... 96 4.1.1. Микропроцессор и микропроцессорные системы ................................. 96 4.1.2. Классическая и шинная структура связей .............................................. 98 4.1.3. Режимы работы микропроцессорных систем ...................................... 100 4.1.4. Архитектура микропроцессорных систем ............................................ 101 4.2. Передача информации в микропроцессорных системах .......................... 102 4.2.1. Шины микропроцессорных систем ....................................................... 102 4.2.2. Циклы программного обмена информацией ........................................ 104 4.2.3. Циклы обмена информацией по прерываниям .................................... 105 4.2.4. Циклы обмена информацией в режиме ПДП ....................................... 107 4.3. Функции устройств магистрали .................................................................. 108 4.3.1. Функции процессора............................................................................... 108 4.3.2. Функции памяти ...................................................................................... 110 4.3.3. Функции устройств ввода/вывода ......................................................... 112 4.4. Адресация операндов .................................................................................... 113 4.4.1. Методы адресации .................................................................................. 113 4.4.2. Сегментирование памяти ....................................................................... 115 4.4.3. Адресация байтов и слов ........................................................................ 115 4.5. Система команд процессора ........................................................................ 116 4.5.1. Команды пересылки данных .................................................................. 116 4.5.2. Арифметические команды ..................................................................... 117 4.5.3. Логические команды............................................................................... 117 4.5.4. Команды переходов ................................................................................ 118 4.5.5. Быстродействие процессора .................................................................. 119 Глава 5. Программирование микроконтроллеров ......................................... 120 5.1. Архитектура микроконтроллеров................................................................ 120 5.1.1. Процессорное ядро ................................................................................. 121 5.1.2. Организация памяти ............................................................................... 122 5.2. Порты ввода/вывода...................................................................................... 123 5.2.1. Регистры PORTA и TRISA ..................................................................... 124 5.3. Таймеры в микроконтроллерах (TMR0, TMR1, TMR2) ............................ 129 5.3.1. TMR0 и сторожевой таймер ................................................................... 129 5.3.2. Таймер TMR1 .......................................................................................... 132 5.3.3. Таймер TMR2 .......................................................................................... 135 5.4. Модуль широтно-импульсной модуляции (CCP) ...................................... 136 5.4.1. Режим захвата .......................................................................................... 137 5.4.2. Режим сравнения ..................................................................................... 138 4
5.4.3. Режим ШИМ ............................................................................................ 139 5.5. Аналоговый компаратор ............................................................................... 140 5.6. Модуль аналого-цифрового преобразователя (ADC)................................ 143 5.6.1. АЦП последовательного приближения ................................................ 143 5.6.2. Модуль АЦП в микроконтроллерах PIC .............................................. 145 5.7. Универсальный синхронно-асинхронный приемопередатчик (USART) ............................................................................... 148 5.8. Память данных EEPROM ............................................................................. 151 5.9. Тактовый осциллятор.................................................................................... 153 5.10. Основы языка программирования Си для микроконтроллеров ............. 156 5.11. Компилятор mikroC PRO для PIC-микроконтроллеров .......................... 160 5.11.1. Компилятор mikroC PRO для программирования PIC ...................... 161 5.11.2. Создание нового проекта и компиляция программы в mikroC PRO ....................................................... 166 5.11.3. Программатор K150. Программная часть программатора microbrn ................................................. 170 5.12. Среда программирования MPLAB IDE и программатор Pickit для PIC-микроконтроллеров ........................................ 173 5.12.1. Среда программирования MPLAB IDE для программирования PIC .............................................................................. 174 5.12.2. Создание нового проекта и компиляция программы в MPLAB IDE ....................................................... 175 5.12.3. Программатор PICkit. Программная часть программатора PICkit ..................................................... 179 5.13. Практические работы .................................................................................. 183 5.13.1. Практическая работа № 1. Программирование портов..................... 183 5.13.2. Практическая работа № 2. Использование таймера .......................... 185 5.13.3. Практическая работа № 3. Использование сторожевого таймера ... 187 5.13.4. Лабораторная работа № 4. Модуль CCP как ШИМ-генератор ........ 189 5.13.5. Практическая работа № 5. Изучение работы аналогового компаратора ................................................................................. 192 5.13.6. Практическая работа № 6. Использование аналого-цифрового преобразователя .............................................................. 195 5.13.7. Практическая работа № 7. Последовательная связь (RS232) ........... 197 5.13.8. Практическая работа № 8. Использование памяти EEPROM .......... 200 5.13.9. Практическая работа № 9. Генерация звука с помощью МК ........... 202 5.13.10. Лабораторная работа № 10. Сопряжение МК с аналоговым датчиком ............................................................................. 205 Глава 6. Программирование контроллеров .................................................... 208 6.1. Применение контроллеров Arduino............................................................. 208 6.1.1. Применение контроллеров для разработки электроники ................... 208 6.1.2. История создания контроллера Arduino ............................................... 209 6.1.3. Основные характеристики контроллера Arduino UNO ....................... 211 6.2. Создание программ в среде разработки Arduino IDE................................ 212 6.2.1. Среда разработки Arduino IDE .............................................................. 213 5
6.2.2. Подключение Arduino UNO и запуск IDE ............................................ 214 6.2.3. Анализ тестовой программы для мигания светодиода ....................... 217 6.2.4. Основы программирования C/C++ для Arduino .................................. 219 6.3. Особенности архитектуры контроллера Arduino ....................................... 225 6.3.1. Цифровые порты и широтно-импульсная модуляция Arduino UNO ......................................... 225 6.3.2. Аналоговые порты и подключение датчиков ...................................... 229 6.3.3. Использование элементов мехатроники ............................................... 232 6.3.4. Последовательная асимметричная шина I2C........................................ 234 6.3.5. Последовательная синхронная шина SPI ............................................. 238 6.3.6. Справочник основных функций для Arduino ....................................... 242 6.4. Практические работы .................................................................................... 246 Практическая работа № 1. Подключение светодиода ................................... 246 Практическая работа № 2. Подключение кнопки .......................................... 248 Практическая работа № 3. Схемы на основе счета ....................................... 249 Практическая работа № 4. Подключение датчиков ...................................... 252 Практическая работа № 5. Мехатронный модуль ......................................... 253 Практическая работа № 6. Подключение дисплея ........................................ 255 Практическая работа № 7. Схема звукового генератора .............................. 258 Практическая работа № 8. Управление схемой через USB .......................... 259 Практическая работа № 9. Передача данных по I2C ..................................... 262 Практическая работа № 10. Передача данных по SPI ................................... 265 Глава 7. Программирование микрокомпьютеров .......................................... 269 7.1. Особенности микрокомпьютеров Raspberry Pi .......................................... 269 7.1.1. История создания микрокомпьютера ................................................... 269 7.1.2. Технические характеристики и возможности ...................................... 270 7.1.3. Настройка операционной системы Raspbian ........................................ 271 7.2. Основы программирования на языке Python.............................................. 276 7.2.1. Программное обеспечение для работы с Python ................................. 276 7.2.2. Целые числа, ввод/вывод, простые операции со строками ................ 278 7.2.3. Вещественные числа и операции над ними ......................................... 280 7.2.4. Условный оператор, цикл while и цикл for .......................................... 282 7.2.5. Кортежи, списки и их сортировка ......................................................... 286 7.2.6. Множества и словари ............................................................................. 288 7.2.7. Функции ................................................................................................... 290 7.2.8. Исключения try-except-finally ................................................................ 291 7.2.9. Библиотеки numpy, matplotlib, pandas................................................... 292 7.3. Практические работы .................................................................................... 297 Практическая работа № 1. Подключение светодиода ................................... 297 Практическая работа № 2. Подключение кнопки .......................................... 299 Практическая работа № 3. Подключение зуммера ........................................ 301 Практическая работа № 4. Измерение напряжения ...................................... 302 Практическая работа № 5. Измерение температуры ..................................... 305 Практическая работа № 6. Измерение интенсивности света ....................... 306 Практическая работа № 7. Широтно-импульсная модуляция ..................... 308 6
Практическая работа № 8. Подключение сервопривода .............................. 310 Практическая работа № 9. Подключение шагового двигателя .................... 312 Практическая работа № 10. Последовательная связь (UART) ..................... 314 Практическая работа № 11. Исследование интерфейса I2C ......................... 318 Практическая работа № 12. Исследование интерфейса SPI ......................... 321 Практическая работа № 13. Сопряжение Arduino и Raspberry Pi ................ 324 Практическая работа № 14. Построение системы контроля освещенности .................................................................................... 326 Практическая работа № 15. Система температурного контроля ................. 328 Практическая работа № 16. Создание Telegram-бота ................................... 331 Заключение ............................................................................................................. 335 Дополнительная литература ............................................................................... 336 7
ПРЕДИСЛОВИЕ Предлагаемое учебное пособие позволяет изучить основы цифровой электроники и микропроцессорных систем. В учебном пособии представлено 7 глав. В первой главе рассмотрены основы электроники, представлены основные базовые электронные устройства. Показана возможность применения современных систем проектирования аналоговых и цифровых схем. Во второй главе более подробно рассмотрены основные аспекты аналоговой схемотехники, в приложении фильтров разных частотных диапазонов рассмотрены базовые схемы устройств на операционных усилителях. Третья глава полностью посвящена изучению основ цифровой схемотехники: от физических основ работы устройств до реализации сложных схем аналого-цифрового преобразования. В четвертой главе рассмотрена теория работы современных микропроцессорных систем. Показано устройство микропроцессора. Обсуждается использование в системах памяти и устройств ввода/вывода. Основная часть посвящена изучению именно внутренней структуры процессора. В пятой главе рассматривается внутреннее устройство микроконтроллеров на примере 8-битных микроконтроллеров PIC. Подробно обсуждается программирование микроконтроллеров с помощью программы MikroC и MPLAB IDE. В завершение рассмотрены возможности физического программирования устройств с использованием специальных программаторов. Глава содержит блок с практическими работами для закрепления изученного материала. В шестой главе представлено описание популярного контроллера Arduino. В приложении к контроллеру рассмотрено использование основных периферийных устройств. Приведены основные конструкции языка программирования, который используется при настройке устройств. Глава содержит блок с практическими работами для закрепления изученного материала. В седьмой главе подробно рассмотрены особенности построения микрокомпьютеров Raspberry Pi. Для программирования устройства используется высокоуровневый язык программирования Python и его основные приложения, в том числе библиотека GPIO. В завершение представлен блок с практическими работами для закрепления изученного материала. Для углубленного изучения рассматриваемых разделов, в конце представлен список литературы отечественных и зарубежных авторов, которые считаются признанными авторитетами в своей области знаний. Все предлагаемые программы с описанием можно скачать на сайтах github.com и gitverse.ru. Запуск и работоспособность программ полностью определяется версией ПО и библиотек, с помощью которых они были созданы: – https://github.com/mculab64/electronics_course; – https://gitverse.ru/mculab64/electronics_course. Дополнительный материал курса доступен на сайте https://elteha.ru/. 8
В результате освоения дисциплины студенты будут: 1) знать основы теории цифровой электроники и микропроцессорных систем, программы и инструменты для проектирования аналоговых и цифровых схем; 2) уметь выполнять отладку созданных и запрограммированных микропроцессорных устройств, выполнять отладку программ, созданных на основе высокоуровневых языков программирования C++ и Python; 3) владеть навыками разработки новых устройств, использующих современные архитектуры микропроцессорных систем для микроконтроллеров, контроллеров и микрокомпьютеров. 9
ГЛАВА 1 ОСНОВЫ ЭЛЕКТРОНИКИ 1.1. Электронная природа атома, изотопы и ионы, статическое электричество Модели атома. До конца XIX в. предполагалось, что материя состоит из маленьких неделимых частиц, называемых атомами. Работы Джозефа Джона Томпсона, Эрнеста Резерфорда и Нильса Бора доказали, что атомы представляют собой сложные структуры, содержащие положительные и отрицательные частицы. Д. Д. Томпсон Э. Резерфорд Н. Бор Положительные назывались протонами, а отрицательные — электронами. Было предложено несколько моделей атома. Модель Томпсона предполагала, что внутри атома находится равное количество протонов и электронов, и что эти элементы рассеяны случайным образом, как это показано на рисунке 1.1а. В 1913 г. Резерфорд доказал экспериментально, что атомы содержат тяжелое центральное положительное ядро с электронами, рассеянными случайным образом. Можно сказать, что Резерфорд получил усовершенствованную модель, которую ранее предложил Томпсон. Модель Резерфорда представлена на рисунке 1.1б. Наконец, Бор выдвинул теорию, что электроны имеют разные уровни энергии, как если бы они двигались вокруг ядра по разным орбитам, напоминая движение планет вокруг Солнца. Модель Бора представлена на рисунке 1.1в. Исследования также показали, что атом электрически нейтрален, состоит из протона и электронов. Протоны — это положительно заряженные частицы, которые имеют массу 1,673  10–24 г. Электроны — это отрицательно заряженные частицы, которые имеют массу 9,109  10–28 г. Современное представление атома основано на квантово-механическом представлении. Отличие данной модели от модели Бора заключается в том, что электроны движутся не по конкретным траекториям, а находятся на определенной электронной оболочке, описываемой квантовой механикой. Число прото10
нов в атоме определяет его атомный номер. Например, атом водорода имеет один протон и атомный номер 1, гелий имеет 2 протона, углерод имеет 6 протонов. Если сравнить отношение массы к электрическому заряду в разных атомах, то можно обнаружить, что ядро должно состоять из большего количества протонов. Например, ядро гелия имеет в два раза больший заряд, чем ядро водорода, но в четыре раза большую массу. а б Рис. 1.1 Модели атомов в Дополнительная масса объясняется тем, что в ядре есть еще одна частица, называемая нейтроном, которая имеет такую же массу, как и протон, но не имеет электрического заряда. На рисунке 1.2 показана модель атома гелия с двумя протонами, двумя электронами и двумя нейтронами. Рис. 1.2 Модель атома гелия Изотопы и ионы. На самом деле количество протонов и электронов в атоме может не соответствовать друг другу. В нейтральном атоме число протонов в атомном ядре точно соответствует числу электронов, число протонов не обязательно должно соответствовать числу нейтронов. Например, большинство атомов водорода имеют один протон, но не имеют нейтронов, в то время как небольшой процент имеет один нейтрон, а еще меньший процент имеет два нейтрона. В этом смысле атомы элемента, которые содержат разное число нейтронов, являются изотопами элемента; например, вода (H2O), содержащая атомы водорода с двумя нейтронами (дейтерий), называется «тяжелой водой». Атом, который заряжен из-за избытка или недостатка электронов, называется ионом. Если исключить несколько электронов, атом принимает положительный 11
заряд. В этом случае он называется положительным ионом. Когда свободный электрон соединяется с нормальным атомом, тогда он называется отрицательным ионом. Статическое электричество. Свободные электроны могут перемещаться в веществе или на поверхности. Когда электроны находятся на поверхности, то поверхность имеет статический электрический заряд, который может быть положительным или отрицательным. Когда электроны движутся потоком, мы называем это движение электрическим током. Электроны могут быть удалены с поверхности посредством трения, тепла, света или химической реакции. В этом случае поверхность становится положительно заряженной. Древние греки обнаружили, что при трении янтаря шерстью янтарь становится электрически заряженным и будет притягивать небольшие кусочки материала. В этом случае заряд положительный. Трение может привести к тому, что другие материалы, такие как твердая резина или пластик, станут отрицательно заряженными. Наблюдая за объектами, имеющими положительные и отрицательные заряды, можно заметить, что одноименные заряды отталкиваются, а разноименные притягиваются, как показано на рисунке 1.3. Рис. 1.3 Взаимодействие электрических зарядов Трение приводит к переносу слабо удерживаемых электронов с одной поверхности на другую. Это приводит к появлению отрицательного заряда на поверхности, которая приобрела электроны, и положительного заряда на поверхности, которая потеряла электроны. Электроны могут постепенно утекать. Если электрический заряд продолжает накапливаться, он в конечном итоге достигает момента, когда заряд больше невозможно удерживать. В этом случае он разряжается по любому доступному пути, как, например, это происходит в случае с электрической молнией. Статическое электричество не перемещается из одного места в другое. Статическое электричество не может выполнять постоянную работу. Электрический заряд. Очень часто в области физики ученые используют модели и теории, чтобы описать и представить некоторую силу взаимодействия, как, например, взаимодействие заряженных тел. Тела, имеющие электрический заряд, оказывают измеримые силы друг на друга. Термин «электрический заряд» был придуман для объяснения этих наблюдений. Электрический заряд существует и может быть измерен. Заряд измеряется в кулонах (в системе СИ — Кл, на англ. C), единице, названной в честь французского ученого Шарля Огюстена Кулона. Один кулон [1 Кл] — это заряд, который проходит за 1 с че12
рез поперечное сечение проводника при силе тока 1 А. Минимальный элементарный электрический заряд имеет значение –1,6  10–16 Кл. Заряд может быть положительным или отрицательным. Заряд не может быть ни создан, ни уничтожен. Если два объекта с равным количеством положительного и отрицательного заряда объединить на каком-либо объекте, то полученный объект будет электрически нейтральным и иметь нулевой суммарный заряд. 1.2. Электрические величины: напряжение, ток, мощность и закон Ома Напряжение. Напряжение — это энергия (или работа), которая требуется для перемещения единичного заряда из точки с низким потенциалом в точку с более высоким потенциалом. Очень часто напряжение называют разностью потенциалов или электродвижущей силой (ЭДС). Единицей измерения напряжения является вольт (в системе СИ — В, на англ. V). Обозначается в формулах и на схемах буквой U. Единица названа в честь итальянского ученого Алессандро Вольта. Для расчета напряжения можно использовать формулу U = A/q, где [U] = 1 В = 1 Дж/1 Кл. Напряжение всегда измеряется между двумя точками. Для сравнения напряжений нескольких заряженных тел необходима общая точка отсчета. Эту точку обычно называют «землей». Ток. Электрический заряд способен осуществлять движение в некоторых материалах. Если материал проводит ток, то его называют проводником, если не проводит, то изолятором. Металлы являются хорошими проводниками, в то время как стекло, пластик и резина являются изоляторами. Кроме того, существует третья категория материалов, называемых полупроводниками (кремний и германий). Обсуждению полупроводников будет посвящен отдельный раздел. Электрический ток — это направленное движение заряженных частиц. Очень часто понятие электрический ток связывают с силой тока, которая показывает, какое количество зарядов проходит через поперечное сечение проводника за единицу времени. Единицей измерения напряжения является ампер (в системе СИ — А, на англ. A). Обозначается в формулах и на схемах буквой I. Единица названа в честь французского ученого Андре-Мари Ампера. Для расчета силы тока можно использовать формулу I = q/t, где [I] = 1 А = 1 Кл/1 c. Мощность. Ток, протекающий через проводник, производит тепло. Тепло является результатом преобразования энергии, которой обладает движущийся заряд. Работа, необходимая для производства этого тепла, является электрической мощностью. Единицей измерения мощности является ватт (в системе СИ — Вт, на англ. W). Обозначается в формулах и на схемах буквой P. Единица названа в честь английского ученого Джеймса Уатта. Для расчета электрической мощности можно использовать формулу P = A/t, где [P] = 1 Вт = 1 Дж/1 с. Сопротивление. Еще одной важной характеристикой проводников является сопротивление. Сопротивление — физическая величина, которая препятствует прохождению электрического тока через проводник. Единицей измерения сопротивления является Ом (в системе СИ — Ом, на англ. Ohm). Обозначается в формулах и на схемах буквой R. Единица названа в честь немецкого ученого Ге13
орга Симона Ома. Для расчета сопротивления можно использовать формулу R = = (l/S), где [R] = 1 Ом, где  — удельное сопротивление проводника; l — длина проводника (м); S — площадь поперечного сечения проводника (м2). А. Вольта А.-М. Ампер Д. Уатт Г. С. Ом Закон Ома. Рассмотрим еще одну важную особенность, которая свидетельствует о существовании взаимосвязи между напряжением, током и мощностью. Очень часто данная связь описывается через напряжение, ток и сопротивление. Выражение, которое показывает связь рассматриваемых величин, называется законом Ома. Закон можно сформулировать следующим образом. Сила тока на участке электрической цепи прямо пропорциональна напряжению и обратно пропорциональна сопротивлению проводника. В этом случае U — напряжение, I — сила тока, а R — сопротивление в цепи. Соотношение, которое связывает величины: I = U / R. Напряжение в законе Ома относится к напряжению на резисторе, другими словами, к напряжению между двумя точками проводника. На рисунке 1.4 показана пирамида закона Ома и соотношения, позволяющие рассчитать значения силы тока, напряжения и сопротивления. U=IR а I=U/R б Рис. 1.4 Пирамида закона Ома: R=U/I в а — расчет напряжения; б — расчет силы тока; в — расчет сопротивления. 1.3. Электрические цепи и их виды Принято разделять электрические цепи на разные группы. По типу тока существуют цепи постоянного и переменного тока (однофазные и многофазные). По уровню тока и напряжению: слабо- и сильноточные, низкого и высокого напряжения. По сложности бывают неразветвленные и разветвленные цепи. Если в цепи присутствуют нелинейные элементы, то такие цепи называют 14
нелинейными. По наличию источников энергии: активные и пассивные. При использовании различных элементов: аналоговые и цифровые. Про аналоговую и цифровую схемотехнику будет подробно рассказано в следующих главах. Необходимо отметить различие схем по типу соединений: последовательного, параллельного и смешанного типа. а б в Рис. 1.5 Типы соединений электрических цепей: а — последовательное; б — параллельное; в — смешанное. Рассмотрим различные виды соединения электрических цепей: последовательное, параллельное и смешанное соединения. На рисунке 1.5 показаны электрические схемы с использованием последовательного, параллельного и смешанного типа подключений. При последовательном соединении все элементы цепи соединены последовательно. Ток в данном случае протекает через каждый элемент. Параллельное соединение характеризуется тем, что элементы имеют подключение к одним и тем же узлам, а напряжение на них одинаковое. Смешанный тип соединения характеризуется использованием двух вышеуказанных методов. Количество узлов с параллельным и последовательным подключением может быть разным. Особый интерес представляет последовательное и параллельное подключения резисторов и конденсаторов, которые будут рассмотрены далее. 1.4. Элементы электрических цепей 1.4.1. Резисторы при параллельном и последовательном подключении Резистор — это пассивный элемент в электрических схемах, имеющий определенный уровень электрического сопротивления. Его основная функция связана с ограничением силы тока в цепи, а также поглощением и перераспределением электрической энергии. Резисторы могут быть использованы в различных электронных устройствах. На рисунке 1.6 представлены примеры серийно выпускаемых резисторов с разными номиналами. Величина тока, проходящего через металлический проводник или любой другой материал с определенной проводимостью, пропорциональна напряжению, приложенному к этому проводнику. Обычно проводники, применяемые в электрических схемах, имеют большое сечение, чтобы пренебречь падением напряжения. Резисторы изготавливаются из проводящего материала, такого как 15
графит или тонкая металлическая пленка, обладающего невысокой проводимостью. Каждый конец резистора соединен с металлическим проводником. Рис. 1.6 Резисторы разного номинала и мощности, графическое обозначение на схемах Типы резисторов. Сопротивление резистора R измеряется в Ом. Наиболее распространенные типы резисторов имеют сопротивление от 1 Ома (1 Ом) до 22 мегаом (22 МОм). Все резисторы имеют определенные характеристики. Важным параметром является рассеиваемая мощность. Наиболее распространены резисторы с мощностью рассеяния 0,25–2 Вт. Дополнительными характеристиками резистора являются точность, температурный коэффициент, уровень шума, коэффициент напряжения (зависимость сопротивления от приложенного напряжения) и индуктивность. По типу сопротивления резисторы бывают постоянные, переменные (потенциометры) и подстроечные. Резисторы могут изменять свое сопротивление в зависимости от внешнего воздействия. Существуют резисторы, которые изменяют сопротивление при воздействии разных температур (терморезисторы, термопара) и света (фоторезисторы). Номинал и допуск точности резистора. Для определения номинала резистора можно воспользоваться специальной таблицей, которая позволяет сделать это по цвету полос на корпусе. Используется несколько цветовых кодов, наиболее распространенными являются 4-полосный и 5-полосный коды. В 4-полосном коде первые две полосы представляют величину сопротивления, третья полоса является множителем для этого значения, а четвертая кодирует допуск погрешности. В 5-полосном коде первые три полосы представляют величину, четвертая служит множителем, а пятая — допуск погрешности. Для определения номинала резистора, вопервых, нужно определить количество полос. Затем перейдите к определению диапазона допуска, который обычно бывает золотым или серебряным. Начиная с противоположного конца, считайте две или три полосы величины и умножьте это значение на диапазон множителя. Например, резистор с четырьмя цветными полосами: красной, оранжевой, коричневой и золотой — это резистор 230 Ом с допуском погрешности 5%. Последовательное и параллельное соединение резисторов. В электрических схемах используется последовательное и параллельное подключение резисторов. Сопротивление n последовательно соединенных резисторов равно Rобщ = R1 + R2 + ... + Rn. 16
Цвет Черный Коричневый Красный Оранжевый Желтый Зеленый Голубой Фиолетовый Серый Белый Золотой Серебристый Значение 0 1 2 3 4 5 6 7 8 9 Множитель 1 10 100 1K 10K 100K 1M 10M Допуск 0,1 0,01 5% 10% 1% 2% 0,5% 0,25% 0,10% 0,05% Рис. 1.7 Цветовая маркировка резисторов Общее сопротивление всегда будет больше значения номинала резистора, если рассматривать их по отдельности. Сопротивление n параллельно соединенных резисторов равно: Rобщ = R1  R2    Rn R1 + R2 +  + Rn или Rобщ = 1 . 1 1 1 + +  + R1 R2 Rn При параллельном сопротивлении общее значение сопротивления всегда меньше, чем при последовательном соединении. На рисунке 1.8 показана схема соединения двух резисторов при последовательном и параллельном подключении. 17
а б Рис. 1.8 Последовательное и параллельное подключение резисторов: а — последовательное; б — параллельное. Делители напряжения. Делитель напряжения — это схема, которая для данного напряжения на входе создает на выходе напряжение, которое является некоторой частью входного. Для расчета значения выходного напряжения можно воспользоваться формулой (без нагрузки): U вых = I  R2 = U вх  R2 . ( R1 + R2 ) На рисунке 1.9 представлена схема делителя напряжения с использованием двух резисторов. Рис. 1.9 Схема делителя напряжения на двух резисторах Выходное напряжение практически всегда будет меньше или равно входному напряжению. Если резистор R2 заменить потенциометром, то можно получить регулируемый делитель напряжения в заданном диапазоне. 1.4.2. Конденсаторы при параллельном и последовательном подключении Конденсатор — это пассивный элемент в электрических схемах, имеющий два полюса с постоянным или переменным значением емкости, обладающий малой проводимостью. Конденсатор можно использовать для накопления заряда и энергии электрического поля. Говорят, что конденсатор имеет емкость (или электроемкость) C = Q / U, где [С] = 1 Ф = 1 Кл/1 В (фарад, в системе СИ — Ф, на англ. F). Емкость определяется способностью накапливать заряд на пластинах конденсатора, к которым прикладывается напряжение U. В конденсаторе ток пропорционален скорости изменения напряжения. Сила тока может быть определена по следующей формуле: Iс = C  18 dU . dt
Если напряжение на конденсаторе, имеющем емкость 1 Ф, изменится на 1 В за 1 с, то ток будет 1 А. И наоборот, протекание тока 1 А через конденсатор емкостью 1 Ф вызывает изменение напряжения на 1 В за 1 с. Емкость, равная одной фараде, — очень большое значение. По этой причине чаще используют микрофарады (мкФ) или пикофарады (пФ). На рисунке 1.10 представлены примеры серийно выпускаемых конденсаторов с разной емкостью и их графическое обозначение на электрических схемах. Рис. 1.10 Примеры конденсаторов и их графическое обозначение на схемах Типы конденсаторов. Промышленность производит конденсаторы разных форм и размеров. Простейший конденсатор состоит из двух проводников, расположенных на небольшом расстоянии друг от друга. Для получения большей емкости нужны большая площадь и минимальный зазор между проводниками. Обычно один из проводников покрывают тонким слоем изолирующего материала (диэлектрика). Существуют различные типы конденсаторов: керамические, электролитические (из металлической фольги с оксидной пленкой в качестве изолятора) и слюдяные (из металлизированной слюды). Последовательное и параллельное соединение конденсаторов. В электрических схемах используется последовательное и параллельное соединение конденсаторов. Емкость последовательно n соединенных конденсаторов равна Собщ = 1 . 1 1 1 + +  + С1 С2 Сn При параллельном соединении общая емкость будет складываться из емкостей отдельных элементов. Общая емкость всегда будет больше значения емкости, если рассматривать их по отдельности. Емкость n параллельно соединенных конденсаторов равна Собщ = С1 + С2 + ... + Сn. На рисунке 1.11 показана схема соединения двух конденсаторов при последовательном и параллельном соединении. 19
а б Рис. 1.11 Последовательное и параллельное подключение конденсаторов: а — последовательное; б — параллельное. 1.4.3. Индуктивность Индуктивность — это пассивный элемент в электрических схемах, характеризующий магнитные свойства в электрической цепи. Индуктивность можно использовать для накопления энергии магнитного поля, при условии, что через элемент протекает электрический ток. Говорят, что индуктивность имеет магнитный поток, сцепленный с контуром Ф = LI, где [L] = 1 Гн = 1 Вб/1 А (генри, в системе СИ — Гн, на англ. Н). Скорость изменения силы тока будет зависеть от приложенного напряжения. Напряжение может быть определено по следующей формуле: Ui = L  dI . dt На рисунке 1.12 представлены примеры серийно выпускаемых дросселей (катушек индуктивности) с разной величиной индуктивности и их графическое обозначение на электрических схемах. Обозначение зарубежное Обозначение отечественное Рис. 1.12 Примеры катушек индуктивности и их графическое обозначение на схемах Условно индуктивность можно представить в виде нескольких намотанных витков металлического (медь, алюминий или другой проводящий материал) провода. Если же рассматривать более сложные конструкции, то в них добавляют сердечник, позволяющий изменить индуктивность катушки. В качестве сердечника могут использовать металлический и ферритовый тор, цилиндр или брусок. Индуктивность находит широкое применение в электрических схемах в качестве дросселей, позволяющих выполнять фильтрацию сигнала, и в схемах резонанса. Компоновка дросселей позволяет получить более сложные технические элементы, например трансформатор. 20
1.4.4. Преобразователь напряжения (трансформатор) Трансформатор — это индуктивное устройство, которое может изменять уровни напряжения или тока. Типичный трансформатор имеет две или более обмоток, намотанных вокруг сердечника. Очень часто сердечник изготавливают из последовательно сложенных вместе металлических пластин железа. Одна из обмоток, называемая первичной, получает колеблющийся ток. Другая обмотка, называемая вторичной, производит ток, индуцированный первичной. На рисунке 1.13 показана схема трансформатора. Рис. 1.13 Схематичное изображение трансформатора Трансформатор может выполнять функцию повышения или понижения напряжения. Это определяется числом обмоток в первичной и вторичной катушках. Соотношение числа витков в каждой обмотке определяет изменение напряжения. Трансформатор с равным числом витков в первичной и вторичной обмотках передает ток без изменений. Этот тип устройства иногда называют изолирующим трансформатором. Трансформатор с меньшим числом витков во вторичной обмотке, чем в первичной, является понижающим трансформатором, и его задача заключается в снижении первичного напряжения на вторичной обмотке. Примером может служить катушка зажигания в автомобиле, которую можно представить в виде трансформатора, позволяющего преобразовать низкое напряжение аккумулятора в высокое напряжение, необходимое для образования искры. 1.4.5. Другие пассивные элементы В заключение данного раздела давайте рассмотрим еще несколько пассивных элементов, которые еще очень часто называют электромеханическими элементами. Реализация полноценных электрических схем без этих элементов была бы затруднительна. Переключатели. Данные элементы предназначены для изменения логики работы электрических цепей. Они имеют достаточно простое исполнение в виде переключаемой контактной группы. Важной характеристикой переключателей является эффект дребезга контактов. В схемах необходимо использовать элементы, для которых данный эффект будет оказывать минимальное влияние на схему, так как возникновение лишних помех может быть не только причиной шума, но и причиной выхода из строя других электрических элементов. Тумблеры. Существуют различные типы тумблеров. Обычно в схемах используются одно-, двух- и трехпозиционные переключатели. В последнем случае мы можем использовать среднее положение, которое будет соответствовать состоянию разъединения контактов «разомкнут». Устройства могут одновременно переключать до четырех возможных контактных групп одновременно. 21
Кнопочные переключатели. Данный вид переключателей позволяет обеспечить мгновенный контакт. Кнопочные переключатели бывают двух видов: нормально разомкнутые (разомкнут по умолчанию) и нормально замкнутые (замкнут по умолчанию). Они всегда работают по принципу «разомкнутзамкнут». Достаточно популярно использование кнопок с фиксирующим положением механизма переключения. Поворотные переключатели являются более сложной реализацией схемы переключения, способными использовать промежуточные положения. Реле. Данный тип устройств является управляемым переключателем. Схематично реле можно представить в виде катушки индуктивности и сердечника, который может втягиваться, если по катушке протекает электрический ток. Реле используется в тех случаях, если нужно управлять работой устройств, потребляемый ток которых может существенно отличаться от токов управления. Для подобных устройств есть определенные ограничения в скорости срабатывания. Для увеличения скорости можно использовать твердотельные реле или элементы переключения на полевых транзисторах. Разъемы. Штекерные разъемы. Разъемы для экранированных кабелей. Разъемы предназначены для объединения отдельных частей электрической схемы или даже объединения различных устройств. Они могут быть использованы для подачи сигналов и осуществления питания схем. Наиболее простым вариантом является использование штекерного разъема (однополюсная вилка, «банан»), который часто используется в измерительных схемах, источниках питания и т. д. Очень часто в качестве подобных разъемов используются разъемы типа «крокодил». Если для передачи сигнала необходимо исключить всевозможные наводки, помехи и емкостные связи, то в этом случае можно использовать защищенные экранированные разъемы типа BNC. 1.4.6. Элементы индикации (светодиоды и индикаторы) Создание лампы накаливания связывают с именем американского инженера и изобретателя Томаса Эдисона. В 1879 г. была создана первая коммерческая версия данного изобретения. Томас Эдисон Ник Холониак 22
Основной принцип работы устройства основывается на эффекте нагрева нити накаливания, которая находится в вакууме, до высоких температур, при пропускании электрического тока, что приводит к излучению света. Свет — это электромагнитное излучение, которое может воспринимать человеческий глаз. Позднее были созданы газоразрядные и флюоресцентные лампы. Первый светодиод (Light-emitting diode, LED) был создан в 1962 г. инженером Ником Холониаком. Был создан красный светодиод на основе арсенида галлия (GaAs), что послужило основой для дальнейшего развития данной области. Особенностью светодиодов является то, что они имеют низкое энергопотребление по сравнению с лампами накаливания, что позволяет существенно экономить на электроэнергии. Если же говорить про внутреннее устройство светодиодов, то они похожи на обычные диоды, только в дополнение способны излучать электромагнитные волны в различных диапазонах длин волн. Обычно прямое напряжение для светодиодов составляет от 1,8 до 3,6 В. Красные и желтые светодиоды имеют прямое напряжение 1,8–2,2 В. Зеленые и синие светодиоды имеют прямое напряжение 2,5–3,6 В. Белые светодиоды имеют прямое напряжение 3,0–3,6 В. Ток, который протекает через светодиод, может быть от 5 до 30 мА. Бывают и более мощные светодиоды, потребляемый ток которых может составлять более 350 мА. Светодиоды отличаются от ламп накаливания длительностью срока работы в режиме излучения. На рисунке 1.14 показан светодиод и его графическое обозначение. Рис. 1.14 Пример светодиода и его графическое обозначение на схемах При использовании светодиода в электрических схемах всегда нужно помнить про напряжение и ток, на которые рассчитан светодиод. Источник можно подобрать, исходя из паспортных данных прибора. Если же подходящего источника напряжения нет, то можно использовать токоограничивающий резистор, номинал которого можно рассчитать по следующей формуле: R= U пит − U диода . I диода Рассмотрим пример расчета нужного резистора. Допустим, что напряжение и ток для питания светодиода составляют 2,5 В и 10 мА соответственно, а напряжение питания основного источника составляет 5 В. Тогда значение резистора, с учетом формулы выше, составляет 250 Ом. Близкое значение серийно выпускаемых сопротивлений составляет 270 Ом (0,05 Вт). Рассеиваемая мощность на резисторе и светодиоде составляет 25 мВт. Общая потребляемая 23
мощность схемы составляет 25 мВт. На рисунке 1.15 показана схема для подключения рассмотренного случая. Рис. 1.15 Схема подключения светодиода с резистором Параллельное и последовательное подключение светодиодов. При параллельном подключении все диоды могут потреблять одинаковое напряжение, а ток потребляется независимо. Преимуществом является то, что при выходе из строя одного светодиода остальные продолжают работу. Недостатком является сложность конструкции и необходимость расчета номинала резистора для каждого светодиода по отдельности, если они разные. При последовательном подключении ток светодиодов остается постоянным, а вот значение напряжения на каждом светодиоде складывается. Преимуществом является возможность использования только одного светодиода и меньшее значение используемого тока. Недостатком является то, что при выходе из строя одного светодиода будет нарушена работа всей цепи. Рис. 1.16 Семисегментный индикатор с общим катодом На рисунке 1.16 показан внешний вид и схема подключения семисегментного индикатора, который изготовлен с использованием набора светодиодов. Принцип работы индикатора основан на подаче напряжения на соответствующий сегмент (светодиод) напряжения питания. Одновременно могут быть 24
запитаны несколько светодиодов, тогда на индикаторе будет показано определенное числовое значение. Различают две схемы подключения светодиодов: подключение с общим анодом и подключение с общим катодом. Необходимо помнить, что для подключения индикатора нужно использовать токоограничивающие резисторы. 1.5. Полупроводниковая электроника Открытие и использование полупроводниковых материалов позволило осуществить быстрый рывок в развитии электронных устройств. Полупроводники занимают, если рассматривать их с точки зрения проводимости, промежуточное место между металлами и диэлектриками. Принято выделять пять основных этапов развития полупроводниковой электроники в XX в. Первый этап связан с открытием полупроводниковых материалов (кремния и германия). Конечно, открыты они были еще в XIX в., но свойства материалов начали активно изучать немного позже. В 1904 г. был изобретен вакуумный диод, который послужил прототипом будущего полупроводникового диода, что можно назвать началом развития эпохи полупроводниковых приборов. Второй этап развития полупроводниковой электроники связан с изобретением в 1947 г. транзистора. Создание этого прибора послужило основой для развития целой отрасли компактных и эффективных электронных устройств. Третий этап ознаменован появлением интегральных микросхем. В конце 1950-х и начале 1960-х гг. началось промышленное производство серийно выпускаемых устройств, которые могли на одном кристалле объединить множество различных компонентов. Минимизация размера устройств существенно уменьшала стоимость последних и открывала перспективы дальнейшего развития полупроводниковых устройств. Четвертый этап начинается в конце 1960-х гг. Происходит революция в мире вычислительных устройств. Появляется микропроцессор. В 1971 г. компания Intel выпустила свой первый опытный образец микропроцессора — Intel 4004. Начинается доминирующая эра компьютеров и устройств цифровой электроники. Пятый этап связан с развитием технологии минимизации цифровых устройств. Если в 1971 г. технологический процесс изготовления транзисторов для микропроцессора составлял 10 мкм, то в 2017 г. уже 10 нм. Далее, безусловно, будет достигнут размер атомного размера в 1,5 нм. Но и это не предел, так как уже активно обсуждается создание квантовых полупроводников компьютеров, которые будут функционировать совершенно на иных физических принципах. 1.5.1. Интегральные микросхемы Использование отдельных электронных компонентов удобно в том случае, если необходимо реализовать относительно простую электрическую схему или требуется использовать элемент для одной конкретной задачи, позволяющий выполнить одну функцию. 25
Джек Килби Роберт Нойс До 1958 г. приходилось использовать соединение элементов вместе, чтобы реализовать сложную функциональную схему. В 1959 г. американский инженер Джек Килби, работая в компании Texas Instruments, создал первую интегральную микросхему, в которой элементы были размещены на одном полупроводниковом кристалле. Практически в это же время сотрудники компании Fairchild Semiconductor Жан Эрни и Роберт Нойс проводили подобные исследовательские работы. Инженерам удалось разработать технологию нанесения различных слоев на поверхность кремниевой пластины, оставляя при этом слой защитного оксида на переходах (использование планарной технологии). С 1960-х гг. начинается массовое производство интегральных микросхем. Достоинством интегральных микросхем является компактность, надежность, эффективность и низкое энергопотребление. На рисунке 1.17 представлен пример микросхемы ИД006. Рис. 1.17 Двухразрядный дешифратор со входом разрешения (К04ИД006) Мы не будем подробно останавливаться на существующей номенклатуре интегральных микросхем. Данная тема выходит за рамки изучения основ по электронике. Рекомендуется использовать специальные справочники, в которых подробно описаны свойства отечественных и зарубежных интегральных микросхем. 26
Современные тенденции. На данный момент интегральные микросхемы имеют свое развитие в новых системах: 3D-микросхемы, системы на кристалле и использование нанотехнологий. Развитие интегральных микросхем позволяет повысить производительность и функциональность электронных устройств. Особенно актуальным представляется развитие технологии создания новых микропроцессоров и микропроцессорных устройств. 1.5.2. Полупроводниковая электроника Для понимания работы полупроводниковых устройств нам необходимо еще раз рассмотреть строение атома. Электроны являются одним из компонентов атома, а атомы являются основой построения всей материи. Атомы связываются друг с другом, образуя молекулы. Молекулы, состоящие только из одного типа атомов, называются элементами (см. периодическую таблицу элементов Д. И. Менделеева). В этом смысле золото, серебро, кислород и др. являются элементами, поскольку все они состоят только из одного типа атомов. Когда молекула содержит более одного типа атома, она называется соединением. Вода, например, содержащая атомы водорода и кислорода, является сложным соединением. Пример другого сложного соединения (дважды ионизированный ион бора B²⁺) показан на рисунке 1.18. Орбитальная модель данного атома имеет пять протонов и три электрона. Рис. 1.18 Модель атома с пятью протонами и тремя электронами Для представленной модели атома протоны имеют положительный заряд, а электроны — отрицательный. Нейтроны, которые не представлены на рисунке, не имеют электрического заряда. Подобная модель является нестабильной в обычных условиях и обладает парамагнитными свойствами. Атомы, имеющие одинаковое количество протонов и электронов, не имеют суммарного электрического заряда. Такие атомы принято называть электрически нейтральными. Электроны, находящиеся далеко от ядра, могут свободно перемещаться, поскольку притяжение ядра атома слабое. Можно затратить энергию и добиться того, что внешний электрон будет полностью удален из атома. При изменении количества электронов атом уже не будет нейтральным. В этом случае атом превратится в положительно заряженный ион. Если же атом нейтральный, атом получит дополнительный электрон, и становится отрицательно заряженным ионом. Количество электронов может быть изменено не 27
только для атома. Ионом может быть и соединение нескольких атомов. Знание строения атома крайне важно при изучении физико-химических свойств разных материалов, так как их свойства и поведение в электрическом поле напрямую зависят от атомной структуры и взаимодействия электронов. Важным свойством любого материала является проводимость носителей заряда. Обычно проводимость в материалах рассматривают, исходя из зонной теории проводников. В этом случае все материалы можно разделить на металлы, полупроводники и диэлектрики. На рисунке 1.19 показаны зонные диаграммы для металла, полупроводника и диэлектрика. Важной характеристикой является наличие или отсутствие в материале зоны проводимости, запрещенной зоны и валентной зоны. В диэлектриках ширина запрещенной зоны больше всего. По этой причине проводимость в диэлектриках меньше, чем в металле или полупроводнике. Рис. 1.19 Зонные диаграммы разных материалов: а — диэлектрик; б — металл; в — полупроводник. В металлах свободными носителями заряда являются электроны, которые могут свободно перемещаться между атомами кристаллической решетки. Именно свободные электроны образуют электрический ток, если к проводнику приложить внешнее электрическое поле. Принято считать, что направление тока в металлах от «плюса» к «минусу», а направление движения электронов наоборот — от «минуса» к «плюсу». В полупроводниках носителями заряда являются свободные электроны и положительно заряженные дырки. Дырка — это квазичастица, вакантное электронное состояние в кристаллической решетке с положительным зарядом. Для получения определенной концентрации дырок используют легирование полупроводника акцепторными примесями, способными принять свободные электроны. Дырки могут возникнуть и в нелегированном материале. На внешних орбиталях атомов существуют так называемые валентные электроны, образующие валентные энергетические зоны. Если сообщить часть энергии полупроводнику, то электроны смогут перейти из валентной зоны в зону проводимости. Таким образом возникают дырки в собственном полупроводнике. В качестве источника энергии может быть свет, нагрев или ионизирующее излучение. На рисунке 1.20 представлены зонные диаграммы полупроводников, исходя из зонной теории собственного, электронного и дырочного проводников. 28
Рис. 1.20 Зонные диаграммы полупроводников: а — собственного; б — электронного; в — дырочного. 1.5.3. Проводники p-типа и n-типа Полупроводниковые приборы очень часто изготавливаются из кремния (Si). Поскольку чистый кремний при низких температурах почти не имеет свободных носителей заряда и ведет себя как диэлектрик (см. рис. 1.21), то он не может быть использован в качестве проводника, но кремний можно сделать проводящим, объединив его с другими элементами (легированием) (см. рис. 1.22) или изменив его температуру. В зависимости от типа примеси различают проводники n-типа (negative type) и p-типа (positive type). Рис. 1.21 Двумерное представление кристаллической решетки кремния: а — чистый кремний; б — кремний в измененных условиях. В первом случае примеси выступают в качестве донора, способного отдать свободный электрон. Свободные электроны свободно перемещаются в электрическом поле и образуют ток. Классическими донорными примесями являются элементы с пятью валентными электронами, такие как фосфор (P), мышьяк (As) или сурьма (Sb). Проводимость зависит от концентрации примесей донора. Электропроводность выше, чем в чистом полупроводнике. Во втором случае примеси выступают в качестве акцептора, способного принимать электроны, образуя дырки. Дырки могут свободно перемещаться, что приводит к проведению тока. Классическими акцепторными примесями являются элементы с тремя валентными электронами, такие как бор (B), алюми29
ний (Al) или галлий (Ga). Проводимость зависит от концентрации примесей акцептора. Рис. 1.22 Двумерное представление кристаллической решетки кремния: а — донорный; б — акцепторный полупроводник. Оба типа проводимости используются при создании различных полупроводниковых приборов. Особое внимание заслуживает контакт двух проводников с разными типами проводимости (p–n-переход). На основе различных эффектов, возникающих в контактном слое, работают современные полупроводниковые диоды и транзисторы, которые далее будут рассмотрены подробнее. 1.5.4. Диод Диод — полупроводниковый прибор с двумя выводами, имеющий p–nпереход. Вольт-амперная характеристика диода является нелинейной. Чаще всего диоды изготавливают из германия (Ge) и кремния (Si). На рисунке 1.23 представлен пример серийных диодов и их графическое обозначение на схемах. Обозначение зарубежное Обозначение отечественное Рис. 1.23 Примеры диодов и их графическое обозначение на схемах Для описания свойств диода необходимо рассмотреть возможность его проводимости электрического тока в прямом и обратном направлении. Если смещение прямое (от анода к катоду), то в этом случае диод проводит ток при условии, что значение входного напряжения является достаточным. При обратном смещении (от катода к аноду) диод практически не пропускает ток, за исключением небольшого обратного тока. Для обратной проводимости существу30
ет понятие пробоя, которое характеризуется максимальным значением напряжения, позволяющим проводить электрический ток. На рисунке 1.24 показана схема включения диода в прямом и обратном направлении (на рисунке ОПЗ — область пространственного заряда). При прямом смещении свободные электроны из области n (носители заряда — электроны) переходят в область p (носители заряда — дырки). При контакте двух материалов с разной проводимостью возникает область пространственного заряда (ОПЗ), ширина которой уменьшается при прямом смещении. При обратном смещении ширина данной зоны увеличивается, что препятствует нормальному току. Рис. 1.24 Схемы включения диода в прямом и обратном направлении тока: а — прямое смещение; б — обратное смещение; в — вольт-амперная характеристика (ВАХ) диода. Направление электрического поля запирающего слоя, при прямом смещении, противоположно направлению внешнего электрического поля. При обратном смещении направление электрического поля запирающего слоя совпадает с направлением внешнего электрического поля. Диоды можно разделить на группы по разным признакам. По виду материалов бывают германиевые или кремниевые диоды. По частотному диапазону диоды бывают низких, средних, высоких и сверхвысоких частот. По выполняемым функциям выделяют группу выпрямительных, детекторных, импульсных и стабилизирующих диодов. По форме исполнения они бывают штыревыми, фланцевыми, таблеточными и модульными. Среди группы специальных диодов можно выделить варикап и диод Ганна. Варикап — полупроводниковый диод, барьерная емкость которого зависит от приложенного обратного напряжения. В этом случае варикап можно сравнить с конденсатором, который может изменять свою емкость. Диод Ганна — полупроводниковый диод, который используется для генерации колебаний в СВЧ-диапазоне. Важным свойством полупроводниковых диодов является возможность выпрямления переменного тока в постоянный. Обычно диоды используются в этом случае с трансформаторами, питающимися от силовой линии переменного тока. На рисунке 1.25 представлена схема одно- и двухполупериодного выпрямителя. Схема объединения четырех диодов на рисунке 1.25б называется диодным мостом. 31
Рис. 1.25 Схемы выпрямителя переменного тока на полупроводниковом диоде: а — однополупериодный; б — двухполупериодный выпрямитель. 1.5.5. Транзистор Транзистор — полупроводниковый прибор с тремя выводами, который можно использовать для управления сигналами и усиления тока. В основном транзистор состоит из трех слоев полупроводниковых материалов разной проводимости (n-типа или p-типа, структура n–p–n или p–n–p). Впервые об этом изобретении стало известно в 1947 г., когда американские физики Уильям Шокли, Джон Бардин и Уолтер Бреттейн (рис. 1.26) из компании Bell Labs получили первый образец данного устройства. Рис. 1.26 Уильям Шокли, Джон Бардин и Уолтер Бреттейн в лаборатории Bell Labs 32
Открытие транзистора можно назвать уникальным событием, которое определило развитие всей будущей полупроводниковой электроники. Можно выделить два основных вида транзисторов: биполярные транзисторы (БТ, на англ. “bipolar junction transistor” — BJT), полевые транзисторы (ПТ, на англ. “field-effect transistor” — FET). Транзисторы широко используются в современной электронике для создания усилительных устройств, переключателей и других устройств. Их можно назвать основой для построения вычислительных машин, компьютеров, мобильных устройств и многих других электронных устройств. На рисунке 1.27 представлен пример серийных биполярных транзисторов и их графическое обозначение на схемах. Рис. 1.27 Примеры биполярных транзисторов и их графическое обозначение на схемах Рассмотрим разные виды транзисторов подробнее. Биполярный транзистор БТ состоит из трех слоев полупроводникового материала, которые могут иметь проводимость n- или p-типа. В зависимости от расположения слоев различают транзисторы с двумя разными структурами: n–p–n (1) и p–n–p (2). Первая структура транзистора имеет слой n-типа (эмиттер), слой p-типа (база) и еще один слой n-типа (коллектор). Второй структура состоит из слоя p-типа (эмиттер), слоя n-типа (база) и еще одного слоя p-типа (коллектор). На рисунке 1.28 показаны схемы включения биполярных транзисторов. а б Рис. 1.28 Схемы включения n–p–n биполярных транзисторов: а — с общей базой; б — с общим эмиттером; в — с общим коллектором. 33 в
Схема с общим эмиттером. Эмиттер транзистора в данном случае подключают к общему потенциалу. База управляет током коллектора. Выходной сигнал снимается с коллектора. Входной подсоединяют между базой и эмиттером. Схема используется для усиления сигнала по току и напряжению. Возможна реализация инверсии фазы входного сигнала. Особенностью схемы является то, что она имеет высокое входное сопротивление и низкое выходное сопротивление. Схема с общей базой. База транзистора подключена с к общему потенциалу. Входной сигнал подается на эмиттер, а выходной сигнал снимается с коллектора. Данная схема не позволяет реализовать инверсию сигнала. Обладает низким входным сопротивлением и высоким выходным сопротивлением. Подобное подключение используется при создании высокочастотных и малошумящих схем. Схема с общим коллектором. Коллектор транзистора подключен к общему потенциалу. Входной сигнал подается на базу, выходной сигнал снимается с эмиттера. Данная схема не позволяет реализовать инверсию сигнала. Обладает высоким входным сопротивлением и низким выходным сопротивлением. Схема может быть использована для создания буферных каскадов с большим входным током. Важной характеристикой биполярного транзистора является его вольтамперная характеристика. На рисунке 1.29а приведена схема включения биполярного транзистора по схеме с общим эмиттером, где выполняется условие IЭ = IБ + IК (токи в цепи эмиттера, базы и коллектора). На рисунке 1.29б, в показаны входная и выходные вольт-амперные характеристики биполярного транзистора. На рисунке 1.29в на ВАХ транзистора видно, как при росте напряжения «коллектор-эмиттер» ток базы сначала влияет на ток коллектора, но со временем перестает (происходит насыщение). Рис. 1.29 Схемы включения n–p–n биполярного транзистора и его ВАХ: а — схема с общим эмиттером; б — входная характеристика; в — выходная характеристика. Принцип работы полевого транзистора ПТ (униполярный транзистор) отличается от работы биполярного транзистора. Регулирование тока в таком транзисторе происходит с помощью проводимости проводящего канала, электрическое поле которого перпендикулярно направлению тока. Прохождение тока осуществляется одним типов зарядов, а управление происходит благодаря электрическому полю. Подключенные электроды имеют свое название: сток 34
(С, на англ. D — drain), исток (И, на англ. S — source) и затвор (З, на англ. G — gate). Управляемое напряжение в канале прикладывается между затвором и истоком. Можно условно разделить все полевые транзисторы на две большие группы: с управляющим p–n-переходом и изолированным затвором. Полевой транзистор с изолированным затвором (рис. 1.30). Для данного типа транзисторов затвор изолирован от полупроводникового материала пленкой диэлектрика из двуокиси кремния SiO2. По этой причине транзистор называют МОП-транзистором (металл — оксид — полупроводник, на англ. MetalOxide-Semiconductor Field-Effect — MOSFET). Электроды стока и истока имеют контакт с полупроводником. Существуют разные виды каналов. Канал может быть обогащен или, наоборот, обеднен носителями зарядов. В случае обедненного канала электрическое поле затвора повышает проводимость. Такой канал называют индуцированным. Существует и обратный случай, когда канал обогащен зарядами, тогда электрическое поле уменьшает число носителей зарядов. Такой канал называется встроенным. Каналы могут иметь электронную (n-тип) или дырочную проводимость (p-типа). Рис. 1.30 Схемы полевого транзистора с изолированным затвором (p-типа): а — с индуцированным каналом; б — со встроенным каналом. Рис. 1.31 Схемы полевого транзистора с управляющим p–n-переходом: а — с одним управляющим каналом; б — с двумя управляющими каналами. Полевой транзистор с управляющим p–n-переходом (рис. 1.31). Данный тип транзистора характеризуется тем, что затвор выполнен в виде обратно смещенного p–n-перехода. Обратное напряжение затвора позволяет регулировать ток в канале. Повышение обратного напряжения приводит к уменьшению 35
проводимости канала. Транзистор с управляющим p–n-переходом может работать только на обеднение канала носителями заряда. 1.6. Системы проектирования, моделирования и прототипирования электрических схем 1.6.1. Проектирование схем в программе Multisim Программное обеспечение Multisim (Circuit Design Suite) от компании National Instruments предназначено для проектирования, симуляции, анализа и валидации электрических схем на компьютере. Набор специальных модулей позволяет проводить интерактивное SPICE-моделирование с последующим анализом электрических цепей. Важным свойством программы является возможность комплексного построения системы виртуальных приборов, позволяющих имитировать работу реальных устройств, с последующей проверкой на основе использования серийного оборудования компании National Instruments. Далее мы рассмотрим базовые функции программы Multisim, которые позволяют создавать электрические цепи, выполнять добавление и редактирование электронных компонентов, использовать виртуальные приборы и проводить графический анализ электрических схем. Рис. 1.32 Внешний вид программы Multisim Интерфейс программы Multisim. На рисунке 1.32 представлен внешний вид программы Multisim версии 10.0. Условно главное окно программы можно разделить на несколько частей: 1 — меню навигации и элементы создания, редактирования и анализа электрических цепей; 2 — окно редактора проекта 36
(Design Toolbox); 3 — окно для создания электрических цепей; 4 — панель виртуальных приборов. В вашем случае расположение структурных элементов для 1 может отличаться. Причина может быть в исходном размещении окон программой или в отличии версии программы. Можно сказать, что внешний вид программы похож на большинство программ, которые позволяют выполнять создание и анализ электрических цепей на компьютере. В меню навигации можно выполнить следующее: File (Файл, позволяет сохранить и открыть проект), Edit (Редактирование, возможность правок в проекте), View (Вид, просмотр проекта), Place (Вставить, размещение компонента на схеме), MCU (Микроконтроллер, возможно для работы на схеме с микроконтроллерами), Simulate (Симуляция, симуляция схемы), Transfer (Трансляция, передача данных проекта в другие программы), Tools (Инструментарий, создание нового компонента и проверка качества электрической цепи), Reports (Отчеты, создание отчетов), Options (Установки, настройка программы), Window (Окно, редактирование вкладок проекта) и Help (Помощь, контекстная справка программы). Все кнопки, которые представлены на панели, по сути, дублируют возможности основного меню. Для добавления нужных элементов программы на панель можно использовать меню View → Toolbars, а затем отметить галочкой нужные инструменты. Важным блоком на главной панели является Components (компоненты), позволяющие быстро добавлять новые элементы схемы. На рисунке 1.33 показана возможность добавления новых блоков на панель программы. Для запуска симуляции схемы можно использовать кнопку в виде зеленого треугольника (Run/resume simulation) или можно нажать кнопку F5 на клавиатуре. Для быстрого освоения программы рекомендуется использовать подход, при котором выполняется создание простых электрических схем с их последующей симуляцией. Далее подробнее рассмотрим возможность добавления компонентов схемы в проект. Рис. 1.33 Добавление новых блоков управления на панель программы Multisim 37
Добавление компонентов на схеме. Для добавления новых компонентов можно использовать блок на основной панели или выбрать в меню Place → Component (для быстрого добавления можно использовать сочетание клавиш CTRL + W). На рисунке 1.34 показано окно для добавления нового компонента на схему. Рис. 1.34 Добавление новых компонентов в схему Добавим резистор 1 кОм на пространство будущей схемы. Для этого в выпадающем списке Database (база данных) выберите базу Master Database (главная база данных), в выпадающем списке Group (группа компонентов) выберите Basic (основная группа компонентов), а в окне Family (семейство компонентов) выберите RESISTOR. Далее в окне Component (компонент) выберите нужный номинал сопротивления. После этого нажмите кнопку OK и поместите элемент на пустое поле в окне для создания электрических цепей, нажав в удобном свободном месте левую кнопку мыши. На рисунке 1.35 показан поиск резистора в основной группе элементов. Рис. 1.35 Поиск резистора в группе Basic 38
После добавления элемента вновь откроется окно добавления компонентов. Аналогичным образом можно добавить источники для питания схемы, механические элементы управления, виртуальные приборы и другие электронные компоненты. Если использовать кнопки для добавления элементов через главную панель программы, то при нажатии сразу будут доступны элементы конкретной группы элементов (см. рис. 1.36): источники, основные элементы, диоды, транзисторы, TTL, CMOS, цифровые элементы, индикаторы и т. д. Рис. 1.36 Основная группа кнопок панели инструментов для добавления компонентов на схему Для добавления приборов можно использовать быстрые кнопки на панели виртуальных приборов. Далее рассмотрим подробный процесс создания новой электрической цепи с возможностью симуляции. Создание электрической схемы. При открытии программы Multisim всегда будет открываться пустой проект, который можно уже использовать. Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Делитель напряжения на резисторах». Рассмотрим создание схемы делителя напряжения на резисторах. На рисунке 1.37 показана схема делителя напряжения с использованием двух резисторов. Рис. 1.37 Схема делителя напряжения на резисторах Для сборки схемы необходимо последовательно добавить на пустую область источник напряжения (DC_POWER), два резистора (RESISTOR) номиналом 1 кОм и мультиметр. На рисунке 1.38 показано окно программы с добавленными электронными компонентами и мультиметром (Multimetr). Для вращения элемента на плоскости можно его выделить, воспользоваться сочетанием клавиш CTRL + R. Объединение элементов выполняется методом соединения проводником. Необходимо курсор мыши навести на вывод элемента и нажать левую кнопку мыши. Появится проводник. Далее нужно навести курсор мыши над выводом нужного элемента и нажать повторно на левую кнопку мыши. Проводники можно редактировать, изменяя их путь. 39
Рис. 1.38 Добавление электронных компонентов делителя напряжения На рисунке 1.39 показана схема делителя напряжения. Обратите внимание, что напряжение источника составляет 12 В. Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. Запуск симуляции выполняется через кнопку в меню или нажатием на клавиатуре кнопки F5. Рис. 1.39 Схема делителя напряжения на резисторах в программе Multisim Для активации экрана мультиметра необходимо нажать на иконку прибора в схеме два раза. Проанализируем полученную схему. В нашем случае полу40
чен делитель напряжения на 2. Значение входного напряжения Uвх = 12 В, а выходное значение составляет Uвых = 6 В. Данный результат можно было получить, если заранее рассчитать значение напряжения для двух резисторов по 1 кОм, используя выражение для расчета. Использование виртуальных приборов. Рассмотрим еще несколько виртуальных приборов, которые позволяют выполнять генерацию и анализ сигнала. Все виртуальные приборы можно разделить на две большие группы: для работы с аналоговыми и цифровыми сигналами. Далее создадим несколько проектов, позволяющих показать работы этих устройств. 1. Схема генерации сигнала с использованием функционального генератора, с последующим выводом сигнала на осциллографе (пример аналоговой схемы). Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Генератор сигналов». Для реализации схемы потребуется функциональный генератор (Function Generator) и осциллограф (Oscilloscope). На рисунке 1.40 показана схема генератора сигналов. Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. Рис. 1.40 Схема генератора сигналов в программе Multisim На следующем шаге необходимо выполнить настройки генератора сигналов. Для этого нужно дважды нажать на генератор, и откроется дополнительное окно настроек. Укажем вид сигнала (Waveforms), например, гармонический сигнал, частота 10 Гц и напряжение 10 В. Запуск симуляции выполняется через кнопку в меню или нажатием на клавиатуре кнопки F5. На рисунке 1.41 показана схема генератора сигналов при симуляции схемы. Дополнительно показа41
но окно настройки генератора и окно осциллографа, которое можно открыть двойным нажатием на соответствующий ярлык схемы. Рис. 1.41 Окно настройки функционального генератора и осциллографа По умолчанию окно осциллографа будет черного цвета. Для отображения белого экрана необходимо нажать на кнопку Reverse в открывшемся окне осциллографа. Изменение времени симуляции можно выполнить в меню Simulate → Interactive Simulation Settings, где нужно указать другое значение параметра TMAX. Для реального времени укажите значение TMAX = 1 с. 2. Схема индикации двоичных чисел с использованием индикатора и генератора слова (Word Generator) (пример цифровой схемы). Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Индикатор чисел». Для реализации схемы потребуется семисегментный индикатор и генератор слова. Добавим индикатор на пространство будущей схемы. Для этого в выпадающем списке Database (база данных) выберите базу Master Database (главная база данных), в выпадающем списке Group (группа компонентов) выберите Indicators (индикаторы), а в окне Family (семейство компонентов) выберите HEX_DISPLAY. Далее в окне Component (компонент) выберите нужный индикатор. После этого нажмите кнопку OK и поместите элемент на пустое поле в окне для создания электрических цепей, нажав в удобном свободном месте левую кнопку мыши. На рисунке 1.42 показан поиск индикатора в основной группе элементов. На панели приборов выберите генератор слова и добавьте его на схему. На рисунке 1.43 показана схема индикатора чисел. Подключите 4 младших раз42
ряда генератора (0–3) к выводам индикатора. Для индикатора порядок выводов начинается слева направо. Рис. 1.42 Поиск индикатора в группе Indicators Рис. 1.43 Схема генератора сигналов в программе Multisim Принцип работы данной схемы заключается в следующем. Генератор слова последовательно перебирает числа, например, в двоичном виде. Двоичный код передается на индикатор, который показывает десятичный эквивалент двоичного кода. На рисунке 1.44 показано окно настройки генератора слова. Необходимо указать циклический режим (Controls → Cycle), выбрать двоичное представление данных (Display → Binary), частоту перебора 1 Гц (Frequency). В окне для чисел укажите для каждого шага свое значение числа в двоичной форме. Порядок разрядов слева направо. Для последнего шага укажите значение Set Final Position, что послужит условием для завершения цикла и его 43
повторения. Запуск симуляции выполняется через кнопку в меню или нажатием на клавиатуре кнопки F5. Убедитесь в работоспособности данной схемы. Рис. 1.44 Окно настройки генератора слова в программе Multisim Анализ электрических схем. Программа Multisim позволяет выполнять еще одну важную функцию, которая связана с построением графиков и проведением анализа схемы. Рассмотрим пример нескольких схем с их последующим анализом на графике. Анализ схем выполняется с использованием специального модуля, который можно открыть, если перейти в главном меню Simulate → Analyses. 1. Схема фильтра нижних частот (ФНЧ). Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Фильтр нижних частот». Для реализации схемы потребуется источник переменного напряжения AC_POWER (Group → Source), 1 резистор, 1 конденсатор и осциллограф. Последний выполняет роль нагрузки, которую в качестве альтернативы можно представить в виде дополнительного резистора. Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. На рисунке 1.45 показана схема фильтра нижних частот. Номиналы резистора и конденсатора рассчитаны таким образом, чтобы значение граничной частоты составляло 10 МГц. Обратите внимание, что каждый значимый проводник схемы имеет свою нумерацию, которая выставляется автоматически. Данная информация будет полезна в том случае, когда требуется анализ характеристик схемы для конкретного узла. Выполним анализ амплитуд-частотной (АЧХ) и фазо-частотной (ФЧХ) характеристики схемы. Для этого переходим в главном меню Simulate → Analyses → AC Analysis. В окне настройки параметров симуляции необходимо указать диапазон частот для моделирования FSTART и FSTOP. Можно оставить параметры по умолчанию. На рисунке 1.46 показано график полученных характеристик для фильтра нижних частот. 44
Рис. 1.45 Схема фильтра нижних частот в программе Multisim Рис. 1.46 График АЧХ и ФЧХ для фильтра нижних частот На графике видно, что на АЧХ значение метки приблизительно находится на значении 10 МГц. На ФЧХ значение фазы составляет приблизительно –45, что соответствует расчетному значению заданных номиналов резистора и конденсатора. 2. Схема инвертирующего операционного усилителя. Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Инвертирующий операционный усилитель». Для реализации схемы потребуется функциональный генератор, операционный усилитель OPAMP_3T_BASIC (Group → Analog), два резистора и осциллограф. Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. На рисунке 1.47 показана схема инвертирующего операционного усилителя. 45
Рис. 1.47 Схема инвертирующего операционного усилителя в Multisim В программе используется виртуальный операционный усилитель. Для изменения полярности выводов можно выделить элемент и использовать горизонтальное отображение, используя сочетание клавиш ALT + X. На рисунке 1.48 показано окно осциллографа с графическим анализом сигнала инвертирующего операционного усилителя. На вход операционного усилителя подается переменное напряжение 1 мВ и частотой 10 Гц. Сигнал на выходе регистрируется и отображается с помощью осциллографа. Значение резистора в цепи обратной связи составляет 100 кОм. Значение второго резистора составляет 1 кОм. Значение амплитуды выходного сигнала, с учетом коэффициента усиления, составляет ~100 мВ. Обратите внимание, что выходной сигнал имеет смещение по фазе на π радиан. Для настройки графика на осциллографе можно использовать специальные элементы управления, позволяющие установить нужное значение времени и амплитуды (TimeBase, Channel A, Channel B). Точное значение сигнала в точке можно узнать, используя метки курсора (1) и (2). 3. Схема для анализа вольт-амперных характеристик диода. Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Анализ ВАХ диода». Для реализации схемы потребуется источник переменного напряжения DC_POWER (Group → Source), 1 резистор, 1 виртуальный диод DIODE_ VIRTUAL (Group → Diodes). Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. На рисунке 1.49 показана схема на основе полупроводникового диода, позволяющего анализировать ВАХ. Выполним анализ вольт-амперной характеристики схемы. Для этого пе46
реходим в главном меню Simulate → Analyses → DC SWEEP. На рисунке 1.50 показано главное окно (DC Sweep Analysis) для настройки параметров анализа схемы. В окне настройки параметров симуляции необходимо указать диапазон напряжений для моделирования Start value = 0 и Stоp value = 1. Шаг дискретизации Increment = 0.001. Для выбора нужной точки на схеме для анализа ВАХ необходимо выполнить дополнительную настройку. Рис. 1.48 Окно осциллографа и графический анализ сигнала инвертирующего операционного усилителя Рис. 1.49 Схема для анализа ВАХ диода в Multisim 47
Рис. 1.50 Окно настройки параметров анализа схемы диода (вкладка Analysis Parameters) Перейдите в окне DC Sweep Analysis во вкладку Output, в которой выберите в поле More options -> Add device/model parameter (рис. 1.51). В новом окне в поле Device type необходимо выбрать Diode, в поле Parameter выбрать ток id (Diode current) и сохранить настройки, нажав кнопку OK (рис. 1.52). В окне DC Sweep Analysis добавить кнопкой Add новую переменную (на рисунке I(d1[id])) из поля Variables in Circuit в поле Selected variables for analysis (рис. 1.53). Рис. 1.51 Окно настройки параметров анализа схемы диода (вкладка Output) 48
Рис. 1.52 Окно настройки параметров Add device/model parameter Рис. 1.53 Окно настройки параметров и добавление новых параметров для анализа На последнем шаге необходимо нажать кнопку для анализа Simulate. Откроется новое окно с ВАХ выбранного диода. На рисунке 1.54 показан график рассчитанной ВАХ диода. Рис. 1.54 ВАХ виртуального диода в программе Multisim 49
Аналогичный график можно было получить, если использовать специальный прибор (IV анализатор) для получения различных ВАХ характеристик схемы устройств: Diode, PNP BJT, NPN BJT, PMOS, NMOS. Прибор может производить анализ устройств, которые не включены в схему. На рисунке 1.55 показана схема и график ВАХ виртуального диода в программе Multisim. Рис. 1.55 Схема и график ВАХ виртуального диода в программе Multisim Обратите внимание, что меню Simulate Parameters заданы следующие параметры симуляции: Start = 0, Stop = 1 и Increment = 10. Полученный результат можно сравнить с графиком на рисунке 1.54. 4. Схема для анализа вольт-амперных характеристик биполярного транзистора. Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Анализ ВАХ биполярного транзистора». Для реализации схемы потребуется источник переменного напряжения DC_POWER, DC_CURRENT (Group → Source), 1 биполярный n–p–n транзистор TRANSISTORS_VIRTUAL (Group → Transistors). Схему необходимо подключить к земле, для этого используется специальный элемент схемы GROUND. На рисунке 1.56 показана схема на основе полупроводникового биполярного транзистора, позволяющая анализировать ВАХ. На рисунке 1.57 показано главное окно (DC Sweep Analysis) для настройки параметров анализа схемы. В окне настройки параметров симуляции необходимо указать диапазон напряжений и тока. Для выбора нужной точки на схеме для анализа ВАХ необходимо выполнить дополнительную настройку. Перейдите в окне DC Sweep Analysis во вкладку Output, в которой выберите в поле More options → Add device/model parameter (рис. 1.58). 50
Рис. 1.56 Схема для анализа ВАХ транзистора в Multisim Рис. 1.57 Окно настройки параметров анализа схемы транзистора (вкладка Analysis Parameters) Рис. 1.58 Окно настройки параметров Add device/model parameter (вкладка Output) В новом окне в поле Device type необходимо выбрать BJT, в поле Parameter выбрать ток ic (Current at collector node) и сохранить настройки, нажав кнопку OK. 51
В окне DC Sweep Analysis добавить кнопкой Add новую переменную (на рисунке I(q1[ic])) из поля Variables in Circuit в поле Selected variables for analysis. На последнем шаге необходимо нажать кнопку для анализа Simulate. Откроется новое окно с ВАХ выбранного транзистора. На рисунке 1.59 показан график рассчитанной ВАХ транзистора. Аналогичный график можно получить, если использовать в качестве анализатора схемы IV анализатор из набора виртуальных приборов. Рис. 1.59 ВАХ виртуального биполярного транзистора в программе Multisim 5. Схема для воспроизведения логических функций с помощью модельного дешифратора. Для создания нового проекта в главном меню выберите File → New → Schematic Capture (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Логические функции на дешифраторе». Для реализации схемы потребуется дешифратор 3 на 8 — 74S138D (Group → TTL) и логический конвертер Logic Converter. На рисунке 1.60 показана схема на основе дешифратора для реализации логических операций. Рис. 1.60 Схема реализации логических функций на основе дешифратора 52
Рассмотрим возможность использования дешифратора для реализации логических операций немного подробнее. Дело в том, что выход дешифратора уже выполняют некоторые логические операции. На рисунке 1.61 показано схематичное изображение дешифратора 3 на 8 и логические операции, которые можно выполнить на его основе. Рис. 1.61 Воспроизведение логических функций на основе дешифратора: а — дешифратор 3 на 8; б — минтермы входных значений дешифратора. Используя данные минтермы, можно получить разные логические функции. Рассмотрим пример на рисунке 1.60. Данная схема позволяет получить логическую операцию произведения двух входных сигналов x3  x2. Подробнее результат можно записать в следующем виде: y6 + y7 = x3  x2  x1 + x3  x2  x1 = = x3  x2 ( x1 + x1 ) = x3  x2 . Значение x1 + x1 = 1 , исходя из свойств логической дизъюнкции. Обратите внимание, что выходы дешифратора являются инверсными. Для обратной инверсии используется логический элемент NOT (не). Для реализации сложения двух сигналов используется логический элемент OR (или). Рис. 1.62 Окно Logic Converter для проверки результатов преобразования 53
Проверка выполняется с помощью логического конвертера Logic Converter. Необходимо открыть окно конвертера, нажав два раза на ярлык прибора на схеме. Далее требуется выделить входные каналы A, B и С (активные каналы отмечены белым). Преобразование результатов моделирования схемы выполняется с помощью кнопки в поле Conversions (схема → бинарный код). На рисунке 1.62 показан результат работы данной схемы. Убедитесь в том, что дешифратор позволяет получить необходимую логическую операцию. 1.6.2. Разработка печатных плат в программе Ultiboard Программное обеспечение Ultiboard от компании National Instruments предназначено для проектирования, анализа и валидации печатных плат электрических схем на компьютере. Программа является дополнением к программе Multisim. Далее мы рассмотрим базовые функции программы Ultiboard, которые позволяют импортировать готовые электрические схемы, создавать новые проекты печатных плат, выполнять добавление и редактирование посадочных мест (footprint) электронных компонентов, выполнять трассировку проводников, проводить анализ схемы на наличие ошибок. Интерфейс программы Ultiboard. На рисунке 1.63 представлен внешний вид программы Ultiboard версии 10.0. Условно главное окно программы можно разделить на несколько частей: 1 — меню навигации и элементы создания, редактирования и анализа печатных плат; 2 — окно редактора проекта (Design Toolbox) и редактор слоев (Layers); 3 — окно для создания печатных плат; 4 — обзор таблиц проекта (Spreadsheet View). Рис. 1.63 Внешний вид программы Ultiboard На рисунке 1.63 представлено главное окно программы, в котором рабочее пространство для создания печатных плат имеет белый фон. По умолчанию 54
программа имеет черный фон. Для изменения цвета в главном меню необходимо перейти во вкладку Options Preferences → вкладка Colors → Color element (Background). Далее выбрать наиболее подходящий цвет фона. В меню навигации можно выполнить следующее: File (Файл, позволяет сохранить и открыть проект), Edit (Редактирование, возможность правок в проекте), View (Вид, просмотр проекта), Place (Вставить, размещение компонента на схеме), Place (Размещение, добавление в проект элемента из базы данных или специальной области), Design (Дизайн, проектирование схем), Tools (Инструменты, набор инструментов для создания области печатной платы, элементов печатной платы и редактирования Netlist), Autoroute (Автотрассировка, автоматическое размещение проводников на плате) Options (Установки, настройка программы), Window (Окно, редактирование вкладок проекта) и Help (Помощь, контекстная справка программы). Все кнопки, которые представлены на панели, по сути, дублируют возможности основного меню. Для добавления нужных блоков программы на главную панель можно использовать в меню View → Toolbars, а затем отметить галочкой нужные инструменты. Существует несколько способов работы с новым проектом в программе Ultiboard: передача проекта из программы Multisim и создание нового проекта стандартными инструментами. 1. Передача проекта из программы Multisim. После того как схема собрана и выполнена проверка на наличие ошибок, можно переходить к следующему этапу — трансляции схемы в программу. Для того чтобы передать готовую схему в программу Ultiboard, выполните следующее: в главном меню Multisim выберите раздел для трансляции Transfer → Transfer to Ultiboard. На следующем шаге программа предложит сохранить новый проект. Если ошибок не возникло, то программа сохранит новую версию и откроет окно нового проекта в Ultiboard. На рисунке 1.64 показано главное окно программы с добавленными элементами схемы (цвет фона — черный). Рис. 1.64 Внешний вид программы с добавленными элементами схемы 55
На данном этапе может возникнуть несколько сложностей. Во-первых, если в схеме использованы виртуальные элементы, то будьте готовы, что для них никакой трансляции посадочных мест выполнено не будет. Программа имеет базу данных только серийно выпускаемых элементов. Во-вторых, если элемент по какой-то причине не имеет собственного корпуса, то в этом случае передачи информации об этом элементе не будет. Для проверки наличия корпуса выполните следующие действия: нажмите правой клавишей мыши на интересующий вас элемент, выберите в выпадающем меню вкладку свойства; находясь в свойствах, найдите вкладку параметры, а в ней строку корпус; если область названия корпуса пуста, то этот элемент не имеет собственного корпуса. После трансляции готовой схемы в программу Ultiboard программа представит перечень соединений схемы (Nets). Данный этап является одним из ключевых, так как возможная потеря или отсутствие некоторых соединений в итоге не позволит автоматически разработать полноценную печатную плату. Однако возможность доработки схемы вручную в программе не исключается. На следующем шаге необходимо создать границы платы и разместить элементы в указанной области. В Design Toolbox во вкладке Layers расположены все возможные слои будущей схемы. Перейдите во вкладку Layers, найдите слой Board Outline (желтого цвета) и переключитесь на него, дважды нажав на название (строка будет выделена красным цветом). Данный слой определяет границы будущей печатной платы. Создайте новые границы. Для этого в главном меню выберите Place → Shape → Rectangle (прямоугольная область). Начертите прямоугольник в свободной области окна печатной платы. Размеры прямоугольника всегда можно изменить. Далее переместите ранее добавленные в проект компоненты в полученную область. Разместите произвольно элементы внутри выбранной области. На рисунке 1.65 показана печатная плата с размещенными площадками компонентов схемы. Рис. 1.65 Внешний вид программы с добавленными элементами схемы и Board Outline 56
На последнем этапе необходимо выполнить трассировку проводников. Основные слои для трассировки называются Copper top и Copper bottom. Перейдите во вкладку Layers, найдите слой Copper top (зеленого цвета) и переключитесь на него, дважды нажав на название (строка будет выделена красным цветом). Теперь можно выполнить соединение контактных площадок, используя инструмент для создания прямых линий. В главном меню выберите Place → Line (прямая линия). Для соединения контактов нужно навести курсор мыши и нажать на первую площадку, появится зеленая линия, которая будет менять траекторию при движении курсора. Наведите курсор над второй площадкой и второй раз нажмите кнопку мыши. Аналогично и для других площадок. Подобный подход удобен в том случае, если нужно соединить несколько простых площадок. Если же нужно выполнить соединение площадок сложной схемы, то в этом случае лучше использовать автоматическую трассировку. Для автоматической трассировки нужно выбрать в главном меню Autoroute → Start/Resume Autoroute. Будет выполнена трассировка данных в автоматическом режиме. На рисунке 1.66 показан результат трассировки. Рис. 1.66 Внешний вид программы после автоматической трассировки проводников Программа Ultiboard позволяет просматривать 3D-модель полученной схемы. Для просмотра 3D-модели в главном меню нужно выбрать View → 3D Preview или нажмите кнопку Show 3D на панели инструментов. На рисунке 1.67 показана 3D-модель схемы. 2. Создание нового проекта стандартными инструментами. Проектирование печатной платы можно выполнить, используя стандартные инструменты. Для этого в главном меню выбираем File → New Design (для быстрого добавления можно использовать сочетание клавиш CTRL + N). Сохраните вновь созданный проект, например, используя название «Печатная плата». Теперь нужно добавить граничную область в слое Board Outline, добавить посадочные 57
площадки для разных элементов из базы данных, соединить вручную элементы и выполнить трассировку проводников. Дополнительные элементы печатной платы можно добавить, используя пункты в главном меню Place. Рис. 1.67 3D-модель с элементами проектируемой печатной платы В Design Toolbox вкладка Layers расположены все возможные слои будущей схемы. Перейдите во вкладку Layers, найдите слой Board Outline (желтого цвета) и переключитесь на него, дважды нажав на название (строка будет выделена красным цветом). Данный слой определяет границы будущей печатной платы. Создайте новые границы. Для этого в главном меню выберите Place → Shape → Rectangle (прямоугольная область). Начертите прямоугольник в свободной области окна печатной платы (размеры произвольные). В главном меню выберите Place → From Database (для быстрого добавления можно использовать сочетание клавиш CTRL + W). Выберите несколько элементов из базы. Например, в нашем случае использованы три резистора, один конденсатор и пьезоизлучатель. Вы можете использовать свои элементы. На рисунке 1.68 показана схема печатной платы без соединений. Рис. 1.68 Внешний вид программы с добавленными элементами При соединении площадок вручную существует необходимость создания списка для соединения площадок (Net list). При импорте схемы из программы Multisim такой необходимости нет, так как список соединений формируется ав58
томатически. Для создания списка соединений вручную необходимо в главном меню выбрать Tools → Net Editor. В поле Net необходимо создать новый список, например, назовите его N_1_1. Далее во вкладке Pins необходимо нажать кнопку для добавления пинов. Выбираем пины, которые необходимо соединить, например, U4 pin1 и U3 pin1 (см. рис. 1.69). Аналогично выполняем соединение остальных площадок. Нажимаем кнопку OK и закрываем окно. Теперь площадки на печатной плате можно соединить с помощью инструмента Line (прямая линия). Рис. 1.69 Окно настройки Net list в программе Ultiboard Перейдите во вкладку Layers, найдите слой Copper bottom (красного цвета) и переключитесь на него, дважды нажав на название (строка будет выделена красным цветом). Теперь можно выполнить соединение контактных площадок, используя инструмент для создания прямых линий. В главном меню выберите Place → Line (прямая линия). Для соединения контактов нужно навести курсор мыши и нажать на первую площадку, появится зеленая линия, которая будет менять траекторию при движении курсора. Наведите курсор над второй площадкой и второй раз нажмите кнопку мыши. Аналогично и для других площадок. Толщину проводника можно изменить в его настройках. На рисунке 1.70 показана печатная плата после соединения проводников. Проверка на наличие ошибок проектирования выполняется автоматически. Результат проверки показан в окне программы Spreadsheet View -> DRC. Как правило, очень часто при проектировании вручную возникает ошибка пересечения проводников. Необходимо отслеживать и исключать подобные ошибки проектирования. 59
Для просмотра 3D-модели в главном меню нужно выбрать View → 3D Preview или нажмите кнопку Show 3D на панели инструментов. На рисунке 1.71 показана 3D-модель схемы. Рис. 1.70 Печатная плата после соединения проводников Рис. 1.71 3D-модель с элементами проектируемой печатной платы Заключительным этапом проектирования печатной платы является экспорт модели в формате, который будет использован специальными устройствами для изготовления печатных плат. Для экспорта проекта: File → Export. В новом окне необходимо выбрать формат экспортируемого файла. Выберите формат файла Gerber (см. рисунок 1.72). Далее нажмите кнопку для настройки свойств формата и укажите экспортируемые слои. В нашем случае укажем слои Copper Bottom и Board Outline (см. рисунок 1.73). Можно использовать и другие форматы. Сохраните изменения и закройте данное окно. После возврата к предыдущему окну нажмите кнопку экспорт. Сохраните экспортируемые файлы. На этом процесс экспорта формата Gerber для печатной платы завершен. 60
Рис. 1.72 Экспорт проекта в формате Gerber в программе Multisim Рис. 1.73 Окно для настройки свойств формата Gerber 61
ГЛАВА 2 АНАЛОГОВАЯ СХЕМОТЕХНИКА 2.1. Проектирование аналоговых фильтров Пассивные фильтры на основе RC-цепи применяются в разных сферах, включая аудиоаппаратуру, многополосные эквалайзеры, разделение звуковых сигналов на низкие, средние и высокие частоты в акустических системах, а также в схемах частотной коррекции разных устройств. Особенности пассивных фильтров на RC-цепи: простота конструкции, устойчивость, низкая чувствительность характеристик к изменениям номиналов элементов, большие габариты и вес из-за размеров индуктивных катушек на частотах ниже 100 МГц. В RC-цепях наиболее распространены следующие типы пассивных фильтров. Фильтр нижних частот (ФНЧ) пропускает частоты ниже частоты среза, ослабляя более высокие частоты. Фильтр верхних частот (ФВЧ) пропускает частоты выше частоты среза, ослабляя более низкие частоты. Полосовой фильтр (ПФ) пропускает частоты в определенном диапазоне, ослабляя частоты вне этого диапазона. Режекторный фильтр (РФ) ослабляет частоты в определенном диапазоне, пропуская частоты вне этого диапазона. При создании частотных фильтров на основе RC- или LC-цепи учитывают следующие параметры: наклон АЧХ — всегда стараются получить более крутой наклон, частота среза — может быть рассчитана проектировщиком, неравномерность АЧХ — данный параметр всегда стараются уменьшить, отношение входного и выходного сопротивлений, ослабление в полосе задержания — ослабление в полосе заграждения. Частота среза. Частота среза — это частота, на которой коэффициент передачи фильтра снижается на 3 дБ (или до 0,707 от максимального значения в линейной шкале). Информация о сопротивлении, индуктивности и емкости позволяет определить частоту, на которой произойдет ослабление на –3 дБ. Таким образом, зная требуемую частоту среза, мы можем рассчитать и спроектировать фильтр. Частота среза в случае RC-цепи может быть найдена по следующей формуле: fg = 1/2RC, где R — значение резистора (Ом), С — значение емкости конденсатора (Ф). Частота среза в случае LC-цепи может быть найдена по следующей формуле: f g = 1 / 2 LC , где L — индуктивность (Гн). На рисунке 2.1 показана амплитуда — частотная характеристика для фильтра нижних частот. Значение граничной частоты определяется на уровне 0,707 (линейная шкала) и –3 дБ (логарифмическая шкала). Крутизна спада определяет эффективность фильтра. 62
Рис. 2.1 АЧХ фильтра нижних частот Порядок фильтра. Наклон амплитудно-частотной характеристики не всегда оптимален, так как при слишком пологом наклоне радиоприемное устройство может улавливать дополнительные частоты. Для устранения этого недостатка разработчики стремятся создавать фильтры с более крутыми характеристиками. Крутизна наклона АЧХ зависит от величины ослабления в полосе и порядка фильтра. Например, в фильтре пятого порядка будут использоваться три конденсатора и две катушки индуктивности. Для расчета фильтра большого порядка применяют специальные методики расчета. Среди наиболее известных можно выделить формулы на основе полиномов Баттерворта и Чебышева, функций Бесселя. 2.1.1. Фильтр нижних частот Фильтр нижних частот (ФНЧ) — это электронный фильтр, пропускающий частотный спектр сигнала ниже частоты среза и подавляющий частоты выше нее. Частота среза определяется как частота, при которой коэффициент передачи А(ω) снижается на 3 дБ (соответствует 0,707 от максимального значения). На рисунке 2.2 представлена схема для фильтра нижних частот. Для построения данной схемы потребуется резистор и конденсатор. Для расчета заданного значения частоты срезы можно использовать ранее представленную формулу. В зависимости от расположения конденсаторов может быть Г-, Пи Т-образный фильтр. Рис. 2.2 Фильтр нижних частот Если проанализировать АЧХ и ФЧХ фильтра нижних частот на рисунке 2.3, то можно сделать вывод, что значение, которое соответствует частоте среза, на графике ФЧХ будет соответствовать угловой мере в –45. 63
Рис. 2.3 АЧХ и ФЧХ фильтра нижних частот 2.1.2. Фильтр верхних частот Фильтр верхних частот (ФВЧ) — это электронный фильтр, пропускающий частотный спектр сигнала выше частоты среза и подавляющий частоты ниже нее. Частота среза определяется как частота, при которой коэффициент передачи А(ω) снижается на 3 дБ (соответствует 0,707 от максимального значения). На рисунке 2.4 представлена схема для фильтра верхних частот. Для построения данной схемы потребуются резистор и конденсатор. Для расчета заданного значения частоты среза можно использовать ранее представленную формулу. В зависимости от расположения резисторов может быть Г-, П- и Т-образный фильтр. Рис. 2.4 Фильтр верхних частот Рис. 2.5 АЧХ и ФЧХ фильтра верхних частот 64
Если проанализировать АЧХ и ФЧХ фильтра верхних частот на рисунке 2.5, то можно сделать вывод, что значение, которое соответствует частоте среза, на графике ФЧХ будет соответствовать угловой мере в 45. 2.1.3. Полосовой частотный RC-фильтр Соединив последовательно фильтр верхних и фильтр нижних частот, можно получить полосовой фильтр. Этот фильтр ослабляет как низкие, так и высокие частоты, пропуская лишь определенный диапазон частот. Пример схемы полосового RC-фильтра показан на рисунке 2.6. Рис. 2.6 Полосовой частотный RC-фильтр Рис. 2.7 АЧХ и ФЧХ полосового частотного фильтра Частота, на которой наблюдается максимум амплитуды сигнала, называется резонансной частотой. Частота резонанса может быть найдена по следующей формуле: fg = 1/2RC, где R — значение резистора (Ом); С — значение емкости конденсатора (Ф). На рисунке 2.7 показано, что фазовый сдвиг на резонансной частоте равен нулю. 2.1.4. Мост Вина — Робинсона Если добавить сопротивления R1 и 2R1 к полосовому фильтру, представленному на рисунке 2.6, то мы получим мост Вина — Робинсона (рис. 2.8). Омический делитель напряжения обеспечивает частотно-независимое напряжение, которое равно 1/3Uвх. 65
Рис. 2.8 Мост Вина — Робинсона Рис. 2.9 АЧХ и ФЧХ моста Вина — Робинсона Важно отметить, что на резонансной частоте выходное напряжение равно нулю. В отличие от полосового фильтра, амплитудно-частотная характеристика коэффициента усиления на резонансной частоте имеет минимальное значение (рис. 2.9). 2.2. Проектирование схем на операционных усилителях Операционный усилитель (ОУ) функционирует аналогично обычному усилителю, усиливая напряжение или мощность входного сигнала. Однако, в отличие от обычных усилителей, характеристики ОУ определяются в основном параметрами цепи обратной связи. ОУ представляют собой усилители постоянного тока с высоким коэффициентом усиления, высоким входным и низким выходным сопротивлением. Изначально такие усилители применялись в аналоговых вычислительных машинах для выполнения математических операций, таких как суммирование и интегрирование, что и дало им название «операционные». Сегодня ОУ чаще всего изготавливаются в виде монолитных интегральных схем. Примеры серийно выпускаемых ОУ представлены на рисунке 2.10. Идеальный ОУ. Рассмотрим идеальный операционный усилитель (ОУ) — теоретическую модель с предельными, идеализированными парамет66
рами. Ключевые характеристики идеального ОУ включают: бесконечно большой коэффициент усиления, бесконечно широкую полосу пропускания, бесконечно высокое входное сопротивление, бесконечно низкое выходное сопротивление и нулевое выходное напряжение при нулевом входном напряжении. Хотя достижение этих идеальных характеристик на практике невозможно, современные технологии приближаются к подобной модели. Рис. 2.10 Примеры серийных операционных усилителей Рассмотрим основные характеристики операционного усилителя. 1. Коэффициент усиления — это отношение изменения выходного напряжения к вызвавшему его изменению входного напряжения в линейном режиме работы усилителя. В идеальном ОУ этот параметр бесконечен, а в реальных системах он принимает конечное, но, как правило, очень большое значение. 105...106). 2. Входное сопротивление — сопротивление между входами усилителя (оно имеет величину от нескольких кОм до нескольких мОм). 3. Выходное сопротивление — сопротивление усилителя со стороны подключения нагрузки (оно находится в пределах от 50 до 2000 Ом). 4. Полоса пропускания — диапазон частот, в пределах которого усилитель обеспечивает требуемое усиление и стабильность. Для современных ОУ максимальная скорость нарастания обычно составляет от 0,3 до 50 В/мкс. 5. Смещение выходного напряжения (нуля) — разница между фактическим выходным напряжением и ожидаемым при нулевом входном сигнале. (Типичное значение напряжения смещения нуля составляет 10–50 мВ.) 6. Дрейф напряжения смещения — изменение напряжения смещения во времени и при изменении внешних условий. 7. Входные токи — токи, протекающие через входы усилителя (сила входного тока составляет 1–100 мкА). 8. Коэффициент подавления синфазных сигналов — отношение коэффициентов усиления по обоим входам усилителя (величина находится в пределах от 80 до 100 дБ). 67
Передаточная характеристика. Идеальный операционный усилитель должен иметь передаточную характеристику, проходящую через нулевую точку. Для достижения нулевого выходного напряжения требуется определенная разность напряжений на входе, называемая напряжением смещения нуля U0. Обычно оно составляет несколько милливольт и часто может быть проигнорировано. На рисунке 2.11 представлена передаточная характеристика операционного усилителя (на рис. 2.11 Ud — входное напряжение, Ua — выходное напряжение). Рис. 2.11 Передаточная характеристика ОУ На графике видно, что значение напряжения, которое можно подать на вход, находится в области малых значений напряжений. В этом заключается смысл операционного усилителя как устройства, способного усиливать слабые сигналы. Коэффициент усиления будет определяться значением опорного напряжения, которое обычно ограничивается диапазоном ±1,5–15 В. Максимальное значение усиленного сигнала не может превышать указанную величину. Принцип отрицательной обратной связи. Как упоминалось ранее, операционные усилители чаще всего применяются в схемах с отрицательной обратной связью. Принцип ее работы показан на рисунке 2.12. Отрицательная обратная связь реализуется путем возврата части выходного напряжения через цепь обратной связи на вход усилителя. Эта связь считается отрицательной, если напряжение обратной связи вычитается из входного напряжения. В противном случае, когда напряжение обратной связи суммируется с входным напряжением, связь является положительной. В дальнейшем мы будем рассматривать только отрицательную обратную связь. Рис. 2.12 Принцип отрицательной обратной связи В схеме с отрицательной обратной связью коэффициент усиления определяется исключительно параметрами цепи обратной связи и не зависит от ха68
рактеристик самого усилителя. В простейшем случае цепь обратной связи может быть реализована в виде делителя напряжения. Тогда схема, представленная на рисунке 2.12, будет функционировать как линейный усилитель, коэффициент усиления которого задается коэффициентом деления цепи обратной связи. Если же в качестве цепи обратной связи использовать RC-цепь, то получится активный фильтр. Наконец, в цепи обратной связи можно применять нелинейные элементы, такие как диоды или транзисторы, что позволяет создавать нелинейные схемы операционных усилителей, используемых в вычислительной технике. 2.2.1. Инвертирующий усилитель Инвертирующий операционный усилитель (инвертирующий ОУ) — это схема, предназначенная для усиления входного сигнала с одновременным инвертированием его фазы (созданием выходного напряжения противоположной по знаку полярности). Он реализуется на базе операционного усилителя и нескольких резисторов. Коэффициент усиления инвертирующего ОУ определяется значениями резисторов R1 и RN по следующей формуле: K = Uвых(t) / Uвх(t) = –RN / R1. Схема инвертирующего операционного усилителя с обратной связью представлена на рисунке 2.13. Рис. 2.13 Схема инвертирующего операционного усилителя Работа операционного усилителя основывается на схеме, в которой входной сигнал подается на инвертирующий вход, а неинвертирующий вход обычно соединен с землей. В схеме с обратной связью имеется резистор, который соединяет выход операционного усилителя с инвертирующим входом. 2.2.2. Неинвертирующий усилитель Неинвертирующий операционный усилитель — это электронное устройство, предназначенное для усиления выходного сигнала и создания выходного напряжения, совпадающего по фазе с входным сигналом. Он состоит из операционного усилителя и нескольких резисторов. 69
На рисунке 2.14 изображена схема неинвертирующего операционного усилителя с обратной связью. Коэффициент усиления этой схемы определяется значениями резисторов R1 и RN по следующей формуле: K = Uвых(t) / Uвх(t) = 1 + (RN / R1). Рис. 2.14 Схема неинвертирующего операционного усилителя Убрав резисторы из схемы на рисунке 2.14, мы получим схему повторителя напряжения. Коэффициент усиления в этом случае равен единице K = 1. Эта схема включения операционного усилителя используется как эмиттерный повторитель и преобразователь напряжения. Преимущество этой схемы заключается в небольшом различии между выходным и входным напряжением (всего несколько милливольт). 2.2.3. Сумматор на операционном усилителе Для суммирования нескольких напряжений можно использовать операционный усилитель в инвертирующем включении. В этом случае входные сигналы подаются на инвертирующий вход ОУ через соответствующие резисторы. Пример схемы сумматора напряжений представлен на рисунке 2.15. Выходное напряжение определяется следующей формулой: Uвых(t) = (RN /R1)U1 + (RN / R2)U2 + ... + (RN / Rn)Un. Рис. 2.15 Схема сумматора напряжений 70
Инвертирующий сумматор также может работать как усилитель с широким диапазоном изменения нулевого уровня. Для этого на один из входов схемы подают постоянное напряжение. 2.2.4. Интегратор на операционном усилителе Интегратор на операционном усилителе — это электронная схема, использующая ОУ для выполнения математической операции интегрирования по времени. Выходное напряжение этой схемы пропорционально интегралу входного напряжения по времени. Схема интегратора на ОУ показана на рисунке 2.16. Рис. 2.16 Схема интегратора на операционном усилителе Существует два особых случая: постоянное входное напряжение и переменное входное напряжение. В первом случае изменение выходного сигнала описывается формулой Uвых = –(Uвх / RC)t + Uвх0. При переменном входном напряжении формулы для расчета выходного напряжения, изменяющегося во времени, выглядят следующим образом: Uˆ вых / Uˆ вх = 1/ RC. Идеальный интегратор не меняет выходное напряжение, когда входное напряжение равно нулю, так как входной ток стремится к нулю. Это свойство используется в схемах динамических запоминающих устройств. Однако на практике выходное напряжение интегратора изменяется при нулевом входном напряжении, достигая максимального значения выходного напряжения операционного усилителя. Это связано с перезарядкой конденсатора входным током операционного усилителя и током смещения, определяемым входным напряжением смещения и входным резистором. 2.2.5. Дифференциатор на операционном усилителе Дифференциатор на операционном усилителе — это электронное устройство на основе операционного усилителя, которое выполняет математическую операцию дифференцирования. На рисунке 2.17 представлена схема дифференциатора на операционном усилителе. 71
Рис. 2.17 Схема дифференциатора на операционном усилителе Выходное напряжение дифференциатора пропорционально скорости изменения входного напряжения: Uвых = –RC(dUвх / dt). Для переменного входного напряжения формула расчета выходного напряжения, изменяющегося во времени, имеет вид Uˆ вых / Uˆ вх = RC. При подаче на вход дифференциатора синусоидального сигнала, он ведет себя как фильтр высоких частот, причем коэффициент усиления этого фильтра прямо пропорционален частоте входного сигнала. 72
ГЛАВА 3 ЦИФРОВАЯ СХЕМОТЕХНИКА 3.1. Физические основы работы устройств В данном разделе мы подробно ознакомимся с существующими элементами цифровой схемотехники. Понятно, что вся цифровая схемотехника основана на использовании аналогового сигнала. Основу цифрового сигнала составляют дискретные аналоговые сигналы, имеющие определенный уровень напряжения и тока. Давайте остановимся на некоторых основных понятиях, которые, безусловно, будут нам полезны при разборе основных элементов цифровой схемотехники. Сигнал — это физическая величина (температура, давление воздуха, интенсивность света, сила тока и т. д.), которая изменяется со временем. Благодаря этому изменению сигнал может передавать информацию. Электрический сигнал — это электрическая величина (напряжение, ток, мощность), которая изменяется со временем. Вся электроника работает с электрическими сигналами, хотя сейчас все чаще используются световые сигналы, представляющие собой изменяющуюся во времени интенсивность света. Аналоговый сигнал — это сигнал, который может принимать любые значения в определенных пределах. Устройства, работающие только с аналоговыми сигналами, называются аналоговыми устройствами. Название «аналоговый» означает, что сигнал изменяется аналогично физической величине, то есть непрерывно. На рисунке 3.1 (слева) показан пример аналогового сигнала. Цифровой сигнал — это сигнал, который может принимать только два (реже три) значения с некоторыми отклонениями от них. Например, напряжение может принимать два значения: от 0 до 0,5 В (уровень логического нуля) или от 2,5 до 5 В (уровень логической единицы). Устройства, работающие исключительно с цифровыми сигналами, называются цифровыми устройствами. На рисунке 3.1 (справа) показан пример цифрового сигнала. Еще раз обратим внимание на то, что в природе почти все сигналы являются аналоговыми, то есть они непрерывно изменяются в определенных пределах. По этой причине первые электронные устройства были аналоговыми. Они выполняли преобразование физических величин в напряжение и ток, с возможностью обратного преобразования. Например, голос человека (механические или акустические колебания) могут быть преобразованы с помощью специальных систем в электрические колебания, которые могут быть изменены средствами аналоговой электроники. Можно изменить частотный состав, изменить амплитуду и другие характеристики. Потом выполнить возврат к механическим колебаниям, используя специальные звуковоспроизводящие системы типа динамиков или наушников. Если говорить про использование аналоговых систем, то у них имеются два существенных недостатка: наличие шума и влияние наводок. В первом слу73
чае мы будем вынуждены бороться со слабыми сигналами (хаотическими сигналами) любого электронного устройства. Во втором случае влияние оказывается электронными устройствами, но их природа может быть значительно сильнее. К подобного рода системам можно отнести электромагнитное излучение от радиопередающих устройств или трансформатора. Рис. 3.1 Электрические сигналы: аналоговый (слева) и цифровой (справа) Однако и с цифровыми системами не все так однозначно. Аналоговый сигнал имеет непрерывное представление во времени, в то время как цифровой сигнал определен дискретно в конкретный момент времени. По этой причине быстродействие аналоговых систем всегда будет больше, чем у цифровых. Скорость передачи и обработки сигнала у аналоговых систем всегда будет выше. Существуют и положительные стороны использования цифрового сигнала. Например, цифровой сигнал менее подвержен влиянию разного рода искажениям и шумам. Описание подобных систем всегда проще и понятнее. Цифровые устройства проще проектировать. Все эти преимущества и обеспечили развитие цифровой электроники. Далее мы подробно остановимся на основных элементах цифровой схемотехники, которые составляют основу современных цифровых устройств. Все цифровые устройства состоят из логических микросхем. Каждая микросхема обязательно имеет цифровые входы/выходы, вывод питания (обычно от +3,3 до 5 В) и вывод и общий вывод. Входы и выходы цифровых микросхем. В настоящее время наибольшее распространение получили два вида технологий для реализации внутренней логики устройства: ТТЛ (TTL) или ТТЛШ (TTLS) — биполярная транзисторнотранзисторная логика и ТТЛ с диодами Шоттки и КМОП (CMOS) — комплементарные транзисторы со структурой «металл — оксид — полупроводник». При изготовлении CMOS использует полевые транзисторы, а TTL — биполярные транзисторы. Основные различия между CMOS и TTL заключаются в их характеристиках, свойствах и уровнях логических значений. CMOS обладает высоким входным сопротивлением и низким энергопотреблением, однако с увеличением частоты переключения растет потребляемый ток. В свою очередь, TTL более чувствителен к напряжению питания и имеет постоянное потребление мощности при повышении частоты. Входы рассматриваются как бесконечно большое сопротивление, которое не влияет на подключенные выходы. В цифровых микросхемах применяют следующие три разновидности выходных каскадов: выход с двумя состояниями (2С, 2S, ТТЛ, TTL), выход с открытым коллектором (ОК, OC), выход с тремя состояниями (обозначается 3С, 3S). Выход 2C содержит два ключа, которые 74
переключаются поочередно. Верхний переключатель замкнут при логической единице, а нижний — при логическом нуле. Выход OK использует один переключатель. Замкнутый переключатель создает логический нуль, а разомкнутый — логическую единицу. Переключатели выхода 3C могут переключаться поочередно или одновременно, создавая третье состояние, управляемое сигналом EZ (высокоимпедансное состояние). Рис. 3.2 Схема логического элемента 2И-НЕ на ТТЛ (слева) и КМОП (справа) Простейшие логические элементы. Основой цифровой схемотехники является набор простейших логических элементов, которые способны выполнять разные операции. Рассмотрим некоторые из этих элементов: инвертор, повторитель, элементы И, И-НЕ, ИЛИ, ИЛИ-НЕ и исключающее ИЛИ. На рисунке 3.2 показана внутренняя схема логического элемента 2И-НЕ на ТТЛ и КМОП-логики. Инвертор (логический инвертор или элемент НЕ «Inverter») — устройство, которое выполняет простейшую логическую функцию — инвертирование, с изменением уровня входного сигнала на противоположный. Устройство имеет один вход и один выход (рис. 3.3). Выход инвертора может быть типа 2С или типа ОК. Ниже представлены условные обозначения инвертора, которые приняты в отечественной и зарубежной литературе. Дополнительно представлена таблица истинности. Таблица истинности — соответствие значению уровня входного и выходного сигнала логической микросхемы. Мы будем использовать данное понятие на протяжении объяснения всего данного раздела. Понятие можно назвать фундаментальным для всей цифровой схемотехники. Рис. 3.3 Логический элемент инвертор: а — обозначение в зарубежных источниках; б — обозначение в отечественных источниках; в — таблица истинности. Из таблицы истинности видно, что при поступлении на вход уровня логического нуля на выходе мы получим уровень логической единицы. И обратная 75
ситуация, при поступлении на вход уровня логической единицы на выходе мы получим уровень логического нуля. Повторители и буферы — устройства, которые выполняют две основные функции: усиление входного сигнала и согласование протоколов обмена. В первом случае повторители и буферы могут быть использованы для увеличения нагрузки сигнала, то есть использовать один сигнал для множества входов (рис. 3.4). Используются буферы с повышенным выходным током и выходом 2С. Рис. 3.4 Повторители и буферы: а — обозначение в зарубежных источниках; б — обозначение в отечественных источниках; в — таблица истинности. Принцип действия аналогичен работе транзисторного повторителя. Буферы, которые имеют выход ОК или 3С, используют для создания двунаправленных линий передачи данных и мультиплексирования сигналов. Имеется вход разрешения –EZ. Элементы И, И-НЕ, ИЛИ, ИЛИ-НЕ — устройства, которые выполняют различные операции булевой алгебры, если говорить о положительной логике. Элементы «И» (рис. 3.5) выполняют операцию произведения. Элемент имеет два входа и один выход. Если подать на входы два нуля, то на выходе получим два нуля. Если на входы подать нуль и единицу (или наоборот), то на выходе получим нуль. При подаче на вход двух единиц мы получим единицу на выходе. Элементы «И-НЕ» инвертируют выход сигнала элемента «И». Элементы «ИЛИ» (рис. 3.6) выполняют операцию сложения. Элемент имеет два входа и один выход. Если подать на входы два нуля, то на выходе получим два нуля. Если на входы подать нуль и единицу (или наоборот), то на выходе получим единицу. При подаче на вход двух единиц мы получим единицу на выходе. Элементы «ИЛИ-НЕ» инвертируют выход сигнала элемента «ИЛИ». Все рассмотренные элементы могут быть с выходами типа 2С, ОК и 3С. Рис. 3.5 Элементы И и И-НЕ: а — обозначение в зарубежных источниках; б — обозначение в отечественных источниках; в — таблица истинности. 76
Рис. 3.6 Элементы ИЛИ и ИЛИ-НЕ: а — обозначение в зарубежных источниках; б — обозначение в отечественных источниках; в — таблица истинности. Элемент исключающее ИЛИ (на англ. Exclusive-OR) — устройство, у которого все входы элементов исключающее ИЛИ равноправны, ни один из входов не может блокировать работу других входов. Принцип работы элемента исключающее ИЛИ следующий. Если подать на вход два нуля или две единицы, то на выходе будет без изменений и значение нуля. Выход будет установлен в единицу, если хотя бы на один из входов подать значение логической единицы. Обозначение и таблица истинности данного элемента представлена на рисунке 3.7. Рис. 3.7 Элементы исключающее ИЛИ и исключающее ИЛИ-НЕ: а — обозначение в зарубежных источниках; б — обозначение в отечественных источниках; в — таблица истинности. Подведем небольшой итог относительно логических элементов. Выше мы подробно рассмотрели основную часть элементов, которую реализовали на основе логических функций. Далее приведена сводная таблица 3.1, в которой приведены логические элементы, их обозначение, схема и функция. Таблица 3.1 Логические элементы и их обозначение Элемент НЕ Обозначение Схема ЛН Функция F=A 77
Продолжение табл. 3.1 Элемент Обозначение Схема Функция И ЛИ F=AB И-НЕ ЛА F = A B ИЛИ ЛЛ F=AB ИЛИ-НЕ ЛЕ F = A B Искл. ИЛИ ЛП F = ( A  B)  ( A  B) Искл. ИЛИ-НЕ ЛС F = ( A  B)  ( A  B) Примечания. В таблице использованы следующие обозначения: A и B — входы логического элемента; F — выход логического элемента; A — отрицание значения A; B — отрицание значения B;  — логическое умножение (конъюнкция);  — логическое сложение (дизъюнкция). 3.2. Триггеры Триггер (на англ. Trigger или Flip-flop) — простейшее электронное устройство, имеющее два устойчивых состояния, переход между которыми обусловлен наличием в электрической цепи положительной обратной связи (сигналы с выходов подаются на входы). Устойчивые состояния триггера обозначаются Q = 1 и Q = 0. Инверсный выход триггера обозначается Q . В каком именно состоянии находится триггер, зависит от сигнала на входе и его текущего состояния. Можно сказать, что триггер в данном случае можно рассматривать как элементарную ячейку памяти. Триггер может иметь установочные, информационные и управляющие входы. Управляющие входы разрешают или запрещают подачу сигнала на информационные входы. Установочные входы регулируют работу схемы независимо от других входов. Среди наиболее распространенных видов можно выделить RS-, JK-, D- и T-триггеры. На схемах триггеры обозначаются буквой «T». На рисунке 3.8 представлены условные изображения триггеров. 78
RS JK D T Рис. 3.8 Условное обозначение триггеров RS, JK, D и T RS-триггер. В случае RS-триггерa существует два информационных входа: S и R. Если на вход S подать логическую единицу, а на вход R логический нуль, то на выходе Q получим логическую единицу (на выходе Q логический нуль). И наоборот, если на вход S подать логический нуль, а на вход R логическую единицу, то на выходе Q получим логический нуль ( Q на выходе логическая единица). Работу RS-триггера можно описать следующим уравнением: Qn+1 = Rn Sn + RnQn , где Qn и Qn+1 — предыдущее и новое состояние триггера. Для RS-триггера состояние S = 1 и R = 1 является запрещенным. На выходе Q может быть логический нуль или единица. На рисунке 3.9 представлена схема RS-триггера на двух элементах ИЛИ-НЕ. S R Q 0 0 1 1 0 1 0 1 Q 0 1 – Q Q 1 0 – Режим Хранение Установка 0 Установка 1 Запрещено Рис. 3.9 RS-триггер на двух элементах ИЛИ-НЕ и таблица истинности JK-триггер. В случае JK-триггерa существует два информационных входа: J и K. Работа JK-триггерa напоминает работу RS-триггерa. Отличие заключается в том, что состояние J = 1 и K = 1 не является запрещенным. В этом случае выход триггера Q изменит свое состояние на противоположное. Такое состояние называется счетным режимом. Для данного триггера существует управляющий синхросигнал C. Если на вход J подать логическую единицу, а на вход K логический нуль по фронту сигнала С, то на выходе Q получим логическую единицу. И наоборот, если на вход J подать логический нуль, а на вход K логическую единицу по фронту сигнала С, то на выходе Q получим логический нуль. Работу JK-триггера можно описать следующим уравнением: Qn+1 = J nQn + KnQn , где Qn и Qn+1 — предыдущее и новое состояние триггера. 79
D-триггер. Данный триггер еще имеет название триггер задержки. При поступлении синхросигнала на вход C устанавливается в состояние, которое соответствует потенциалу на входе D. Работу D-триггера можно описать следующим уравнением: Qn + 1 = Dn, где Qn+1 — новое состояние триггера. Изменение происходит не сразу, а только после прихода сигнала D, то есть с задержкой на один период импульсов. T-триггер. В случае T-триггера состояние выхода изменяется по фронту импульса на входе C. Данный вид триггера еще принято называть счетным триггером. Дополнительно можно использовать вход T, который разрешает или запрещает срабатывание триггера по положительному фронту синхросигнала C. Работу T-триггера можно описать следующим уравнением: Qn+1 = TnQn + TnQn , где Qn и Qn+1 — предыдущее и новое состояние триггера. Очень часто T-триггер используется для построения двоичных счетчиков. 3.3. Дешифраторы и шифраторы Дешифратор. Дешифратор (на англ. Decoder) — комбинационная логическая схема, которая преобразует двоичный код в унитарный код (дешифрует код из 2n в код 1 из N, где n — число входов, а N — число выходов). На схемах дешифраторы обозначаются DC. Большинство дешифраторов имеют отрицательную логику на выходе. Выходы могут иметь 2C или ОК тип выхода. На рисунке 3.10 представлена схема дешифратора и таблица истинности. В таблице истинности не учитывается работа управляющих сигналов. Представлены только информационные сигналы дешифратора DC 3–8. Рис. 3.10 Схема дешифратора 3–8: а — обозначение на схеме; б — таблица истинности. Основная функция дешифратора заключается в дешифрировании входных кодов. Вход E используют в качестве управляющего сигнала. Если нужно преобразовать сигнал с большим количеством числа разрядов, то для этого используется схема с наращиванием дешифраторов (рис. 3.11). 80
Рис. 3.11 Схема наращивания дешифратора из DC 3–8 в DC 4–16 Шифратор. Шифратор (на англ. Сoder) — комбинационная логическая схема, которая преобразует унитарный код в двоичный код (шифрует код 1 из N в код 2n, где n — разрядность двоичного кода, а N — число входов). На схемах шифраторы обозначаются CD. Если нужно преобразовать сигнал с большим количеством числа разрядов, то для этого используется схема с наращиванием шифраторов. На рисунке 3.12 представлена схема шифратора и таблица истинности. В таблице истинности не учитывается работа управляющих сигналов. Представлены только информационные сигналы шифратора CD 8–3. На рисунке 3.13 представлена схема наращивания шифратора из CD 8–3 в CD 16–4. Рис. 3.12 Схема шифратора 8–3: а — обозначение на схеме; б — таблица истинности. Отметим основные области применения дешифраторов и шифраторов. Области применения дешифраторов: системы отображения чисел, адресация памяти, управление цифровыми устройствами. Шифраторы используются для преобразования входных сигналов в двоичный код. 81
Рис. 3.13 Схема наращивания шифратора из CD 8–3 в CD 16–4 3.4. Мультиплексоры Мультиплексор (на англ. Multiplexer) — комбинационная микросхема, которая предназначена для последовательной передачи входных сигналов на выход. Еще говорят о том, что выполняется операция мультиплексирования. Входы называются каналами мультиплексора, выходы принято называть разрядами мультиплексора. Приоритетная работа конкретного канала может быть задана с помощью специальных управляющих сигналов. Существуют разные серии мультиплексоров, которые могут иметь от 2 до 16 каналов и число разрядов от 1 до 4. В зависимости от соотношения информационных входов n и адресных входов m различаются полные и неполные мультиплексоры. В случае полного мультиплексора выполняется условие n = 2m, в случае неполного — n < 2m. На схемах мультиплексоры обозначаются MS. На рисунке 3.14 представлена схема мультиплексора 4–1 и его таблица истинности. Рис. 3.14 Схема мультиплексора 4–1: а — обозначение на схеме; б — таблица истинности. 82
Мультиплексор может быть построен на основе простых логических элементов. На рисунке 3.15 представлена схема 4-канального мультиплексора, которая построена на основе элемента НЕ, И и ИЛИ. Схему можно усложнить, добавив элементы управления и логические элементы для увеличения количества информационных входов. Рис. 3.15 Схема мультиплексора 4–1 на логических элементах НЕ, И и ИЛИ Мультиплексоры можно объединять для наращивания схемы мультиплексирования (пирамидальное каскадирование). Рассмотрим схему наращивания линий мультиплексирования с использованием мультиплексоров 4–1 (рис. 3.16). Рис. 3.16 Схема каскадирования мультиплексоров пирамидальной структуры 83
Для более сложных схем каскадирования мультиплексоров можно использовать дешифратор, входные сигналы которого будут выбирать один из мультиплексоров. Существуют микросхемы, которые выполняют обратную функцию мультиплексирования. Такие микросхемы называются демультиплексорами. Они выполняют передачу единственного информационного сигнала на один из выходов. На схемах демультиплексоры обозначаются DMS. На рисунке 3.17 представлена схема демультиплексора 1–4 и его таблица истинности. Рис. 3.17 Схема демультиплексора 1–4: а — обозначение на схеме; б — таблица истинности. Мультиплексоры используются в разных областях цифровой схемотехники и микропроцессорных систем. Применяют мультиплексоры в цифровых системах связи, где они используются для мультиплексирования нескольких сигналов на одной линии передачи данных, что позволяет повысить эффективность использования канала связи и увеличить пропускную способность системы. Мультиплексоры применяются в цифровых системах обработки сигналов, например, в аудио- и видеообработке данных. В компьютерных сетях мультиплексоры позволяют выполнять коммутацию сетевых пакетов и управлять трафиком. 3.5. Сумматоры Сумматор (на англ. Adder) — комбинационная микросхема, которая предназначена для сложения двух двоичных кодов. Информационные входы микросхемы предназначены для ввода двух двоичных чисел, имеющих разряд n. Выходы микросхемы предназначены для вывода суммы чисел. Например, если одно входное десятичное число — 8 (двоичное число 1000), а второе — 6 (двоичное число 0110), то сумма чисел на выходе будет 14 (двоичное число 1110). На схемах сумматоры обозначаются SМ. На рисунке 3.18 представлена схема сумматора и его таблица истинности. С помощью сумматора можно реализовать схему вычитания двух двоичных чисел. В этом случае для реализации арифметической операции вычитания необходимо выполнить инверсию каждого разряда. Для инвертирования значений можно использовать логический элемент инвертор. Данный режим возможен, если на вход сигнал переноса С подать логическую единицу. На рисунке 3.19 представлена схема вычитания двух двоичных кодов на основе сумматора. 84
а A B C P S 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1 б в Рис. 3.18 Схема сумматора: а — обозначение на схемах; б — одноразрядный сумматор; в — таблица истинности одноразрядного сумматора. Рис. 3.19 Схема вычитания с использованием сумматора Для сумматоров можно реализовать схему наращивания каскадов. Увеличить разрядность каскадированием сумматоров достаточно просто. Нужно подать сигнал с выхода переноса младшего разряда P на вход переноса старшего разряда С (рис. 3.20). Рис. 3.20 Схема каскадирования сумматоров 85
Сумматоры используются в различных отраслях, включая электронику, арифметико-логические устройства, цифровые сигнальные процессоры и другие вычислительные системы. Они способны выполнять точные расчеты с длинными последовательностями чисел, что имеет большое значение для финансовых операций и научных исследований. 3.6. Регистры Регистр (на англ. Register) — устройство, которое предназначено для хранения одного многоразрядного числа в виде двоичного кода. Регистр представляет собой несколько D-триггеров. В зависимости от формы представления сигнала существуют два вида регистров: последовательные и параллельные. В последовательном регистре цифровой код передается последовательно по одному разряду, начиная с младшего. В параллельном регистре все разряды числа для хранения передаются одновременно. На схемах регистры обозначаются RG. На рисунке 3.21 показана схема последовательного регистра и схема регистра, которая собрана на D-триггерах. Последовательные регистры, также известные как регистры сдвига, представляют собой последовательную цепочку триггеров. Их основной функцией является сдвиг битов данных, которые записаны в триггерах. При поступлении тактового сигнала С данные от входа D каждого триггера передаются на выход Q. Далее сигналы передаются по порядку. Таким образом информация, хранящаяся в регистре, на каждом такте перемещается на один разряд либо в сторону старших разрядов, либо в сторону младших. Рис. 3.21 Схема последовательного регистра: а — обозначение на схеме; б — схема регистра на D-триггерах. На рисунке 3.22 показана схема параллельного регистра и его схема на D-триггерах. В параллельных регистрах каждый триггер имеет отдельный информационный вход Dn и выход Qn, которые функционируют независимо. Все тактовые входы С-триггеров связаны между собой. Можно сказать, что параллельный регистр представляет собой многовходовый триггер, который может хранить несколько бит информации. Еще одно важное применение регистров связано с сохранением нескольких последовательных значений переменного входного кода. Данный подход позволяет сравнивать предыдущее значение кода с его последующим значени86
ем или выполнять арифметические операции с несколькими последовательно полученными значениями одного и того же кода. В данном случае регистр выполняет функцию элемента, который задерживает информацию, сохраняя историю изменений входного кода. Подобные задачи часто встречаются в области цифровой обработки аналоговых сигналов. Рис. 3.22 Схема параллельного регистра: а — обозначение на схеме; б — схема регистра на D-триггерах. 3.7. Счетчики Счетчик (на англ. Counter) — устройство, которое предназначено для подсчета входных электрических импульсов. Для подсчета импульсов используется вход С. Каждый новый импульс изменяет значение счетчика на единицу. Счетчик может быть реализован на триггерах. В этом случае состояние счетчика будет зависеть от состояний триггеров. На рисунке 3.23 представлена схема двоичного суммирующего счетчика на D-триггерах. Рис. 3.23 Двоичный суммирующий счетчик на D-триггерах Каждый счетчик можно охарактеризовать его состоянием в течение одного цикла, которое определяется числом доступных состояний. Число состояний определяется количеством триггеров. Если мы имеем дело с последовательностью из трех триггеров, то число доступных состояний k равно 3, и тогда число состояний определяется по соотношению N = 23 = 8 (двоичный код от 000 до 87
111). Коэффициент счета — это число возможных состояний счета и определяется по формуле Kc = Nвх / Nвых, где Nвх и Nвых — число импульсов на входе и выходе. При подаче периодического сигнала на вход счетчика с частотой fвх частота импульсов на выходе fвых будет меньше в Kc раз: Kc = fвх / fвых. По этой причине счетчики можно рассматривать в качестве делителя частоты, а коэффициент Kc рассматривать коэффициентом деления. Если возникает необходимость уменьшения коэффициента пересчета, то для этого можно использовать промежуточные выходы триггеров. Асинхронные счетчики. Асинхронные счетчики — это устройства на основе JK-триггеров, которые выполняют подсчет электрических импульсов сигнала в режиме последовательного переключения выходов (разрядов). Разряды переключаются с определенной задержкой, то есть асинхронно. Последовательное переключение накладывает определенные ограничения на частоту входного сигнала, так как повышение частоты будет влиять на время установления нужного счета. По этой причине увеличение частоты работы счетчика будет приводить к тому, что на выходе уменьшается количество разрядов. Достаточно часто делители асинхронные счетчики используются в схемах делителя частоты. Может быть реализована схема с делителем частоты, используя стандартную логику счетчика. Примером может служить счетчик с делителем на 10, выдающий меандр (рис. 3.24а). Счетчик можно использовать в качестве делителя частоты на произвольное значение, например, схема делителя на 9 с обратной связью представлена на рисунке 3.24б. а б Рис. 3.24 Схема делителя частоты на асинхронном счетчике: а — схема делителя на 10; б — схема делителя на 9 с обратной связью. Для реализации делителя частоты на произвольное число раз необходимо нужный выход счетчика подать на входы сброса, используя обратную связь. Достижение нужного значения в двоичном коде счетчика будет сигналом для сброса и началом нового счета. Синхронные счетчики. Синхронные счетчики — это устройства, которые выполняют подсчет электрических импульсов сигнала в режиме параллельного переключения выходов (разрядов). Разряды переключаются одновременно. Логика работы синхронного счетчика сложнее, чем у асинхронного счетчика. Скорость работы быстрее и нет особых ограничений на количество выходов по сравнению с асинхронным счетчиком. В зависимости от того, как 88
выполняется обработка сигнала, синхронные счетчики делятся на счетчики с асинхронным переносом и счетчики с синхронным переносом (или полностью синхронные счетчики). В первом случае при последовательном переносе будет возникать некоторая задержка по времени. Во втором случае при полном параллельном переключении подобная задержка исключена, и время переключения будет ограничено скоростью переключения триггера. Наибольший интерес представляет использование синхронных счетчиков в двух схемах: увеличения разрядности и делителя частоты. На рисунке 3.25 показана схема делителя частоты на синхронном счетчике с асинхронным переносом. Рис. 3.25 Схема делителя частоты на синхронном счетчике с асинхронным переносом В данной схеме в качестве управляющего сигнала можно подать 12-разрядный двоичный код, который определяет коэффициент деления входной частоты. Код будет записан по сигналу переноса от старшего счетчика < 0. С этого значения счетчик начнет счет на уменьшение после достижения минимального значения. Далее выработается сигнал переноса старшего счетчика, после этого входной код вновь будет записан в счетчики. Если входной код будет N, то коэффициент деления будет равен (N + 1). Схема управляемого делителя частоты на синхронном счетчике может быть реализована следующим образом. Сигнал переноса CR старшего счетчика необходимо подать на вход разрешения EWR младших счетчиков. Управление происходит в режиме обратного счета, для чего на вход U/D подается значение логического нуля. На рисунке 3.26 представлена схема делителя частоты на синхронном счетчике. Рис. 3.26 Схема делителя частоты на синхронном счетчике 89
После достижения счетчиками нулевого значения будет выработан сигнал переноса CR, который переводит все счетчики в режим параллельной записи. Для реализации полного цикла счета (от входного кода управления до нуля) используется положительный фронт тактируемого сигнала C. Если входной код будет N, то коэффициент деления будет равен (N + 1). Входной код принимает значения от 1 до (2n – 1), где n — количество разрядов кода. Для правильной работы схемы необходимо выполнение условия, при котором период тактового сигнала не должен быть меньше полной задержки переноса. 3.8. Аналого-цифровой преобразователь В начале данного раздела мы подробно рассмотрели такие важные определения, как аналоговый и цифровой сигнал. Далее последовательно изучили основные устройства цифровой схемотехники. В данной части мы рассмотрим специальные устройства, которые позволяют выполнять оцифровку аналогового сигнала. Аналого-цифровой преобразователь (АЦП, на англ. ADC) — устройство, которое преобразует непрерывный аналоговый сигнал в его дискретное представление в виде последовательности цифровых кодов. Устройства АЦП могут использовать разные способы аналого-цифрового преобразования. Наиболее распространенные из них включают: метод последовательного приближения, параллельную, последовательно-параллельную, двойную интеграцию и дельта-сигма модуляцию. На основе данных методов и существуют многие современные АЦП. Рассмотрим основные определения, которые относятся к цифровому представлению сигнала и основные виды АЦП. Дискретизация сигналов. Чтобы получить цифровой сигнал, в первую очередь необходимо преобразовать его в дискретный вид. Рассмотрим аналоговый сигнал x(t), который дискретизируют через каждые t секунд. Время дискретизации называется интервалом или периодом дискретизации. Обратное значение интервала 1/t является частотой дискретизации. Каждое дискретное значение x(t) в моменты времени t = 0, t, 2t, 3t и т. д. называется выборкой. Таким образом, набор x(0), x(t), x(2t) и т. д. представляет собой полный набор выборок. Сигнал x(t) можно представить в виде дискретного набора данных в виде {x(0), x(t), x(2t), x(3t), ...}. Данная последовательность данных и называется дискретным сигналом. Частота выборки (дискретизации). Одним из важных понятий измерительной системы с аналоговым вводом является частота, с которой устройство осуществляет выборку входящего сигнала. Частота выборки в аналогоцифровом преобразователе (АЦП) показывает, как часто выполняется процесс преобразования аналогового сигнала в цифровой вид. При увеличении частоты выборки получают больше данных за фиксированный период времени, что обеспечивает более точное отображение исходного сигнала. Например, преобразование сигнала с частотой 1 КГц позволяет сделать 1000 выборок в секунду. Преобразование сигнала с частотой 10 Гц позволяет сделать 10 выборок в секунду. Частота 1 КГц обеспечивает значительно более корректное представление исходного сигнала по сравнению с частотой 10 Гц. Чем выше частота вы90
борки, тем более детализированным и точным будет восстановленный сигнал. Недостаточная частота выборки может привести к тому, что исходный аналоговый сигнал будет неправильно оцифрован, так как частота сигнала будет отлична от действительной. Возникает эффект наложения частот (aliasing). Необходимо производить выборки сигнала на частоте, которая будет больше удвоенной максимальной частоты сигнала в соответствии с теоремой Котельникова — Найквиста. Данная частота является минимальной, при которой сигнал можно представить без эффекта наложения частот. Параметры систем АЦП: разрядность, диапазон и усиление. Разрядность — количество бит, применяемых для отображения аналогового сигнала. Данный показатель определяет разрешающую способность АЦП. Если устройство обладает большей разрядностью, оно разделяет рабочий диапазон АЦП на большее количество частей, что позволяет детальнее передать исходный аналоговый сигнал. АЦП с 3 битами делит диапазон значений на 23 = 8 частей. Каждая часть представлена в виде дискретного трехразрядного цифрового кода от 000 до 111. На рисунке 3.27 представлена дискретная синусоида, которая получена с помощью трехбитного АЦП. Цифровой сигнал не полностью передает исходный аналоговый сигнал, поскольку дискретное представление накладывает определенные ограничения. При повышении разрешающей способности, например, до 16 бит, количество возможных делений увеличивается с 8 (2 3) до 65536 (216), что позволяет достигать высокой точности при отображении исходного аналогового сигнала. Рабочий диапазон — это диапазон напряжений аналогового сигнала, который может быть оцифрован с помощью АЦП. Разные АЦП могут использовать различные рабочие диапазоны. Они могут быть только положительными (диапазон от 0 до 10 В), а могут быть положительными и отрицательными (диапазон от –10 до 10 В). Нижняя и верхняя граница диапазона называется опорным напряжением. Диапазон значений зависит от конкретной задачи. Если исходный аналоговый сигнал меняется в диапазоне от –1 до 1 В, то не имеет смысла использовать рабочий диапазон АЦП больше этого диапазона. Нужно отметить еще одну особенность рабочего диапазона. Меньший диапазон позволяет получить более точные дискретные значения. Например, трехбитное АЦП имеет 8 возможных уровней напряжения. Если использовать рабочий диапазон от 0 до 1 В, то дискретный шаг между измерениями составит 0,125 В. Если использовать рабочий диапазон от –1 до 1 В, то дискретный шаг между измерениями составит 0,25 В. Понятно, что точность измерений во втором случае будет хуже. Правда, последний вариант позволит оцифровку сигнала, который может принимать отрицательные значения. Усиление. Для оптимизации сигнал может быть предварительно усилен или ослаблен. Изменяя уровень сигнала, можно контролировать диапазон входных данных АЦП, что позволит использовать максимально возможное количество доступных разрядов. Например, на трехбитовом АЦП с диапазоном 0–10 В сигнал изменяется в диапазоне от 0 до 5 В. Если не применять усиление (КУ = = 1), то АЦП будет использовать лишь часть из доступных разрядов. Если уси91
лить исходный сигнал в 2 раза (КУ = 2), то при оцифровке сигнала будут использованы все доступные разряды АЦП. Рис. 3.27 Цифровой сигнал синусоиды при 3 и 16 бит разрядности АЦП последовательного приближения. Принцип работы данного преобразователя основан на работе регистра последовательных приближений и микросхемы цифро-аналогового преобразователя (ЦАП). На рисунке 3.28 представлена блок-схема преобразователя. Рис. 3.28 Схема восьмиразрядного АЦП последовательного приближения В начале цикла преобразования все 8 бит устанавливаются в нуль с помощью регистра последовательных приближений. На следующем этапе каждый бит устанавливается в единицу, начиная со старшего. Полученное цифровое значение поступает на вход ЦАП, где сигнал преобразуется в аналоговый. Значение аналогового сигнала сравнивается компаратором с входным опорным напряжением. Если входное значение больше опорного напряжения, то на выходе компаратора формируется единица, если наоборот, то происходит формирование нуля. Полученный разряд сохраняется в регистре данных. Цикл завер92
шается после заполнения последнего разряда. На рисунке 3.29 представлен пример диаграммы преобразования АЦП последовательного приближения. Рис. 3.29 Диаграмма преобразования АЦП последовательного приближения Достоинством подобной схемы является простота и надежность схемы преобразования. Из недостатков можно отметить то, что подобный подход имеет низкую скорость преобразования, если сравнивать с другими видами преобразователей. Параллельное АЦП. Данный вид АЦП является одним из самых быстрых. Принцип работы параллельного преобразователя следующий. В случае n-разрядного АЦП входное напряжение подается одновременно на 2n – 1 компараторов. Компараторы практически одновременно сравнивают входное напряжение с определенным опорным уровнем, как это показано на рисунке 3.30. Компараторы выполняют кодирование разрядов. Когда входное напряжение больше или равно опорному, то на выходе компаратора формируется логическая единица, в ином случае логический нуль. Далее полученные значения будут транслированы в цифровой код с помощью шифратора. Обычно параллельные преобразователи ограничены небольшим количеством разрядов на выходе, так как при увеличении количества разрядов их стоимость и габариты становятся значительно выше. Чтобы снизить затраты, применяются последовательно параллельные АЦП, которые используют комбинированный подход; однако это приводит к снижению скорости обработки сигналов по сравнению с параллельными АЦП. Интегрирующий АЦП. Принцип работы данного преобразователя основан на использовании интегратора. АЦП данного типа обладают множеством преимуществ, включая высокое разрешение, отличную линейность и способность эффективно подавлять шумы благодаря усреднению. Тем не менее, у них есть и значительный недостаток — низкая скорость преобразования. В связи с этим интегрирующие АЦП в основном находят применение в цифровых вольтметрах и других устройствах, которые не требуют частых измерений. Дельта-сигма АЦП. Принцип работы данного преобразователя основан на использовании децимации в сочетании с фильтрами. Оцифровка сигнала происходит не в точке, а на определенном диапазоне, то есть для усредненного значения в диапазоне. Эти устройства предлагают очень высокую частоту дискретизации, высокую точность и лучшую линейность по сравнению с другими типами АЦП. 93
Рис. 3.30 Схема параллельного АЦП 3.9. Цифро-аналоговый преобразователь Рассмотрим принцип работы и устройство цифро-аналогового преобразователя. Цифро-аналоговый преобразователь (ЦАП, на англ. DAC) — устройство, которое преобразует последовательность цифровых кодов в непрерывный аналоговый сигнал. Можно сказать, что устройство выполняет функцию, которая обратна АЦП. Основной принцип преобразования заключается в суммировании входных токов, соответствующих числу разрядов входного цифрового кода. Далее суммарный ток будет преобразован в напряжение с помощью операционного усилителя, используя отрицательную обратную связь. Операционный усилитель создает разность потенциалов на своих входах, которая пропорциональна разности токов, протекающих через его входы. На рисунке 3.31 представлена общая схема преобразования выходного тока ЦАП в напряжение. Рис. 3.31 Общая схема преобразования на микросхеме ЦАП и операционного усилителя Для получения токов могут быть использованы транзисторные источники тока или резистивные матрицы. На рисунке 3.32 показано 4-разрядное ЦАП 94
с использованием резистивной матрицы R-2R. На схеме использованы обычные ключи для переключения разрядов. В реальности в качестве ключей используются транзисторные ключи. Рис. 3.32 Схема четырехразрядного ЦАП с использованием резистивной матрицы R-2R Вклад напряжения от первого ключа составляет UREF/2, для второго ключа UREF/4, для третьего UREF/8 и для четвертого UREF/16 соответственно. Для определения выходного напряжения можно воспользоваться формулой Uвых = = –N UREF 2–n, где n — количество разрядов входного кода, N — десятичный эквивалент двоичного кода. Знак минус говорит о том, что операционный усилитель инвертирует выходной сигнал. 95
ГЛАВА 4 МИКРОПРОЦЕССОРНЫЕ СИСТЕМЫ 4.1. Построение микропроцессорных систем 4.1.1. Микропроцессор и микропроцессорные системы Микропроцессор (МП), или центральный процессор (ЦП) (Central Processing Unit — CPU), — это устройство, которое осуществляет прием, обработку и выдачу информации. Процессор — это элемент, который управляет вычислительной системой согласно заданной программе, записанной в памяти. Управление системой осуществляется посредством электрических сигналов, передаваемых по линиям связи, которые называются шинами. Конструктивно МП содержит одну или несколько интегральных схем. На рисунке 4.1 показан пример микропроцессора Intel Core I7. На рисунке 4.2 представлен внутренний вид микропроцессора. Рис. 4.1 Внешний вид микропроцессора Рис. 4.2 Внутренний вид микропроцессора Микропроцессорная система — это вычислительная, контрольноизмерительная или управляющая система, основным устройством обработки информации в которой является МП. Под вычислительной системой понимается совокупность различных элементов и узлов, предназначенных для обработки информации. Простейшая микропроцессорная система состоит из процессора, памяти и устройств ввода/вывода (рис. 4.3). Перед началом изучения микропроцессорных систем необходимо ознакомиться с некоторыми основными определениями: – электронная система — это электронный узел, блок, прибор или комплекс, предназначенный для обработки информации; – задача — это набор функций, которые выполняет электронная система; – быстродействие — это показатель скорости выполнения электронной системой ее функций; – гибкость — это способность электронной системы подстраиваться под различные задачи; 96
– интерфейс — соглашение об обмене информацией, правила обмена информацией, подразумевающие электрическую, логическую и конструктивную совместимость устройств. Рис. 4.3 Структура микропроцессорной системы Основные структурные элементы процессора: арифметико-логическое устройство (АЛУ, ALU — Arithmetic Logic Unit), внутренние регистры, мультиплексоры, буферы, регистры и другие узлы. АЛУ является ключевым элементом, так как определяет разрядность всей микропроцессорной системы в целом. Поскольку процессор является цифровым устройством, то для синхронизации всех узлов системы используется общий внешний тактовый сигнал процессора. На рисунке 4.4 представлена типичная структура простейшего процессора. В следующих разделах мы подробно рассмотрим каждый блок этой схемы. Рис. 4.4 Структура простейшего процессора 97
Все микропроцессорные системы можно условно разделить на несколько типов. Каждый тип устройств имеет вычислительную мощность, универсальность, быстродействие и структурные отличия. Основные типы следующие: – микроконтроллеры — наиболее простой тип микропроцессорных систем, в которых все или большинство узлов системы выполнены в виде одной микросхемы; – контроллеры — управляющие микропроцессорные системы, выполненные в виде отдельных модулей; – микрокомпьютеры — более мощные микропроцессорные системы с развитыми средствами сопряжения с внешними устройствами; – компьютеры — самые мощные и универсальные микропроцессорные системы. Микроконтроллер Контроллер Микрокомпьютер Компьютер Использование конкретного типа микропроцессорной системы можно ограничить кругом выполняемых задач и скоростью выполнения программ. Например, нет необходимости использовать сложную систему для получения и обработки информации от датчика. В данном случае можно ограничиться микроконтроллером. И наоборот, при решении сложных задач нужно использовать только мощные микропроцессорные системы. 4.1.2. Классическая и шинная структура связей В настоящее время наиболее распространенными являются микропроцессорные системы с двумя типами связей устройств: классическая и шинная структура. Классическая структура связей (рис. 4.5) — это структура, при которой все устройства в микропроцессорной системе подключены по отдельным линиям связи. Передача сигнала и кодов осуществляется независимо от других устройств в системе, что существенно ускоряет скорость работы. Недостатком такой системы является отсутствие универсального протокола обмена данными между устройствами. Кроме того, структура имеет сложную архитектуру, сложность которой возрастает с увеличением количества устройств в системе. Шинная структура связей (рис. 4.6) — это структура, при которой все устройства в микропроцессорной системе подключены к общей линии связи (системная магистраль). Передача сигнала и кодов осуществляется по одним линиям связи, но в разное время (мультиплексирование данных). 98
Рис. 4.5 Классическая структура связей Рис. 4.6 Шинная структура связей При шинной структуре нет необходимости использовать множество различных протоколов обмена информацией. Все узлы в системе унифицированы. Недостатком системы, по сравнению с классической структурой, является снижение скорости передачи данных. Существенный недостаток шинной структуры связан с параллельным подключением устройств. Неисправность одного устройства, нарушающего работу магистрали, выводит из строя всю систему. В системах с шинной структурой связей применяют следующие три существующие разновидности выходных каскадов цифровых микросхем (рис. 4.7): – выход с двумя состояниями (2С, 2S, ТТЛ, TTL); – выход с открытым коллектором (ОК, OC); – выход с тремя состояниями (обозначается 3С, 3S). Рис. 4.7 Типы выходных каскадов 99
Выход 2С имеет два ключа, каждый из которых замыкается по очереди. При логической единице замкнут верхний ключ, а при логическом нуле замкнут нижний. Выход ОК имеет один ключ. Замкнутый ключ формирует уровень логического нуля, разомкнутый — логической единицы. Ключи выхода 3С могут замыкаться по очереди, а могут размыкаться одновременно, образуя третье состояние под управлением сигнала EZ (высокоимпедансное состояние). 4.1.3. Режимы работы микропроцессорных систем Существует три основных режима обмена данными по системной магистрали: – программный обмен информацией; – обмен с использованием прерываний (Interrupts); – обмен с использованием прямого доступа к памяти (ПДП, DMA — Direct Memory Access). Программный обмен информацией. При таком режиме работы процессор является единоличным исполнителем (задатчик) команд на системной магистрали. Все операции обмена информацией инициируются только процессором, все они выполняются строго в порядке, предписанном исполняемой программой. Порядок выполнения программы может быть линейным, циклическим, может содержать переходы (прыжки), но он всегда непрерывен (рис. 4.8). Все сигналы на магистрали в данном случае контролируются процессором. Рис. 4.8 Программный обмен информацией Обмен с использованием прерываний (Interrupts). Прерывание — это реакция микропроцессорной системы на внешнее событие. Внешним событием может быть, например, нажатие клавиши на клавиатуре, сигнал от внешнего устройства, приход пакета данных по локальной сети. При обслуживании прерывания процессор заканчивает выполнение текущей команды из основной команды и обращается в область памяти, где записана программа обработки прерываний. Последовательно выполнив все команды в этой области, процессор возвращается к выполнению команд из основной программы (рис. 4.9). 100
Рис. 4.9 Обмен с использованием прерываний (Interrupts) Иногда для упрощения работы системы используют контроллер прерываний, который не участвует в обмене информацией, но используется процессором для обработки внешних прерываний. Прямой доступ к памяти (ПДП, DMA). Прямой доступ к памяти — это режим работы микропроцессорной системы, при котором обмен данными по системной магистрали идет без участия процессора. Рис. 4.10 Обмен данными по системной магистрали в режиме ПДП При обмене данными (рис. 4.10) процессор заканчивает выполнение текущей команды и отключается от системной магистрали. Процесс обмена данными между памятью и устройством ввода/вывода осуществляется напрямую. К магистрали подключается специальное устройство для работы системы — контроллер ПДП. 4.1.4. Архитектура микропроцессорных систем Принстонская (фон-неймановская) архитектура (рис. 4.11) — это микропроцессорная система с общей шиной данных и команд. Данная архитектура проще, не требуется обработка данных по двум шинам. Наличие единой памяти данных и команд позволяет гибко перераспределять память в системе. Память может быть большого объема, что позволяет решать задачи различной сложности. 101
Гарвардская архитектура (рис. 4.12) — это микропроцессорная система с раздельной шиной данных и команд. Подобная архитектура сложнее, требует обработки данных по двум шинам одновременно, процессор работает с двумя потоками. Наличие двух шин подразумевает использование двух областей памяти: память данных и память команд. Программа размещается только в памяти команд, данные — в памяти данных. Данный подход существенно сокращает круг решаемых задач. Рис. 4.11 Архитектура с общей шиной данных и команд (Принстонская архитектура) Рис. 4.12 Архитектура с раздельной шиной данных и команд (Гарвардская архитектура) Основным преимуществом двухшинной архитектуры является высокое быстродействие системы. Например, использование двух шин в микроконтроллерах, где не требуется выполнение сложных задач, но требуется высокое быстродействие. 4.2. Передача информации в микропроцессорных системах 4.2.1. Шины микропроцессорных систем Шина — это информационный канал, который объединяет все блоки микропроцессорной системы и обеспечивает обмен данными в виде цифрового кода. Системная магистраль (System Bus) — это совокупность трех основных шин микропроцессорной системы: шина данных, шина адреса и шина управления. Шина данных (Address Bus) является двунаправленной и предназначена 102
для передачи данных между различными блоками системы. Разрядность шины данных определяет размерность всей системы в целом. Шина адреса (Data Bus) является однонаправленной и предназначена для передачи адреса ячейки памяти или устройства ввода/вывода. Шина управления (Control Bus) предназначена для передачи управляющих сигналов. Управляющие сигналы также обслуживают запрос и предоставление прерываний, запрос и предоставление прямого доступа к памяти. Для управления сигналами используются стробы обмена, которые определяют начало и конец пересылки данных по шине данных. Наиболее часто используемые стробы: – строб записи (вывода) — момент времени для начала приема данных устройством-исполнителем; – строб чтения (ввода) — момент времени для начала приема данных процессором. Существует два способа обмена данными между процессором и устройством-исполнителем: асинхронный и синхронный режимы передачи данных (рис. 4.13). Рис. 4.13 Синхронный и асинхронный обмен При синхронном обмене процессор заканчивает обмен данными через определенный интервал времени (tвыд.). При таком режиме не учитывается скорость работы устройства-исполнителя. Существует высокая вероятность потери данных. При асинхронном обмене процессор заканчивает обмен только после получения от устройства исполнителя специального строба подтверждения. Вероятность потери данных при таком обмене минимальна. Для снижения линий связи шины адреса и шины данных могут быть использованы в режиме мультиплексирования. По мультиплексированной шине можно передавать адрес и данные. Немультиплексированная шина способна передавать данные только определенного типа (рис. 4.14). Рис. 4.14 Мультиплексированные и немультиплексированные шины 103
Существуют типы системных магистралей, которые можно использовать в режиме частичного мультиплексирования. В этом случае часть разрядов передается по немультиплексированным линиям. Подобный режим работы позволяет повысить скорость магистрали. 4.2.2. Циклы программного обмена информацией Рассмотрим примеры циклов программного обмена на магистрали Q-bus (мультиплексированная асинхронная магистраль) и ISA (немультиплексированная синхронная магистраль с возможностью асинхронного обмена). Теперь подробнее рассмотрим реализацию программного обмена. На магистрали Q-bus. На рисунке 4.15а представлен цикл обмена при чтении и записи данных. Весь цикл делится на 2 фазы: фаза адреса и фаза данных. Отличие двух режимов заключается в том, что при чтении на шине AD адрес данных будет установлен в фазе адреса, а сами данные будут переданы в фазе данных. При записи данных запись данных начинается в фазе адреса. Кроме того, для обмена информацией используются три дополнительных сигнала управления: отрицательный строб -SYNC, строб чтения -DIN и строб -RPLY. Адрес на шину адреса/данных выставляет процессор. Строб -SYNC, выставляемый процессором, предназначен для стробирования адреса. Строб чтения -DIN выставляется процессором и сигнализирует устройству о начале передачи данных (чтении данных от устройства исполнителя). Строб -RPLY является сигналом от устройства исполнителя процессору о том, что передача данных окончена. Аналогично реализуется цикл записи, только вместо сигнала -DIN используется сигнал -DOUT и передача данных происходит от процессора к исполнительному устройству. Рис. 4.15а Циклы программного обмена магистрали Q-bus 104
На магистрали ISA. На рисунке 4.15б представлен цикл обмена при чтении и записи данных. Весь цикл делится на 2 фазы: фаза адреса и фаза данных. Существенным отличием от режима передачи данных на магистрали Q-bus является то, что адрес и данные передаются по двум разным шинам SA и SD. Рис. 4.15б Циклы программного обмена на магистрали ISA Рассмотрим отличие режимов чтения и записи. Для обмена информацией используются два дополнительных сигнала управления: отрицательный строб чтения -IOR (в случае записи -IOW) и строб I/O CH RDY. Адрес данных выставляется процессором в фазе адреса и заканчивается в фазе данных. Чтение и запись самих данных происходит исключительно в фазе данных. Строб -IOR сигнализирует о начале передачи данных от устройства к процессору. Строб -IOW сигнализирует о начале передачи данных от процессора к устройству. Строб I/O CH RDY — сигнал для реализации режима асинхронного обмена (при синхронном объекте всегда положительный). 4.2.3. Циклы обмена информацией по прерываниям Циклы обмена по прерываниям похожи на циклы программного обмена, но имеют ряд особенностей. Прерывания в микропроцессорных системах можно разделить на 2 типа: векторные и радиальные. Векторные прерывания требуют проведение цикла чтения по магистрали, радиальные прерывания исключают данный подход. Рассмотрим пример реализации циклов обмена информацией по прерываниям на магистрали Q-bus (рис. 4.16а) и ISA (рис. 4.16б). Векторные прерывания на магистрали Q-bus. При таком режиме реализуется процесс последовательного опроса каждого устройства на необходимость прерывания. Процессор выставляет сигнал IAKO, который проходит через все устройства. Если устройству требуется прерывание, то оно перехватывает данный сигнал и выставляет на системную магистраль сигнал VIRQ. Если 105
в системе будет одновременно несколько запросов на прерывание, то первым обработается для того устройства, которое ближе всего к процессору (использование географического приоритета). После обработки прерываний устройство снимает сигнал VIRQ с магистрали. Рис. 4.16а Циклы обмена информацией по прерываниям на магистрали Q-bus Рис. 4.16б Циклы обмена информацией по прерываниям на магистрали ISA Радиальные прерывания на магистрали ISA. При таком режиме прерывания не требуется проведение цикла чтения по магистрали. В системе присутствует специальное устройство — контроллер прерываний. Именно это устройство позволяет связать процессор и все устройства системы без их непосредственной связи. Запросом на прерывание является сигнал IRQ, который выставляется устройством и будет обработан контроллером прерываний. На одну линию для сигнала IRQ приходится одно устройство. Преимущества и недостатки. Векторные прерывания обладают большей гибкостью по сравнению с радиальными, не требуют дополнительных аппаратных узлов. Радиальные прерывания имеют более сложную архитектуру, но работать с ними проще, так как для реализации прерываний потребуется использование единственного управляющего сигнала. 106
4.2.4. Циклы обмена информацией в режиме ПДП Циклы обмена информацией в режиме ПДП похожи на циклы программного обмена и циклы обмена по прерываниям. В режиме ПДП устройство напрямую обменивается данными с памятью. Рассмотрим пример реализации циклов обмена информацией в режиме ПДП на магистрали Q-bus (рис. 4.17а) и ISA (рис. 4.17б). При изучении данного режима можно проследить аналогию с циклами обмена информацией по прерываниям. Рис. 4.17а Циклы обмена информацией в режиме ПДП на магистрали Q-bus Рис. 4.17б Циклы обмена информацией в режиме ПДП на магистрали ISA Обмен информацией на магистрали Q-bus. Данный режим предусматривает последовательный опрос процессором всех устройств в системе с помощью сигнала DMGO. Получив этот сигнал, устройство, которому требуется прерывание, выставляет на магистраль сигнал DMR. Далее процессор переходит в режим обмена информацией в режиме ПДП и отключается от системной магистрали. Обмен информацией на магистрали ISA. В системе должен обязательно присутствовать контроллер ПДП, который позволяет осуществить связь устройства и памяти. Управляющие сигналы: DRQ-запрос на прерывание, DACK-предоставление прямого доступа к памяти без участия процессора. 107
4.3. Функции устройств магистрали В микропроцессорных системах можно выделить основные структурные единицы: микропроцессор, память, устройства ввода/вывода. Каждая единица выполняет определенные функции. Все устройства способны взаимодействовать через системную магистраль, которая является проводником для передачи адреса и данных. Далее будут рассмотрены функции этих устройств более подробно. 4.3.1. Функции процессора Процессор — это микросхема (или часть микросхемы), которая выполняет прием, обработку и выдачу информации согласно заданной программе в системе. Можно сказать, что процессор является неким «мозговым центром» всей микропроцессорной системы. Важнейшими характеристиками процессора являются его шина адреса, шина данных и шина управления. Шина адреса — шина, выделенная для передачи адресной информации. Основной характеристикой шины является ее разрядность. Именно разрядность в битах определяет объем адресуемой памяти. Объем адресуемой памяти будет определяться соотношением 2N, где N — ширина адресной шины в битах. Например, 16-разрядная шина обеспечивает 65 536 адресов. Шина может быть одно- или двунаправленной. Шина данных — основная шина микропроцессорной системы, которая определяет скорость и эффективность при обмене информацией. Число разрядов системы определяет количество максимально доступных команд процессора. Шина всегда двунаправленная, может иметь 8, 16, 32 или 64 разряда. Разрядность шины данных определяет разрядность системной магистрали. Шина управления — шина, на которой формируются управляющие сигналы и определяется тип цикла обмена информацией. Кроме того, шина управления позволяет согласовать работу процессора с другими устройствами на магистрали в режиме «ведущий-ведомый». Шина может быть одно- или двунаправленной. Среди управляющих сигналов можно выделить стробы обмена информацией: строб записи и строб чтения. На рисунке 4.18 представлена схема подключения процессора к системной магистрали. Кроме трех основных шин, подключенных к процессору, необходимо рассмотреть другие выводы, предназначенные для управления процессором. CLK — вывод для подключения внешнего тактового сигнала, поскольку процессор является тактируемым устройством. RESET — сигнал начального сброса. Нужен в случае аварийной ситуации. Ucc — шина питания процессора, а GND — узел цепи с потенциалом, равным нулю. Важной частью системы являются буферные элементы, которые используют для связи процессора с системной магистралью, а также для согласования протоколов обмена. На рисунке 4.19 представлена упрощенная структура процессора. Рассмотрим подробнее структурные элементы на схеме. 108
Рис. 4.18 Схема подключения процессора Рис. 4.19 Структура микропроцессора Арифметико-логическое устройство (АЛУ). АЛУ предназначено для обработки информации процессором в соответствии с полученной командой. Могут выполняться логические операции (И, ИЛИ, НЕ, И-НЕ), арифметические операции (+, –, *, /). Разрядность АЛУ называют внутренней разрядностью микропроцессора. Схема управления выборкой команд. Схема управления выборкой команд выполняет чтение команд из памяти микропроцессорной системы и их дешифрацию. В подобных системах для повышения скорости работы используется конвейер, который позволяет записать в небольшую память сразу несколько команд. Принцип работы конвейера основан на FIFO (first in — first out). Первая принятая в память команда будет выполнена первой. Во внутренней структуре процессора конвейер — это кэш-память. Схема управления прерываниями. Поступающий запрос на прерывание определяет адрес начала программы обработки прерывания. Текущее со109
стояние регистров сохраняется в стеке. Подробнее стек будет рассмотрен в разделе о памяти. Схема управления ПДП. Система управления прямого доступа к памяти используется тогда, когда необходимо реализовать обмен информацией между памятью системы и устройством ввода/вывода. Логика управления. Логика управления предназначена для организации работы всех узлов процессора как единой системы. Синхронизирует работу процессора с внешними сигналами и ввод/вывод информации. Регистр признаков (Processor Status Word). Каждый бит PSW (флаг) хранит информацию о результатах выполнения предыдущих операций. Например, PSW используется при обработке команды прерывания и сохранения промежуточных результатов выполнения программы. Напоследок выделим 7 основных функций процессора: выборка (чтение) выполняемых команд, ввод (чтение) данных из памяти или устройства ввода/вывода, вывод (запись) данных в память или в устройства ввода/вывода, обработка данных (операндов), адресация памяти, обработка прерываний, обработка режима прямого доступа. 4.3.2. Функции памяти Память микропроцессорной системы выполняет функцию временного или постоянного хранения данных и команд. Модули памяти чаще всего выполнены в виде микросхемы памяти. Память может быть оперативной или постоянной. Отличие оперативной памяти от постоянной заключается в том, что скорость передачи информации значительно выше, но всегда существует опасность потери данных при отключении питания микросхемы. Последнее время в микропроцессорных системах широко используется flash-память. Она является энергонезависимой памятью с возможностью многократной перезаписи. Информация в памяти хранится в ячейках: количество разрядов ячейки памяти = количеству разрядов шины данных, а количество ячеек памяти = 2N, где N — количество разрядов шины адреса. В одном разряде может храниться 0 или 1. Минимальной единицей измерения памяти является бит. Последовательность из 8 бит называется 1 байт. Пространство памяти — совокупность ячеек памяти системы. Рассмотрим наиболее часто используемые единицы памяти в настоящее время. 210 220 230 240 или 1024 байт (Кбайт) или 1 048 576 байт (Мбайт) – (Гбайт) – (Тбайт) Рассмотрим небольшую задачу на формирование пространство памяти. Если память имеет 65 536 ячеек, каждая из которых 16-разрядная, то говорят, что память имеет объем 128 Kбайт. На рисунке 4.20 показана схема подключения памяти к системной магистрали. 110
Рис. 4.20 Схема подключения памяти к системной магистрали Для подключения памяти к системной магистрали используются специальные модули сопряжения: селектор адреса (дешифратор), схема управления и буферные элементы. Селектор адреса определяет диапазон адресов, отведенных именно этому модулю памяти. В схеме управления генерируются два управляющих сигнала: CS — сигнал разрешения работы памяти, WR — сигнал разрешения записи данных в память. Через буферные элементы осуществляется передача самих данных. Рассмотрим частный случай памяти, который называется стек (рис. 4.21). Стек — это часть оперативной памяти, которая работает по принципу LIFO (last in — first out). Данные, которые были записаны в память последними, будут прочитаны первыми. Основные команды для управления стековой памятью: PUSH — запись в стек, POP — чтения из стека. Рис. 4.21 Принцип работы стека (Stack) Пример использования стековой памяти. Допустим, что у нас есть программа, в которой используется подпрограмма. В этом случае данные основной программы будут храниться в глубине стека, а данные подпрограммы — 111
в начале. Первыми будут прочитаны данные подпрограммы, а потом данные основной программы. Еще одной важной характеристикой памяти микропроцессорной системы является возможность реализации таблицы векторов прерываний. Существуют два вида прерывания работы микропроцессорной системы (основных): програм-мное и аппаратное. Программное прерывание возникает в случае необходимого вызова подпрограммы. Аппаратное прерывание возникает в результате возникновения запроса внешними устройствами. На рисунке 4.22 представлена схема обработки прерываний через таблицу векторов. Рис. 4.22 Обработка прерываний через таблицу векторов Прерывание в микропроцессорных системах обрабатывается через таблицу векторов прерываний. Процессор, получив запрос на прерывание, заканчивает выполнение текущей команды, сохраняя результат промежуточных вычислений в стеке. По известному номеру запроса на прерывание в таблице векторов прерываний будет определен адрес программы обработки прерываний. После выполнения данной программы процессор возвращается к выполнению основной программы. 4.3.3. Функции устройств ввода/вывода Устройства ввода/вывода позволяют процессору обмениваться информацией с внешними устройствами (периферийные устройства). Отличительная особенность подобных устройств от памяти заключается в том, что память не может обмениваться данными с внешними устройствами, а может взаимодействовать исключительно с процессором и магистралью. На рисунке 4.23 представлена схема подключения устройства ввода/вывода к системной магистрали. При анализе данной схемы можно проследить некоторую аналогию с подключением памяти к системной магистрали. Селектор адресов определяет адрес в памяти для принятых данных. Схема управления генерирует два сигнала C и OE, которые разрешают прием и передачу данных. Данные от внешнего устройства принимаются через буферные элементы. Для отправки данных используются буферные элементы и регистры. 112
Рис. 4.23 Схема подключения устройства ввода/вывода к системной магистрали Существуют одно- и двунаправленные порты вводы/вывода. Рассмотрим специальные группы устройств ввода/вывода: – устройства интерфейса пользователя — предназначены для ввода/вывода информации от пользователя; – устройства для длительного хранения информации — предназначены для ввода/вывода информации на носители и переносимые устройства; – таймерные устройства — предназначены для формирования временных интервалов, подсчета импульсов и др. Дополнительно можно отметить возможность сопряжения микропроцессорных устройств с информационными сетями и сопряжение с устройствами аналого-цифрового (АЦП) и цифро-аналогового преобразователя (ЦАП). 4.4. Адресация операндов Основную часть команд процессор выполняет над кодами данных, которые называются операндами. В системе обязательно должны присутствовать входные и выходные операнды. Входные операнды принято называть операндами-источниками, а выходные — операндами-приемниками. Операнды могут располагаться во внутренних регистрах процессора, памяти и устройствах ввода/вывода. Местоположение операнда определяется кодом команды. Методы, при помощи которых определяется начальное и конечное положение операндов, называется методом адресации. Далее будут рассмотрены наиболее распространенные методы адресации. 4.4.1. Методы адресации Непосредственная адресация. При непосредственной адресации операнд в памяти находится непосредственно за кодом команды. На рисунке 4.24 представлен пример непосредственной адресации. 113
Рис. 4.24 Непосредственная адресация Прямая или абсолютная адресация. Операнд находится в памяти по адресу, код которого находится внутри программы сразу же после кода команды. На рисунке 4.25 представлен пример абсолютной адресации. Рис. 4.25 Прямая (абсолютная) адресация Регистровая адресация. Операнд находится во внутреннем регистре процессора. На рисунке 4.26 представлен пример абсолютной адресации. Рис. 4.26 Регистровая адресация Косвенно-регистровая адресация. Во внутреннем регистре процессора находится не сам операнд, а его адрес в памяти. На рисунке 4.27 представлен пример абсолютной адресации. Рис. 4.27 Косвенно-регистровая адресация 114
Кроме того, необходимо отметить еще 2 очень важных метода адресации: автоинкрементная и автодекрементная адресация. Эти методы адресации очень близки к косвенной адресации. Отличие заключается в том, что для АИ после выполнения команды содержимое регистра увеличивается на 1, а для АД содержимое регистра уменьшается на 1. 4.4.2. Сегментирование памяти Сегментирование памяти системы — это процесс разбиения памяти на заданное количество частей заданного размера, которые называются сегментами. Положение сегментов в памяти можно задать программным путем. На рисунке 4.28 представлена схема формирования сегмента в памяти. Рис. 4.28 Формирование физического адреса сегмента В данном случае для формирования физического адреса памяти используется исполнительный адрес и адрес сегмента. Обратите внимание, что в данном случае требуется сегментирование памяти по причине того, что внутренние регистры процессора имеют 16 разрядов, а физический адрес памяти 20-разрядный. 4.4.3. Адресация байтов и слов Современные микропроцессорные системы позволяют адресовать не только целое слово в памяти, но и отдельные байты. При этом каждому байту будет соответствовать свой адрес. На рисунке 4.29 представлена схема адресации целых слов и отдельных байтов. Рис. 4.29 Адресация байтов и слов 115
Рассмотрим подробнее процесс адресации для приведенной выше схемы. В данном случае все слова в памяти имеют только четные адреса, а отдельные байты могут иметь четные или нечетные адреса. Как же поступить в том случае, если слово и отдельные байты имеют одинаковый адрес? Для этого были придуманы различные команды для процессора. В случае обращения к целому слову процессор будет использовать команду «адресующее слово, а при обращении к отдельным байтам — команду «адресующий байт». 4.5. Система команд процессора В системе команд процессора можно выделить четыре основные группы команд для обработки данных: команды пересылки данных, арифметические команды, логические команды, команды перехода. Команды пересылки данных предназначены для пересылки операндов из одной области в другую. В данном случае операнды могут располагаться в регистрах процессора, памяти или устройствах ввода/вывода. Арифметические команды предназначены для выполнения определенных операций над операндами. Обычно на входе имеется два операнда (или один), а на выходе — результат арифметической операции в виде одного операнда. Используемые арифметические операции: сложение, вычитание, умножение, деление, инкрементирование. Логические команды предназначены для выполнения логических операций над операндами. На входе может быть один или два операнда, а на выходе один операнд. Используемые логические операции: логическое И, логическое ИЛИ, логическое И-НЕ, исключающее ИЛИ, логическая инверсия, различные сдвиги (арифметические или логические), очистка операндов через код маски. Необходимо отметить, что при выполнении определенной команды происходит изменение состояния битов (флаги) регистра PSW. Возможно изменение состояния всех битов или изменение только определенной части, что определяется типом конкретного процессора. 4.5.1. Команды пересылки данных Ранее было сказано, что команды пересылки данных не выполняют операций над операндами, а могут только пересылать данные из разных областей. АЛУ процессора в данном случае не используется. Рассмотрим основные функции КПД: • запись данных во внутренние регистры процессора; • сохранение данных в памяти; • копирование данных из одной области памяти в другую; • запись и чтение данных из/в устройство ввода/вывода. Виды команд пересылки данных: MOV — команда пересылки, LOAD — команда для загрузки, PUSH — команда сохранения в стек, POP — команда извлечения из стека. 116
4.5.2. Арифметические команды При выполнении арифметических операций операнды рассматриваются как двоичные или двоично-десятичные коды. Рассмотрим основные функции, которые выполняют арифметические команды: • операции над данными с фиксированной запятой; • операции над данными с плавающей запятой; • операция очистки данных; • команды инкремента и декремента; • команда сравнения. Виды арифметических команд: ADD — вычисление суммы двух кодов, SUB — вычисление разности двух кодов, MUL — умножение двух кодов, DIV — деление двух кодов, CLR — команда очистки, INC — команда инкремента, DEC — команда декремента, CMP — команда сравнения. 4.5.3. Логические команды Логические команды выполняют над операндами логические операции. На входе может быть один или два операнда, на выходе только один. В отличие от арифметических команд, логические команды рассматривают операнд как набор битов. Рассмотрим основные функции, которые выполняют логические команды: • логическое И, логическое ИЛИ, исключающее ИЛИ; • логические, арифметические и циклические сдвиги; • проверка битов и операндов (TST — для всего операнда, BIT — для некоторых битов операнда); • работа с битами (флагами) регистра состояния процессора (PSW). Примеры использования логических команд: операция AND — используется для очистки заданных битов (один из операндов является кодом маски, в котором разряды, требующие очистки, установлены в нуль), операция OR — используется для установки заданных битов (один из операндов является кодом маски, в котором разряды, требующие установки в единицу, равны единице), операция исключающее XOR — используется для инверсии заданных битов (один из операндов является кодом маски, в котором разряды, требующие инверсии, установлены в единицу). В результате применения операции XOR мы получим ответ для нового бита = 1, если число складываемых единичных битов нечетно, и = 0, если четно. Пример операция AND. Операнд Маска Результат Бит 0 1 0 0 Бит 1 1 1 1 Бит 2 1 0 0 Бит 3 1 1 1 117 Бит 4 1 0 0 Бит 5 1 1 1 Бит 6 1 0 0 Бит 7 1 1 1
Пример операция OR. Операнд Маска Результат Бит 0 1 1 1 Бит 1 0 1 1 Бит 2 1 0 1 Бит 3 0 0 0 Бит 4 1 1 1 Бит 5 0 1 1 Бит 6 1 0 1 Бит 7 0 0 0 Бит 2 1 0 1 Бит 3 0 0 0 Бит 4 1 1 0 Бит 5 0 1 1 Бит 6 1 0 1 Бит 7 0 0 0 Пример операция XOR. Операнд Маска Результат Бит 0 1 1 0 Бит 1 0 1 1 Теперь рассмотрим различные битовые сдвиги. Выделяют следующие виды логических сдвигов: логический сдвиг, арифметический сдвиг, логический сдвиг. При логическом сдвиге значение первого бита приобретает значение 0, а значение последнего бита теряется (переходит в бит переноса). Арифметический сдвиг аналогичен логическому, но учитывается знак. При циклическом сдвиге значение последнего бита копируется в первый бит и бит переноса. 4.5.4. Команды переходов Команды переходов используются тогда, когда необходимо нарушить последовательное выполнение программы. В этом случае используются различные циклы, ветвления и вызовы подпрограмм. Команды переходов можно разделить на два больших класса: команды безусловных и команды условных переходов. Команды безусловных переходов будут выполнены независимо от остальных условий программы. Команды условных переходов будут вызваны только в том случае, если выполнены заданные условия. Условия перехода: – переход, если ==, !=, >, < 0; – переход, если есть или нет переполнения. Рис. 4.30 Реализация команды условных переходов 118
На рисунке 4.30 представлен алгоритм выполнения программы с использованием команды условных переходов. Если условие перехода выполнено, то производится загрузка в регистр-счетчик команд нового значения, если же нет, то счетчик просто наращивается и выполняется следующая по порядку команда. Применение команд условного и безусловного перехода — для реализации разветвленных алгоритмов любой сложности. 4.5.5. Быстродействие процессора Быстродействие процессора — это характеристика, которая определяет эффективность работы всей микропроцессорной системы. Основные факторы, влияющие на быстродействие процессора: тактовая частота, разрядность, количество доступных команд, время выполнения коротких операций. Для количественной оценки производительности процессора первоначально использовались единицы измерения MIPS и FLOPS. MIPS (Mega Instructions Per Second) — соответствует миллиону выполняемых инструкций в секунду. Ориентация на самые быстрые команды. FLOPS (Floating Point Operations Per Second) — измерение производительности при выполнении вычислений с плавающей запятой за одну секунду. Необходимо отметить, что на производительность процессора будут влиять методы адресации, сегментирование памяти и методы взаимодействия процессора с устройствами ввода/вывода. 119
ГЛАВА 5 ПРОГРАММИРОВАНИЕ МИКРОКОНТРОЛЛЕРОВ 5.1. Архитектура микроконтроллеров Современное развитие микропроцессорных систем (МПС) характеризуется переходом от систем, построенных на основе нескольких интегральных схем, к однокристалльным микроконтроллерам. Такие микроконтроллеры объединяют на одном кристалле все ключевые элементы МПС: центральный процессор (ЦП), постоянное запоминающее устройство (ПЗУ), оперативное запоминающее устройство (ОЗУ), порты ввода/вывода, таймеры, ШИМ-генератор, компаратор, аналого-цифровой преобразователь и другие компоненты. Условно эти устройства можно разделить на три основные категории: 8-разрядные микроконтроллеры для встраиваемых приложений; 16- и 32-разрядные микроконтроллеры; а также цифровые сигнальные процессоры (DSP). Сегодня наиболее широко распространены семейства 8-разрядных микроконтроллеров, которые активно применяются в промышленности, бытовой технике и компьютерных устройствах. В процессе своего развития эти устройства эволюционировали от простых приборов с ограниченной периферией до современных многофункциональных контроллеров, способных выполнять сложные алгоритмы управления. Популярность 8-разрядных микроконтроллеров обусловлена постоянным расширением ассортимента продукции, выпускаемой ведущими компаниями, такими как Motorola, Microchip, Intel, Atmel, Siemens, Philips и другими. Современные микроконтроллеры обладают рядом отличительных особенностей. 1. Модульная организация: на основе единого процессорного ядра разрабатывается целое семейство микроконтроллеров. Различия между ними заключаются в объемах и типах памяти программ, объеме памяти данных, а также наборе периферийных модулей. 2. Закрытая архитектура: для таких микроконтроллеров характерно отсутствие линий магистралей адреса и данных на выводах корпуса. Вместо этого используются встроенные периферийные модули, такие как таймеры, контроллеры последовательных интерфейсов, аналого-цифровые преобразователи и другие. 3. Универсальность периферийных модулей: хотя эти модули могут незначительно отличаться у разных производителей, их основные функции остаются схожими. Типичная структура микроконтроллера, включающая стандартные периферийные модули, представлена на рисунке 5.1. Рассмотрим подробнее основные блоки, представленные на рисунке 5.1. Для примера будет подробно рассмотрена структура и принцип работы микроконтроллеров фирмы Microchip. Для начала рассмотрим организацию процес120
сорного ядра и памяти микроконтроллера. В последующих разделах будут рассмотрены все используемые в микроконтроллерах периферийные модули. Рис. 5.1 Модульная структура микроконтроллера 5.1.1. Процессорное ядро Микроконтроллеры PIC (от англ. peripheral interface controller — контроллер интерфейса периферии) оснащены процессорным ядром, построенным на основе RISC-архитектуры (от англ. restricted (reduced) instruction set computer — компьютер с сокращенным набором команд). Для такой архитектуры быстродействие системы достигается за счет упрощения инструкций, чтобы их декодирование было простым, а время выполнения — минимальным. Особенности RISC-архитектуры микроконтроллеров PIC: ЦП распознает только 35 простых инструкций; время выполнения инструкции длится в течение 4 тактов. Рис. 5.2 Взаимодействие ЦП с периферийными модулями МК 121
Для выполнения более сложных операций требуется комбинирование команд. При этом каждая команда имеет фиксированную длину (например, 12, 14 или 16 бит), а ее выборка из памяти и выполнение происходят за один такт синхронизации. 5.1.2. Организация памяти Большинство микроконтроллеров обязательно имеет три типа памяти: ROM (постоянное запоминающее устройство), RAM (оперативное запоминающее устройство) и EEPROM. Все они будут рассмотрены отдельно, так как каждая имеет свои функции, особенности и организацию. ПЗУ (ROM). Память ROM используется для постоянного хранения программы. Данная память выполнена с использованием флэш-технологии, поэтому ее содержимое может быть изменено специальным программируемым напряжением (13 В). Содержимое памяти может быть перезаписано с использованием ПК и программатора (рис. 5.3). Рис. 5.3 Процесс программирования flash-памяти микроконтроллера Память EEPROM. Содержимое памяти EEPROM сохраняется всегда, даже при отключении питания. В отличие от ПЗУ, содержимое EEPROM может быть изменено во время работы микроконтроллера. ОЗУ (RAM). Данный вид памяти микроконтроллера является самым сложным для изучения. Она состоит из двух частей: регистров общего назначения и регистров специальных функций (SFR). Регистры общего назначения (General Purpose Registers). Регистры общего назначения используются для хранения временных данных и результатов, полученных за время работы МК. Например, если выполняется программа суммы, то результат этой суммы будет сохраняться в отдельном регистре, из которого в любой момент результат может быть извлечен. Регистры специальных функций (Special Function Registers). В отличие от регистров общего назначения, их задачи определены заранее и не могут быть изменены пользователем. Их биты подключены к конкретным модулям на кристалле (АЦП, модуль последовательной связи и т. д.). Программируя регистры, пользователь программирует модуль. Например, регистры АЦП-преобразова122
теля позволяют определить аналоговый вход, включить или выключить модуль, задать разрядность и др. Особенностью этих ячеек памяти является то, что у них есть свои имена. Данная особенность позволяет упростить процесс написания программы, поскольку в языках программирования высокого уровня можно использовать список всех регистров с их точными адресами. Достаточно указать имя регистра, чтобы прочитать или изменить его содержимое. Стек (Stack). Область памяти, построенная по принципу LIFO (от англ. last in — first out, «последним пришел — первым ушел»). Данные, записанные в стек последними, будут извлечены первыми, а те, что были записаны первыми, будут извлечены последними. Стек используется в ситуациях, когда требуется организовать обработку прерываний или создать временное хранилище данных в памяти. Система прерываний (Interrupt System). Прерывание — это процесс обработки запроса от внешнего устройства или любое событие, нарушающее последовательное выполнение программы процессором. Например, прерывание может возникнуть при некорректном выполнении арифметической операции, такой как деление на нуль. Прерывание может быть программным, когда в коде программы используется команда перехода на определенную подпрограмму, с последующим возвратом в основную программу. В этом случае сходство с настоящим прерыванием заключается только в механизме перехода на подпрограмму и возврата из нее. 5.2. Порты ввода/вывода Порты ввода/вывода — это специализированные устройства, обеспечивающие взаимодействие микропроцессорной системы с внешним пространством. Через порты ввода процессор принимает внешние сигналы, такие как управляющие команды, данные от кнопок, датчиков и других устройств. Через порты вывода процессор управляет внешними устройствами, например, реле, моторами, световыми индикаторами или дисплеями. Центральный процессор взаимодействует с портами ввода/вывода аналогично работе с ячейками памяти. Операции с портами заключаются в чтении данных из порта ввода или записи данных в порт вывода. Порт вывода обычно реализуется в виде параллельного регистра. Порт ввода устроен еще проще — это ключевая схема, которая по команде процессора передает внешние данные на его входы (рис. 5.4). Порты микроконтроллеров PIC имеют свои собственные обозначения: A, B, C, D и E. Для управления вводом/выводом через каждый параллельный порт служит соответствующая пара регистров (где x — любая из приведенных выше букв): – регистр данных — PORTx; – регистр управления направлением передачи — TRISx. Количество таких пар регистров соответствует количеству портов. С их помощью через любой порт можно одновременно передавать или принимать от одного до восьми бит данных. Порты в микроконтроллерах PIC являются дву123
направленными, то есть каждый вывод порта может быть настроен как на вход, так и на выход. Это определяется регистром TRISx: запись логической 1 в определенный разряд регистра TRISx настраивает соответствующий вывод порта как вход, а логический 0 — как выход. Например, чтобы настроить разряды 0 и 1 порта B как входы, а остальные как выходы, в регистр TRISB необходимо записать значение 00000011. Рис. 5.4 Взаимодействие ЦП с портами ввода/вывода Некоторые выводы портов ввода/вывода мультиплексированы с периферийными модулями микроконтроллера. Если периферийный модуль активен, соответствующий вывод нельзя использовать как универсальный канал ввода/вывода. Далее будут подробно рассмотрены регистры восьмиразрядных микроконтроллеров PIC. 5.2.1. Регистры PORTA и TRISA PORTA — это 6-разрядный порт ввода-вывода. Каждый канал PORTA имеет соответствующий бит направления в регистре TRISA, который позволяет настраивать канал как вход или выход. Запись 1 в бит регистра TRISA переводит соответствующий выходной буфер в третье состояние (высокоимпедансное). Запись 0 в регистр TRISA настраивает соответствующий канал как выход, при этом данные из защелки PORTA передаются на вывод микроконтроллера (если выходная защелка подключена к выводу микроконтроллера). Канал RA4 оснащен триггером Шмидта на входе и имеет выход с открытым стоком, а также мультиплексирован с тактовым входом T0CKI. Остальные 124
каналы PORTA имеют TTL-буфер на входе и полнофункциональные КМОПбуферы на выходе. Каналы PORTA мультиплексированы с аналоговыми входами АЦП и аналоговым входом источника опорного напряжения VREF. Настройка режимов работы каналов порта ввода/вывода PORTA осуществляется через регистр ADCON1. Биты регистра TRISA управляют направлением каналов PORTA даже в случае их использования в качестве аналоговых входов. Пользователь должен убедиться, что соответствующие каналы PORTA настроены как входы, если они используются для аналоговых сигналов. Таблица 5.1 Функциональное назначение выводов PORTA Обозначение Тип № бита вывода буфера RA0/AN0 бит 0 TTL RA1/AN1 бит 1 TTL RA2/AN2 бит 2 TTL RA3/AN3 бит 3 TTL RA4/T0CKI бит 4 ST RA5/-SS/AN4 бит 5 TTL Описание Двунаправленный порт ввода/вывода или аналоговый вход Двунаправленный порт ввода/вывода или аналоговый вход Двунаправленный порт ввода/вывода или аналоговый вход Двунаправленный порт ввода/вывода или аналоговый вход Двунаправленный порт ввода/вывода, может использоваться как ТОСКI, выход с открытым стоком Двунаправленный порт ввода/вывода, или вход выбора синхронного последовательного порта, или аналоговый вход Обозначения. ST = вход с триггером Шмидта; TTL = входной буфер TTL. Регистры PORTB и TRISB PORTB представляет собой 8-разрядный двунаправленный порт ввода/вывода. Направление работы каждого канала порта определяется битами регистра TRISB. Если бит в регистре TRISB установлен в 1, соответствующий выходной буфер переводится в третье состояние (высокоимпедансное). Если в регистр TRISB записан 0, соответствующий канал настраивается как выход, и данные из защелки PORTB передаются на вывод микроконтроллера (при условии, что выходная защелка подключена к выводу микроконтроллера). Три вывода PORTB совмещены с функцией низковольтного программирования: RB3/PGM, RB6/PGC и RB7/PGD. Четыре канала PORTB (RB7:RB4), настроенные на вход, могут вызывать прерывания при изменении логического уровня сигнала на входе. Если любой из каналов RB7:RB4 настроен как выход, он не может быть источником прерываний. Сигналы на выводах RB7:RB4 сравниваются с их предыдущими значениями, сохраненными при последнем чтении PORTB. Если обнаруживается не125
совпадение, устанавливается флаг RBIF (INTCON<0>) и, если прерывания разрешены, происходит генерация прерывания. Прерывания по изменению сигнала на входах рекомендуется использовать для обработки событий, таких как нажатие клавиш, особенно когда PORTB полностью задействован для реализации клавиатуры. При использовании прерываний по изменению входного сигнала не рекомендуется опрашивать PORTB вручную. Таблица 5.2 Функциональное назначение выводов PORTB Обозначение вывода № бита Тип буфера Описание RB0/INT бит 0 Двунаправленный порт ввода/вывода с програмTTL/ST мным включением подтягивающего резистора, вход внешнего прерывания RB1 бит 1 TTL Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора RB2 бит 2 TTL Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора RB3/PGM(3) бит 3 TTL Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора или вход программирования в режиме LVP RB4 бит 4 TTL Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора и прерыванием по изменению входного сигнала RB5 бит 5 TTL Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора и прерыванием по изменению входного сигнала ttl/st Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора и прерыванием по изменению входного сигнала. Тактовый вход в режиме программирования ttl/st Двунаправленный порт ввода/вывода с программным включением подтягивающего резистора и прерыванием по изменению входного сигнала. Вывод данных в режиме программирования RB6/PGC RB7/PGD бит 6 бит 7 Обозначения. ST = вход с триггером Шмидта; TTL = входной буфер TTL. Регистры PORTC и TRISC PORTC — это 8-разрядный двунаправленный порт ввода/вывода. Направление работы каждого канала порта определяется битами регистра TRISC. Если бит в регистре TRISC установлен в 1, соответствующий выходной буфер переводится в третье состояние (высокоимпедансное). Если в регистр TRISC записан 0, соответствующий канал настраивается как выход, и данные из защелки PORTC 126
передаются на вывод микроконтроллера (при условии, что выходная защелка подключена к выводу микроконтроллера). Выводы PORTC совмещены с несколькими периферийными модулями (см. табл. 5.3). Все каналы PORTC оснащены входным буфером с триггером Шмидта, что обеспечивает устойчивость к шумам и помехам. При использовании периферийных модулей необходимо корректно настраивать биты регистра TRISC для каждого вывода PORTC, чтобы обеспечить правильную работу подключенных устройств. Таблица 5.3 Функциональное назначение выводов PORTC Обозначение вывода № бита Тип буфера Описание RC0/T10SO/T1CKI бит 0 ST Двунаправленный порт ввода/вывода или выход генератора TMR1 / вход тактового сигнала для TMR1 RC1/T10SI/CCP2 бит 1 ST Двунаправленный порт ввода/вывода или вход генератора TMR1 или вход захвата 2 / выход сравнения 2 / выход ШИМ 2 RC2/CCP1 бит 2 ST Двунаправленный порт ввода/вывода или вход захвата 1 / выход сравнения 1 / выход ШИМ 1 RC3/SCK/SCL бит 3 ST Двунаправленный порт ввода/вывода или вход/выход тактового сигнала модуля MSSP в SPI, 12С режиме RC4/SDI/SDA бит 4 ST Двунаправленный порт ввода/вывода, или вход данных в режиме SPI, или вход/выход данных в режиме 12С RC5/SDO бит 5 ST Двунаправленный порт ввода/вывода, или выход данных в режиме SPI RC6/TX/CK бит 6 ST Двунаправленный порт ввода/вывода, или выход передатчика USART в асинхронном режиме, или линия тактового сигнала USART в синхронном режиме RC7/RX/DT бит 7 ST Двунаправленный порт ввода/вывода, или вход приемника USART в асинхронном режиме, или линия данных USART в синхронном режиме Обозначения. ST = вход с триггером Шмидта. Регистры PORTD и TRISD PORTD представляет собой 8-разрядный двунаправленный порт ввода/вывода. Направление работы каждого канала порта задается битами регистра TRISD. PORTD может функционировать как 8-разрядный микропроцессорный порт, работая в режиме ведомого параллельного порта. В этом режиме входы порта оснащены буферами TTL, что обеспечивает совместимость с цифровыми сигналами стандартного уровня. 127
Таблица 5.4 Функциональное назначение выводов PORTD Обозначение Тип № бита вывода буфера RD0/PSP0 бит 0 ST/TTL RD1/PSP1 бит 1 ST/TTL RD2/PSP2 бит 2 ST/TTL RD3/PSP3 бит 3 ST/TTL RD4/PSP4 бит 4 ST/TTL RD5/PSP5 бит 5 ST/TTL RD6/PSP6 бит 6 ST/TTL RD7/PSP7 бит 7 ST/TTL Описание Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 0 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 1 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 2 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 3 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 4 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 5 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 6 Двунаправленный порт ввода/вывода или вывод ведомого параллельного порта бит 7 Обозначения. ST = вход с триггером Шмидта; TTL = входной буфер TTL. Регистры PORTE и TRISE PORTE включает три вывода (RE0/-RD/AN5, RE1/-WR/AN6, RE2/-CS/ AN7), каждый из которых может быть независимо настроен как вход или выход. Выводы PORTE оснащены входным буфером Шмидта, что обеспечивает устойчивость к шумам и повышает надежность работы. Таблица 5.5 Функциональное назначение выводов PORTE Обозначение Тип № бита вывода буфера RE0/-RD/AN5 бит 0 RE1/-WR/AN6 бит 1 Описание Двунаправленный порт ввода/вывода, или вход управления чтением ведомого параллельного порта, или аналоговый вход: ST/TTL -RD 1 = Ожидание 0 = Операция чтения. Защелка PORTD подключена к выводам PORTD (если -CS = 0) Двунаправленный порт ввода/вывода, или вход управления записью ведомого параллельного порта, или аналоговый вход: ST/TTL -WR 1 = Ожидание 0 = Операция записи. Данные с выводов PORTD сохраняются во внутренней защелке PORTD (если -CS = 0) 128
Продолжение табл. 5.5 Обозначение Тип № бита вывода буфера RE2/-CS/AN7 бит 2 Описание Двунаправленный порт ввода/вывода, или вход выбора микросхемы ведомого параллельного порта, или аналоговый вход: ST/TTL -CS 1 = Микросхема не выбрана 0 = Микросхема выбрана Обозначения. ST = вход с триггером Шмидта; TTL = входной буфер TTL. Каналы PORTE могут выполнять функции управляющих выводов ведомого параллельного порта, если бит PSPMODE установлен в 1. В этом режиме биты TRISE<2:0> должны быть установлены в 1. Дополнительно в регистре ADCON1 требуется настроить выводы PORTE как цифровые каналы ввода/вывода. В режиме ведомого параллельного порта к выводам PORTE подключены входные буферы TTL, что обеспечивает совместимость с цифровыми сигналами стандартного уровня. Выводы PORTE также совмещены с аналоговыми входами. Если каналы PORTE настроены как аналоговые входы, биты регистра TRISE управляют направлением передачи данных (при чтении будет возвращаться значение 0). 5.3. Таймеры в микроконтроллерах (TMR0, TMR1, TMR2) Отметим, что некоторые восьмиразрядные микроконтроллеры PIC оснащены только одним таймером, в то время как другие могут иметь до трех таймеров. В этом случае они нумеруются, начиная с нуля: TMR0, TMR1 и TMR2 (таймеры общего назначения). Кроме того, практически все микроконтроллеры PIC оснащены так называемым сторожевым таймером. Сторожевой таймер (Watchdog Timer) предназначен для автоматического сброса и перезапуска микроконтроллера в случае зависания или сбоя в работе программы. Таймеры общего назначения используются для создания временных интервалов и генерации прямоугольных импульсов с заданной частотой. Они также могут функционировать в режиме счетчика, подсчитывая тактовые импульсы определенной частоты, что позволяет измерять длительность внешних сигналов. Кроме того, таймеры способны подсчитывать количество внешних импульсов, что делает их универсальным инструментом для решения различных задач. 5.3.1. TMR0 и сторожевой таймер Таймер TMR0 представляет собой восьмиразрядный регистр и может работать в режиме таймера или счетчика. В последнем случае его содержимое увеличивается на единицу всякий раз при поступлении тактового импульса на вывод Т0СК1 микроконтроллера. В режиме таймера увеличение значения счетчика происходит с частотой, которая определяется частотой системного такто129
вого сигнала и коэффициентом предварительного деления, задаваемым через регистр OPTION_REG. 7 RBPU 6 INTEDG 5 T0CS 4 T0SE 3 PSA 2 PS2 1 PS1 0 PS0 Биты регистра OPTION_REG бит 7: RBPU: бит 6: INTEDG: бит 5: T0CS: Выбор тактового сигнала для TMR0 1 = внешний тактовый сигнал с вывода RA4/T0CKI 0 = внутренний тактовый сигнал CLKOUT бит 4: T0SE: Выбор фронта приращения TMR0 при внешнем тактовом сигнале 1 = приращение по заднему фронту сигнала (с высокого к низкому уровню) на выводе RA4/T0CKI 0 = приращение по переднему фронту сигнала (с низкого к высокому уровню) на выводе RA4/T0CKI бит 3: PSA: Выбор включения предделителя 1 = предделитель включен перед WDT 0 = предделитель включен перед TMR0 биты 2–0: PS2: PS0: Установка коэффициента деления предделителя Коэффициент деления выбирают с помощью разрядов PS2:PS0 регистра OPTION_REG в диапазоне от 2 до 256 (табл. 5.6). Например, при использовании тактовой частоты 4 МГц базовый командный цикл составляет 1 мкс (частота тактирования внутренне делится на четыре). Таким образом, если, например, выбрать коэффициент деления 16, то содержимое счетчика будет увеличиваться на единицу через каждые 16 мкс. Таблица 5.6 Выбор коэффициента деления с помощью регистра OPTION_REG PS2 PS1 PS0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 Коэффициент деления TMR0 1:2 1:4 1:8 1:16 1:32 1:64 1:128 1:256 Коэффициент деления WDT 1:1 1:2 1:4 1:8 1:16 1:32 1:64 1:128 Если бит PSA установлен в 0, то предделитель включен перед TMR0 (рис. 5.5). Если бит PSA установлен в 1, то предделитель включен перед WDT (рис. 5.6). 130
Рис. 5.5 Включение предделителя перед TMR0 Рис. 5.6 Включение предделителя перед WDT При переполнении (то есть переходе от 255 к 0) счетного регистра формируется прерывание от таймера. Например, если необходимо выдавать запрос на прерывание с интервалом в 200 мкс при тактовой частоте 4 МГц, то мы можем задать коэффициент деления 4 и разрешить прерывания от таймера. В результате мы получим период следования импульсов тактирования таймера 4 мкс. Для получения 200 мкс на таймер необходимо подать 50 тактовых импульсов, а значит, в регистр TMR0 должно быть предварительно загружено значение 256 – 50 = = 206, то есть до переполнения должно быть отсчитано 50 единиц. Что касается сторожевого таймера, то его осциллятор независим от сигнала системной синхронизации. Во избежание сброса от сторожевого таймера, его следует периодически программно обнулять. Если сторожевой таймер не используется, то его при программировании микроконтроллера можно отключить. 131
Для расчета времени до переполнения таймера при известном периоде тактовых импульсов, начальном значении счетчика и коэффициенте деления частоты можно использовать следующую формулу: Тпереп = 4  Тосц  K  (256 – TMR0), где Тпереп — время до переполнения (мкс); Тосц — период тактовых импульсов от осциллятора (мкс); K — коэффициент деления частоты, задаваемый через регистр OPTION_REG, TMR0 — значение, загруженное в регистр TMR0. Например, мы используем кварц на 4 МГц, а коэффициент деления равен 8. Также примем, что в регистр TMR0 загружено десятичное число 100. В таком случае время до переполнения составляет: Тпереп = 4  (1/4МГц)  8  (256 – 100) = 1248 мкс. Если же требуется найти значение TMR0, то можно воспользоваться формулой TMR0 = 256 – Тпереп / (4  Тосц  K). Например, необходимо, чтобы переполнение наступило через 500 мкс. Тактовая частота и коэффициент деления — такие же, как и в предыдущем примере. В таком случае значение, которое должно быть загружено в регистр TMR0 = 193,5. Поэтому в регистр TMR0 следует загрузить число 193. 5.3.2. Таймер TMR1 TMR1 — это 16-разрядный таймер, состоящий из двух восьмиразрядных регистров TMR1H и TMR1L. Он может подсчитать 65 535 импульсов за один цикл. Модуль таймера TMR1 может работать в одном из двух основных режимов: в качестве таймера или счетчика. В отличие от таймера TMR0, оба этих режима имеют дополнительные функции. TMR1 имеет независимый предделитель, который позволяет делить на 1, 2, 4 или 8. При переполнении счетчика TMR1 флаг прерывания TMR1IF в регистре PIR1<0> устанавливается в 1. Прерывание можно разрешить или запретить, установив или сбросив бит TMR1IE в регистре PIE1<0>. TMR1 может работать в двух режимах: режим таймера и режим счетчика. Активация модуля TMR1 осуществляется установкой бита TMR1ON в 1 (T1CON<0>). Источник тактовых импульсов выбирается с помощью бита TMR1CS (T1CON<1>). В режиме таймера TMR1 увеличивает свое значение на каждом машинном цикле. Если TMR1 работает с внешним источником тактового сигнала, инкремент происходит по каждому переднему фронту входного сигнала. Если включен генератор тактовых импульсов (T1OSCEN=1), выводы RC1/T1OSI/CCP2 и RC0/T1OSO/T1CKI автоматически настраиваются как входы. В этом случае значение битов TRISC<1:0> игнорируется, а чтение данных с этих выводов возвращает 0. Управляющие биты TMR1 находятся в регистре T1CON. 7 - 6 - 5 4 3 2 1 0 T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON 132
Биты регистра T1CON биты 7–6: Не реализованы: читаются как 0 биты 5–4: T1CKPS1:T1CKPS0: Выбор коэффициента деления предделителя TMR1 11 = 1:8 10 = 1:4 01 = 1:2 00 = 1:1 бит 3: T1OSCEN: Включение тактового генератора TMR1 1 = генератор включен 0 = генератор выключен (инвертирующий элемент и резистивная обратная связь выключены для уменьшения тока потребления) бит 2: -T1SYNC: Синхронизация внешнего тактового сигнала TMR1CS = 1 1 = не синхронизировать внешний тактовый 0 = синхронизировать внешний тактовый TMR1CS = 0 Значение бита игнорируется бит 1: TMR1CS: Выбор источника тактового сигнала 1 = внешний источник с вывода RC0/T1OSO/T1CKI (активным является передний фронт сигнала) 0 = внутренний источник Fosc/4 бит 0: TMR1ON: Включение модуля TMR1 1 = включен 0 = выключен Работа TMR1 в режиме таймера (рис. 5.7). Увеличение значения таймера TMR1 происходит от внутреннего тактового сигнала Fosc/4, если бит TMR1CS (T1CON<1>) установлен в 0. В этом режиме бит синхронизации T1SYNC (T1CON<2>) игнорируется, так как внутренний тактовый сигнал всегда синхронизирован с системной частотой. Рис. 5.7 Работа TMR1 в режиме таймера 133
Тактовый генератор микроконтроллера не работает в спящем режиме, поэтому переполнение регистра таймера не сможет вызвать прерывание. На рисунке 5.8 дополнительно показана диаграмма приращения таймера TMR1. Работа TMR1 в режиме счетчика (рис. 5.9). TMR1 может функционировать в синхронном или асинхронном режиме в зависимости от состояния бита TMR1CS. Если TMR1 использует внешний тактовый сигнал, увеличение значения таймера происходит по переднему фронту входного сигнала. При активации TMR1 в режиме внешнего тактового сигнала счет начнется только после появления заднего фронта. Если микроконтроллер находится в спящем режиме, то регистры TMR1H и TMR1L таймера не увеличиваются даже при появлении входных импульсов. Рис. 5.8 Приращение TMR1 (стрелками показано приращение TMR1) Рис. 5.9 Работа TMR1 в режиме счетчика Генератор TMR1. Резонатор подключается к выводам T1OSI (вход) и T1OSO (выход усилителя). Максимальная частота резонатора составляет 200 кГц. Тактовый генератор TMR1 (аналогичный LP-генератору) в основном предназначен для работы с кварцевым резонатором на 32 кГц. Активация генератора осуществляется установкой бита T1OSCEN в регистре T1CON<3>, что позволяет TMR1 работать в режиме SLEEP микроконтроллера. Пользователю необходимо предусмотреть программную задержку, чтобы обеспечить корректный запуск генератора. На рисунке 5.10 показана схема подключения внешнего генератора и ориентировочные значения для настройки. 134
Рис. 5.10 Подключение внешнего генератора Предделитель TMR1. Предделитель TMR1 полностью обнуляется при записи в нужный регистр TMR1L или TMR1H. Таймер TMR1 имеет независимый предделитель, который позволяет делить на 1, 2, 4 или 8 входную частоту генератора. 5.3.3. Таймер TMR2 TMR2 представляет собой 8-разрядный таймер, оснащенный программируемым предделителем и выходным делителем, а также 8-разрядным регистром периода PR2. Этот таймер может использоваться в качестве опорного для модуля CCP в режиме ШИМ. Регистры TMR2 поддерживают операции записи и чтения, а также сбрасываются при любом виде сброса системы. 7 6 5 4 3 2 1 0 - TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0 Биты регистра T2CON бит 7: Не реализован: читается как '0' биты 6–3: TOUTPS3:TOUTPS0: Выбор коэффициента выходного делителя TMR2 0000 = 1:1 0001 = 1:2/ /1111 = 1:16 бит 2: TMR2ON: Включение модуля TMR2 1 = включен 0 = выключен биты 1–0: T2CKPS1:T2CKPS0: Выбор коэффициента деления предделителя TMR2 00 = 1:1 01 = 1:4 1x = 1:16 Входной тактовый сигнал (FOSC/4) проходит через предделитель с программируемым коэффициентом деления (1:1, 1:4 или 1:16), который задается битами T2CKPS1:T2CKPS0 (T2CON<1:0>). Таймер TMR2 ведет счет, увеличивая значение от 00h до величины, записанной в регистре PR2, после чего сбрасывается в 00h на следующем машинном цикле. Регистр PR2 доступен как для 135
записи, так и для чтения. Сигнал переполнения TMR2 проходит через 4-разрядный выходной делитель с программируемым коэффициентом деления (от 1:1 до 1:16), что приводит к установке флага TMR2IF в регистре PIR1<1>. Для снижения энергопотребления таймер TMR2 может быть отключен путем сброса бита TMR2ON (T2CON<2>) в 0. Рис. 5.11 Функционирование TMR2 5.4. Модуль широтно-импульсной модуляции (CCP) Таймеры TMR1 и TMR2 в микроконтроллерах PIC используются в составе модуля сравнения, захвата и ШИМ — CCP (Capture/Compare/PWM). В микроконтроллерах могут быть два таких модуля: CCP1 и CCP2. Управление этими модулями осуществляется с помощью регистров CCPxCON. 7 - 6 - 5 4 3 2 1 0 CCPxX CCPxY CCPxM3 CCPxM2 CCPxM1 CCPxM0 Биты регистра CCPxCON бит 7–6: Не используются: читаются как 0 биты 5–4: CCPxX:CCPxY: Младшие биты скважности ШИМ Режим захвата Не используются Режим сравнения Не используются Режим ШИМ Два младших бита скважности. Восемь старших находятся в CCPRxL биты 3–0: CCPxM3:CCPxM0: Режим работы модуля CCPx 0000 = модуль CCPx выключен (сброс модуля CCPx) 0100 = захват по каждому заднему фронту сигнала 0101 = захват по каждому переднему фронту сигнала 0110 = захват по каждому 4-му переднему фронту сигнала 0111 = захват по каждому 16-му переднему фронту сигнала 1000 = сравнение, устанавливает выходной сигнал (устанавливается флаг CCPxIF в 1) 136
1001 = сравнение, сбрасывает выходной сигнал (устанавливается флаг CCPxIF в 1) 1010 = сравнение, на выходной сигнал не влияет (устанавливается флаг CCPxIF в 1) 1011 = сравнение, триггер специальных функций (устанавливается флаг CCPxIF в 1; на вывод CCPx не влияет). CCP1 — сброс таймера TMR1. CCP2 — сброс таймера TMR1, запуск преобразования АЦП (если АЦП включено) 11xx = ШИМ режим Модуль CCP1. Регистр CCPR1 модуля CCP состоит из двух 8-разрядных регистров: CCPR1L (младший байт) и CCPR1H (старший байт). Управляющие биты модуля CCP1 находятся в регистре CCP1CON, который доступен как для записи, так и для чтения. В режиме сравнения триггер специального события сбрасывает таймер TMR1. Модуль CCP2. Регистр CCPR2 модуля CCP также состоит из двух 8разрядных регистров: CCPR2L (младший байт) и CCPR2H (старший байт). Управляющие биты модуля CCP2 расположены в регистре CCP2CON, который также поддерживает запись и чтение. В режиме сравнения триггер специального события сбрасывает таймер TMR1 и, если АЦП включено, запускает процесс аналого-цифрового преобразования. Каждый модуль CCP включает 16-разрядный регистр, который может выполнять следующие функции: – 16-разрядный регистр захвата данных; – 16-разрядный регистр сравнения; – два 8-разрядных регистра (ведущий и ведомый) для работы в режиме ШИМ. Работа модулей CCP1 и CCP2 идентична, за исключением особенностей функционирования триггера специального события. В таблице 5.7 приведены параметры, используемые модулем CCP. Далее будет рассмотрена работа модуля CCP1. Модуль CCP2 функционирует аналогично, а его отличия будут указаны отдельно. Таблица 5.7 Использование таймеров модулями CCP Режим модуля CCP Таймер Захват TMR1 Сравнение TMR1 ШИМ TMR2 5.4.1. Режим захвата В режиме захвата значение счетчика TMR1 (состоящие из TMR1H и TMR1L) переписывается в регистр CCP1 (состоящей из CCPR1H и CCPR1L) (рис. 5.12). События захвата могут происходить в следующих случаях: – при каждом заднем фронте сигнала на входе RC2/CCP1; – при каждом переднем фронте сигнала на входе RC2/CCP1; – при каждом 4-м переднем фронте сигнала на входе RC2/CCP1; – при каждом 16-м переднем фронте сигнала на входе RC2/CCP1. 137
Тип события захвата задается битами CCP1M3:CCP1M0 в регистре CCP1CON. После успешного захвата устанавливается флаг прерывания CCP1F (PIR1<2>) в значение 1. Этот флаг должен быть сброшен программно. Рис. 5.12 Режим захвата модуля CCP 5.4.2. Режим сравнения В этом режиме происходит сравнение 16-разрядного регистра CCPR1 со значением таймера TMR1. Когда значения в регистрах совпадают, модуль CCP1 изменяет состояние вывода RC2/CCP1 следующим образом: – устанавливает высокий уровень сигнала; – устанавливает низкий уровень сигнала; – не воздействует на вывод. Необходимое действие при совпадении выбирается с помощью битов CCP1M3:CCP1M0 в регистре CCP1CON. В момент изменения состояния вывода устанавливается флаг прерывания CCP1IF в значение 1 (рис. 5.13). Рис. 5.13 Режим сравнения модуля CCP 138
5.4.3. Режим ШИМ Сигналы с различной частотой и скважностью имеют широкий спектр применения в автоматических системах. Типичным примером является схема управления мощностью (рис. 5.14). Логический нуль (0) указывает на отключение электрической мощности, а логическая единица (1) — на включение. При этом уровень мощности прямо пропорционален длительности импульса. Рис. 5.14 Управление мощностью с помощью ШИМ Другим примером использования ШИМ является генерация сигналов произвольной формы, например синусоидального сигнала (рис. 5.15). Рис. 5.15 Генерация синусоидального сигнала с помощью ШИМ В режиме ШИМ модуля CCP1 вывод RC2/CCP1 функционирует как выход 10-разрядного ШИМ-сигнала. Поскольку вход CCP1 мультиплексирован с цифровым каналом порта ввода/вывода, бит направления TRISC<2> должен быть сброшен в 0 для настройки вывода на выход. Период ШИМ. Период ШИМ (Tшим, на рис. 5.16) определяется значением в регистре PR2 и может быть вычислен по формуле Т шим = ( PR2 + 1)  4  Tосц  ( коэффициент предделителя 139 TMR 2) , Fшим = 1/Tшим].
Рис. 5.16 Временная диаграмма одного цикла ШИМ Скважность ШИМ. Скважность ШИМ задается битами в регистрах CCPR1L и CCP1CON<5:4>. Для 10-разрядного ШИМ старшие восемь бит хранятся в регистре CCPR1L, а младшие два бита — в регистре CCP1CON<5:4> (CCPR1L:CCP1CON<5:4>). Для расчета длительности сигнала высокого уровня (tшим) используется следующая формула: tшим = (CCPR1L:CCP1CON<5:4>) × Tосц × (коэффициент предделителя TMR2). Максимальное разрешение ШИМ для заданной частоты можно вычислить по формуле (в битах): Rшим F  log  осц   Fшим  . = log(2) Рекомендованная последовательность включения модуля CCP в режиме ШИМ. 1. Установить период ШИМ, записав значение в регистр PR2. 2. Задать длительность импульса, записав соответствующие значения в регистры CCPR1L и CCP1CON<5:4>. 3. Настроить вывод CCP1 как выход, сбросив бит TRISC<2>. 4. Настроить предделитель и включить таймер TMR2, записав необходимые значения в регистр T2CON. В таблице 5.8 показано соответствие частоты ШИМ и разрешения ШИМ при частоте МК 20 МГц. 5. Активировать модуль CCP1 в режиме ШИМ, установив соответствующие биты в регистре CCP1CON. Таблица 5.8 Соответствие частоты ШИМ и разрешения ШИМ при частоте МК 20 МГц Частота ШИМ Коэффициент предделителя TMR2 Значение PR2 Разрешение ШИМ (бит) 1,22 кГц 4,88 кГц 19,53 кГц 78,12 кГц 156,3 кГц 208,3 кГц 16 4 1 1 1 1 0xFF 0xFF 0xFF 0x3F 0x1F 0x17 10 10 10 8 7 5,5 5.5. Аналоговый компаратор В дополнение к аналого-цифровому преобразователю, в микроконтроллерах существует еще один модуль, позволяющий работать с аналоговыми сигналами. Аналоговый компаратор представляет собой усилитель, который сравни140
вает величину напряжения на двух входах. Модуль имеет два входа и один выход. В зависимости от входного напряжения (аналоговое значение), на выходе будет сформирован логический нуль (0) или логическая единица (1), которые уже являются цифровыми. На рисунке 5.17 приведена временная диаграмма работы одного компаратора. Рис. 5.17 Временная диаграмма работы одного компаратора Модуль компараторов содержит два аналоговых компаратора, выводы которых мультиплицированы с каналами ввода/вывода. Выход интегрированного источника опорного напряжения может быть подключен на вход компараторов. В регистре CMCON находятся биты управления модулем компараторов. 7 6 5 C2OUT C1OUT C2INV 4 C1INV 3 CIS 2 CM2 Биты регистра CMCON бит 7: C2OUT: Выход компаратора 2 Если C2INV=0 1 = C2 VIN+ > C2 VIN0 = C2 VIN+ < C2 VINЕсли C2INV=1 0 = C2 VIN+ > C2 VIN1 = C2 VIN+ < C2 VINбит 6: C1OUT: Выход компаратора 1 Если C1INV=0 1 = C1 VIN+ > C1 VIN0 = C1 VIN+ < C1 VINЕсли C1INV=1 0 = C1 VIN+ > C1 VIN1 = C1 VIN+ < C1 VINбит 5: C2INV: Инверсный выход компаратора 2 1 = C2 инверсный выход 0 = C2 не инверсный выход бит 4: C1INV: Инверсный выход компаратора 1 1 = C1 инверсный выход 0 = C1 не инверсный выход бит 3: CIS: Подключение входов компараторов Если CM2:CM0 = 001 1 = C1 VIN- подключен к AN3 141 1 CM1 0 CM0
0 = C1 VIN- подключен к AN0 Если CM2:CM0 = 010 1 = C1 VIN- подключен к AN3 C2 VIN- подключен к AN2 0 = C1 VIN- подключен к AN0 C2 VIN- подключен к AN1 биты 2–0: CM2:CM0: Режим работы компараторов (см. рис. 5.18) Существует восемь режимов работы модуля компараторов, устанавливаемые битами CM2:CM0 (см. рис. 5.18). Биты регистра TRIS управляют направлением каналов ввода/вывода для каждого режима модуля компараторов. Рис. 5.18 Режимы работы модулей компараторов Обозначения: A = аналоговый вход, канал ввода/вывода, читается как 0; D = цифровой вход; CIS = управляющий бит регистра CMCON<3>. В микро142
контроллерах семейства PIC предусмотрена возможность использования как внешнего, так и внутреннего источника для компараторов. Модуль компараторов может быть настроен таким образом, что внешний источник опорного напряжения подключается к входу обоих компараторов либо для каждого компаратора используется отдельный источник. Напряжение опорного источника должно находиться в пределах от Vss до Vdd. Сигнал внутреннего источника опорного напряжения подключается к выводам Vin+ обоих компараторов, если биты конфигурации CM2:CM0 установлены в значение 010. Источник опорного напряжения может работать в любом режиме модуля компараторов. В этом режиме вывод I/O/Vref может использоваться как цифровой порт ввода/вывода или в качестве выхода источника опорного напряжения Vref. 5.6. Модуль аналого-цифрового преобразователя (ADC) Аналого-цифровой преобразователь (АЦП) выполняет преобразование аналоговых сигналов (например, напряжения) в цифровую форму. В большинстве микроконтроллеров PIC, оснащенных АЦП, для аналогового ввода используются выводы порта А, которые совмещают цифровые и аналоговые функции. Количество аналоговых входов может варьироваться от 1 до 8. При этом в микроконтроллере присутствует только один АЦП, а входы мультиплексируются. Разрядность АЦП может составлять 8 или 10 бит. В микроконтроллерах семейства PIC применяется АЦП последовательного приближения. 5.6.1. АЦП последовательного приближения Схема АЦП последовательного приближения изображена на рисунке 5.19. Рассмотрим алгоритм работы АЦП последовательного приближения на примере. Предположим, что вывод низкого уровня опорного напряжения Vоп– подключен к потенциалу 0 В, а вывод высокого уровня опорного напряжения Vоп+ — к потенциалу 5,0 В. АЦП формирует на выходе 8-разрядный двоичный код. Количество различных кодов, которые могут представлять результат оцифровки, составляет 28 = 256. Разрешающая способность такого АЦП равна: (5,0 В – 0,0 В) / 256 = = 19,53 мВ. Рис. 5.19 АЦП последовательного приближения 143
Процесс аналого-цифрового преобразования (АЦП) по методу последовательного приближения состоит из нескольких тактов. Количество тактов, необходимых для выполнения одного преобразования, равно числу двоичных разрядов в представлении результата. В нашем примере, где используется 8-разрядный АЦП, результат будет сформирован после восьми тактов преобразования. На каждом такте формируется один двоичный разряд результата: – на первом такте — старший разряд b7, – на втором такте — разряд b6 и так далее, до младшего разряда b0 на восьмом такте. Алгоритм работы. 1. На первом такте в регистре последовательного приближения устанавливается код К1 = 10000000. Этот код поступает на вход цифро-аналогового преобразователя (ЦАП), опорное напряжение которого равно Vоп = Vоп+ – – Vоп– = 5,0 В. На выходе ЦАП формируется напряжение: Vцап = Vоп × × К1/2⁸ = 2,5 В. 2. Аналоговый компаратор сравнивает измеряемое напряжение Vвх с напряжением на выходе ЦАП Vцап. Если Vвх > Vцап, на выходе компаратора устанавливается логическая 1. Если Vвх < Vцап, на выходе компаратора установлен логический 0. 3. Сигнал с выхода компаратора поступает на вход регистра последовательного приближения. Его значение определяет код на выходе регистра в следующем такте преобразования. Если на выходе компаратора 1, то во втором такте регистр сформирует код К2 = 11000000. Если на выходе компаратора 0, то код будет К2 = 01000000. 4. Значение формируемого в текущем такте двоичного разряда равно значению логического сигнала на выходе компаратора. 5. Количество уровней напряжения на выходе ЦАП увеличивается с ростом номера такта, так как увеличивается число возможных комбинаций кодов на выходе регистра последовательного приближения. Во втором такте при коде К2 = 11000000 на выходе ЦАП будет сформировано напряжение 3,75 В. При коде К2 = 01000000 — напряжение 1,25 В. 6. На восьмом такте число возможных уровней на выходе ЦАП достигает 256. Достоинства подобных АЦП. Время преобразования не зависит от амплитуды входного сигнала и определяется только частотой тактирования и числом двоичных разрядов результата. Постоянное время преобразования удобно в микропроцессорной технике, так как позволяет разработчику точно рассчитывать время выполнения программных фрагментов. Каждое преобразование выполняется независимо, результат предыдущего преобразования не влияет на последующее. Недостатки. Относительно низкая скорость преобразования. Достаточно сложная структура схемы. 144
5.6.2. Модуль АЦП в микроконтроллерах PIC Входной аналоговый сигнал через коммутатор каналов заряжает внутренний конденсатор АЦП CHOLD. Модуль АЦП преобразует напряжение, удерживаемое на конденсаторе CHOLD, в соответствующий 8- или 10-разрядный цифровой код методом последовательного приближения. Источник верхнего и нижнего опорного напряжения может быть выбран с выводов VDD, VSS, RA2 или RA3. Модуль АЦП может работать в режиме SLEEP микроконтроллера. В этом случае в качестве источника тактовых импульсов для АЦП должен быть выбран RC-генератор. Для управления модулем АЦП в микроконтроллере используются четыре регистра: ADRESH — регистр результата (старший байт); ADRESL — регистр результата (младший байт); ADCON0 — регистр управления; ADCON1 — регистр управления. Регистр ADCON0 используется для настройки работы модуля АЦП, а регистр ADCON1 определяет, какие входы микроконтроллера будут использоваться модулем АЦП и в каком режиме (аналоговый вход или цифровой порт ввода/вывода). 7 6 5 4 ADCS1 ADCS0 CHS2 CHS1 3 CHS0 2 GO/DONE 1 0 - AD Биты регистра ADCON0 биты 7–6: ADCS1:ADCS0: Выбор источника тактового сигнала 00 = FOSC/2 01 = FOSC/8 10 = FOSC/32 11 = FRC (внутренний RC генератор модуля АЦП) биты 5–3: CHS2:CHS0: Выбор аналогового канала 000 = канал 0 (RA0/AN0) 001 = канал 1 (RA1/AN1) 010 = канал 2 (RA2/AN2) 011 = канал 3 (RA3/AN3) 100 = канал 4 (RA5/AN4) 101 = канал 5 (RE0/AN5) 110 = канал 6 (RE1/AN6) 111 = канал 7 (RE2/AN7) бит 2: GO/-DONE: Бит статуса модуля АЦП Если ADON=1 1 = модуль АЦП выполняет преобразование (установка бита вызывает начало преобразования) 0 = состояние ожидания (аппаратно сбрасывается по завершении преобразования) бит 1: Не используется: читается как 0 бит 0: ADON: Бит включения модуля АЦП 1 = модуль АЦП включен 0 = модуль АЦП выключен и не потребляет тока 145
7 ADFM 6 - 5 - 4 - 3 PCFG3 2 PCFG2 1 PCFG1 0 PCFG0 Биты регистра ADCON1 бит 7: ADFM: Формат сохранения 10-разрядного результата 1 = правое выравнивание, 6 старших бит ADRESH читаются как 0 0 = левое выравнивание, 6 младших бит ADRESL читаются как 0 биты 6–4: Не используются: читаются как 0 биты 3–0: PCFG3:PCFG0: Управляющие биты настройки каналов АЦП PCGF3: AN7 AN6 AN5 AN4 AN3 AN2 AN1 AN0 PCGF0 RE2 RE1 RE0 RA5 RA3 RA2 RA1 RA0 0000 А А А А А A A A 0001 А А А А Vref+ A A A 0010 D D D А А A A A 0011 D D D А Vref+ A A A 0100 D D D D А D A A 0101 D D D D Vref+ D A A 011х D D D D D D D D 1000 А А А А Vref+ Vref- A A 1001 D D А А А A A A 1010 D D А А Vref+ A A A 1011 D D А А Vref+ Vref- A A 1100 D D D А Vref+ Vref- A A 1101 D D D D Vref+ Vref- A A 1110 D D D D D D D A 1111 D D D D Vref+ Vref- D A A = аналоговый вход; D = цифровой канал ввода/вывода Vоп+ (Vref+) Vdd RA3 Vdd RA3 Vdd RA3 Vdd RA3 Vdd RA3 RA3 RA3 RA3 Vdd RA3 Vоп(Vref-) Vss Vss Vss Vss Vss Vss Vss RA2 Vss Vss RA2 RA2 RA2 Vss RA2 В регистре ADRESH:ADRESL сохраняется 10-разрядный результат аналого-цифрового преобразования. Когда преобразование завершено, результат записывается в регистр ADRESH:ADRESL, после чего сбрасывается флаг GO/ -DONE (бит ADCON0<2>) и устанавливается флаг прерывания ADIF. Структурная схема модуля АЦП представлена на рисунке 5.20. После включения и настройки АЦП выбирается рабочий аналоговый канал. Соответствующие биты TRIS для аналоговых каналов должны быть настроены так, чтобы порт ввода/вывода работал в режиме входа. Для АЦП необходимо опорное напряжение (обычно 5 В). Таким образом, если мы используем 10-разрядный преобразователь (1024 уровня дискретности), то разрешающая способность преобразователя составит 5 / 1024 = 0,00488 В или 4,88 мВ, то есть мы можем измерять аналоговые напряжения с разрешением 4,88 мВ. Например, если измеряемое аналоговое входное напряжение равно 4,88 мВ, то мы получим 10-разрядное цифровое значение 0000000001. Если аналоговое входное напряжение равно 2  4,88 = 9,76 мВ, то получится 10разрядное цифровое значение 0000000010. Если же входное напряжение равно 146
3  4,88 = 14,64 мВ, то 10-разрядное цифровое значение составит 0000000011 и т. д. Подобным же образом, если опорное напряжение равно 5 В, мы используем восьмиразрядный преобразователь (256 уровней дискретности), то разрешающая способность составит 5 / 256 = 19,53 мВ. Например, если измеряемое входное напряжение равно 19,53 мВ, то мы получим восьмиразрядное цифровое значение 00000001 и т. д. Рис. 5.20 Структурная схема модуля АЦП Время, необходимое для завершения преобразования одного бита, определяется как TAD. Минимальное время для преобразования бита составляет 1,6 мкс. Одно полное 10-битное преобразование составляет 11 периодов TAD. Тактовая частота аналого-цифрового преобразования задается с помощью комбинаций битов ADCS1 и ADCS0. Эти биты хранятся в реестре ADCON0. Режим тактирования АЦП Fosc/2 Fosc/8 Fosc/32 RC ADCS1 ADCS0 0 0 1 1 0 1 0 1 Частота осциллятора (FOSC) 20 МГц МГц МГц МГц 100 нс 250 нс 500 нс 2 мкс 400 нс 1 мкс 2 мкс 8 мкс 1,6 мкс 4 мкс 8 мкс 32 мкс 2–6 мкс 2–6 мкс 2–6 мкс 2–6 мкс Рекомендованная последовательность действий для работы с АЦП. 1. Настроить модуль АЦП. Настроить выводы как аналоговые входы, входы VREF или цифровые каналы ввода/вывода (регистр ADCON1). Выбрать входной канал АЦП (регистр ADCON0). Выбрать источник тактовых импульсов для АЦП (регистр ADCON0). Включить модуль АЦП (регистр ADCON0). 147
2. Настроить прерывание от модуля АЦП (если необходимо). Сбросить бит ADIF в 0. Установить бит ADIE в 1. Установить бит PEIE в 1. Установить бит GIE в 1. 3. Выдержать паузу, необходимую для зарядки конденсатора CHOLD. 4. Начать аналого-цифровое преобразование. Установить бит GO/-DONE в 1 (регистр ADCON0). Ожидать окончания преобразования. Ожидать, пока бит GO/-DONE не будет сброшен в 0, ИЛИ Ожидать прерывание по окончании преобразования. 5. Считать результат преобразования. Считать результат из регистров ADRESH:ADRESL. Сбросить бит ADIF в 0, если это необходимо. 6. Для следующего преобразования. Выполнить шаги, начиная с пункта 1 или 2. Примечание. Время преобразования одного бита определяется как время TAD. Минимальное время ожидания перед следующим преобразованием должно составлять не менее 2TAD. 5.7. Универсальный синхронно-асинхронный приемопередатчик (USART) USART (Universal Synchronous and Asynchronous serial Receiver and Transmitter) — это универсальный модуль последовательной связи, который поддерживает как синхронный, так и асинхронный режимы передачи данных. Это делает его гибким инструментом для взаимодействия с различными устройствами, такими как терминалы, компьютеры, ЦАП, АЦП, EEPROM и другими периферийными устройствами. Основные режимы работы USART. Асинхронный режим (полный дуплекс). В этом режиме передача данных происходит без использования общего тактового сигнала. Данные передаются пакетами, которые включают стартовый бит, биты данных, опциональный бит четности и стоповый бит. Полный дуплекс означает, что передача и прием данных могут происходить одновременно. Ведущий синхронный режим (полудуплекс). В этом режиме микроконтроллер генерирует тактовый сигнал для синхронизации передачи данных. Полудуплекс означает, что передача и прием данных происходят поочередно, но не одновременно. Ведомый синхронный режим (полудуплекс). В этом режиме микроконтроллер использует внешний тактовый сигнал для синхронизации передачи данных. Как и в ведущем режиме, передача и прием данных происходят поочередно. На рисунке 5.21 представлен общий способ подключения PIC микроконтроллера, который использует модуль USART. Микросхема MAX-232 используется в качестве преобразователя напряжения (TTL-RS232). 148
Рис. 5.21 Использование USART в микроконтроллерах PIC Приемопередатчик имеет два регистра управления: TXSTA и RCSTA. 7 CSRC 6 TX9 5 4 TXEN SYNC 3 - 2 1 0 BRGH TRMT TX9D Биты регистра TXSTA бит 7: CSRC: Выбор источника тактового сигнала Синхронный режим 1 = ведущий, внутренний тактовый сигнал от BRG 0 = ведомый, внешний тактовый сигнал с входа CK Асинхронный режим Не имеет значения бит 6: TX9: Разрешение 9-разрядной передачи 1 = 9-разрядная передача 0 = 8-разрядная передача бит 5: TXEN: Разрешение передачи 1 = разрешена 0 = запрещена Примечание. В синхронном режиме биты SREN/CREN отменяют действие бита TXEN. бит 4: SYNC: Режим работы USART 1 = синхронный 0 = асинхронный бит 3: Не используется: читается как ‘0’ бит 2: BRGH: Выбор высокоскоростного режима 149
Синхронный режим Не имеет значения Асинхронный режим 1 = высокоскоростной режим 0 = низкоскоростной режим бит 1: TRMT: Флаг очистки сдвигового регистра передатчика TSR 1 = TSR пуст 0 = TSR полон бит 0: TX9D: 9-й бит передаваемых данных (может использоваться для программной проверки четности) 7 SPEN 6 RX9 5 4 3 SREN CREN ADDEN 2 FERR 1 OERR 0 RX9D Биты регистра RCSTA бит 7: SPEN: Разрешение работы последовательного порта 1 = модуль USART включен (выводы RС7/RX/DT, RС6/TX/CK подключены к USART) 0 = модуль USART выключен бит 6: RX9: Разрешение 9-разрядного приема 1 = 9-разрядный прием 0 = 8-разрядный прием бит 5: SREN: Разрешение одиночного приема Синхронный режим 1 = разрешен одиночный прием 0 = запрещен одиночный прием Сбрасывается в ‘0’ по завершении приема Примечание. В режиме ведомого не имеет значения Асинхронный режим Не имеет значения бит 4: CREN: Разрешение приема Синхронный режим 1 = прием разрешен (при установке бита CREN автоматически сбрасывается бит SREN) 0 = прием запрещен Асинхронный режим 1 = прием разрешен 0 = прием запрещен бит 3: ADDEN: Разрешение детектирования адреса Асинхронный 9-разрядный прием (RX9=1) 1 = детектирование адреса разрешено. Если бит RSR<8>=1, то генерируется прерывание и загружается приемный буфер 0 = детектирование адреса запрещено. Принимаются все байты, девятый бит может использоваться для проверки четности. Асинхронный 8-разрядный прием (RX9=0) Не имеет значения Синхронный режим Не имеет значения бит 2: FERR: Ошибка кадра, сбрасывается при чтении регистра RCREG 1 = произошла ошибка кадра 0 = ошибки кадра не было бит 1: OERR: Ошибка переполнения внутреннего буфера, устанавливается в 0 при сбросе бита CREN 150
1 = произошла ошибка переполнения 0 = ошибки переполнения не было бит 0: RX9D: 9-й бит принятых данных (может использоваться для программной проверки четности) Асинхронный режим USART. В асинхронном режиме USART использует стандартный формат NRZ (Non-Return-to-Zero), который включает: cтартовый бит (1 бит), данные (8 или 9 битов), стоповый бит (1 бит). Наиболее распространенным является 8-разрядный формат передачи данных. Для генерации стандартных скоростей передачи данных используется встроенный 8-разрядный генератор BRG (Baud Rate Generator). Приемник и передатчик USART работают независимо, но используют одинаковый формат данных и скорость обмена. Бит четности не поддерживается аппаратно, но может быть реализован программно с использованием 9-разрядного формата данных. Все данные передаются младшим битом вперед (LSB first). В режиме SLEEP микроконтроллера модуль USART (асинхронный режим) отключается. Для выбора асинхронного режима необходимо сбросить бит SYNC в 0 (регистр TXSTA<4>). Синхронный ведущий режим USART. В синхронном ведущем режиме передача данных осуществляется в полудуплексном режиме, то есть прием и передача данных не могут происходить одновременно. При передаче данных прием запрещен, и наоборот. Для включения синхронного режима необходимо сделать следующее. Установить бит SYNC в 1 (регистр TXSTA<4>). Активировать модуль USART, установив бит SPEN в 1 (регистр RCSTA<7>), чтобы настроить выводы RC6/TX/CK и RC7/RX/DT для работы в качестве линии тактового сигнала (CK) и линии данных (DT) соответственно. В ведущем режиме модуль USART самостоятельно генерирует тактовый сигнал CK. Для выбора этого режима необходимо установить бит CSRC в 1 (регистр TXSTA<7>). Синхронный ведомый режим USART. В синхронном ведомом режиме микроконтроллер использует внешний тактовый сигнал, поступающий на вход RC6/TX/CK, вместо генерации собственного тактового сигнала. Это позволяет устройству принимать и передавать данные даже в режиме SLEEP. Для выбора ведомого режима необходимо сбросить бит CSRC в 0 (регистр TXSTA<7>). Основное отличие от ведущего режима заключается в том, что тактовый сигнал формируется внешним устройством, а микроконтроллер синхронизируется с ним. 5.8. Память данных EEPROM Память EEPROM — это энергонезависимая память, созданная по технологии flash, которая предназначена для долговременного хранения переменных данных. В современных микропроцессорных системах часто возникает необходимость в сохранении таких данных. Например, в микропроцессорной системе управления плеером требуется хранить множество констант. У любого плеера есть фиксированные настройки, такие как уровень громкости, режим воспроизведения и другие параметры. Кроме того, при выключении устройства важно сохранить текущие настройки, чтобы восстановить их при следующем включе151
нии. Все эти данные, представленные в виде числовых значений, обычно записываются в энергонезависимую память EEPROM. Данные в памяти EEPROM могут быть прочитаны или перезаписаны в нормальном режиме работы микроконтроллера при любом допустимом напряжении питания VDD. Операции чтения и записи выполняются побайтно. Запись данных осуществляется по принципу «стирание — запись»: перед записью байта соответствующая ячейка памяти автоматически стирается, после чего происходит запись нового значения. При этом запись в EEPROM не влияет на выполнение основной программы микроконтроллера. Доступ к функциям чтения и записи EEPROM памяти осуществляется через шесть специальных регистров: EEDATA, EEADR, EECON1, EECON2. Регистр EECON1 содержит управляющие биты для косвенной записи и чтения данных в EEPROM, а также для работы с FLASH-памятью программ. Регистр EECON2 физически не существует, но используется в процессе записи для предотвращения случайного изменения данных. Он играет роль защитного механизма при выполнении операций записи. Таким образом, память EEPROM обеспечивает надежное хранение критически важных данных, которые должны сохраняться даже после отключения питания, а управление этой памятью осуществляется через специализированные регистры микроконтроллера. 7 EEPGD 6 - 5 - 4 - 3 WRERR 2 WREN 1 WR 0 RD Биты регистра EECON1 бит 7: EEPGD: Бит выбора EEPROM-память данных/FLASH-память программ 1 = FLASH-память программ 0 = EEPROM-память данных (бит не должен изменяться во время выполнения операции чтения/записи) биты 6–4: Не используются: читаются как ‘0’ бит 3: WRERR: Флаг ошибки записи данных 1 = запись прервана (произошел один из сбросов: по сигналу -MCLR, по переполнению WDT в нормальном режиме) 0 = запись завершена бит 2: WREN: Разрешение записи данных 1 = запись разрешена 0 = запись запрещена бит 1: WR: Инициализировать запись данных (программно может быть только установлен в 1) 1 = инициализировать запись (сбрасывается в 0 аппаратно) 0 = запись завершена бит 0: RD: Инициализировать чтение данных (программно может быть только установлен в 1) 1 = инициализировать чтение (сбрасывается в 0 аппаратно) 0 = чтение завершено Чтение из EEPROM-памяти данных. Для чтения данных из EEPROMпамяти необходимо выполнить следующие шаги. Записать адрес ячейки памя152
ти, из которой требуется прочитать данные, в регистр EEADR. Сбросить бит EEPGD в 0, чтобы указать, что операция выполняется с EEPROM-памятью данных, а не с FLASH-памятью программ. Установить бит RD в 1. После этого на следующем машинном цикле данные из указанной ячейки EEPROM будут доступны в регистре EEDATA. Данные в регистре EEDATA остаются доступными до тех пор, пока не будет выполнена следующая операция чтения или записи в этот регистр. Запись в EEPROM-память данных. Запись данных в EEPROM-память требует большего количества шагов по сравнению с чтением. Процесс записи включает следующие этапы. Записать адрес ячейки EEPROM-памяти, в которую нужно записать данные, в регистр EEADR. Записать данные, которые необходимо сохранить, в регистр EEDATA. Сбросить бит EEPGD в 0, чтобы указать, что операция выполняется с EEPROM-памятью данных. Убедиться, что бит WREN (Write Enable) установлен в 1. Этот бит должен быть равен 0 во всех случаях, кроме непосредственной записи в EEPROM. Установить бит WR (Write) в 1 для начала процесса записи. Однако бит WR может быть установлен в 1 только в том случае, если бит WREN был установлен в 1 в предыдущих командах. Это означает, что биты WR и WREN не могут быть установлены одновременно одной командой. После инициализации записи бит WREN должен быть сброшен в 0. Это не влияет на процесс записи, но предотвращает случайные записи в дальнейшем. Перед началом записи в EEPROM необходимо выполнить обязательную последовательность команд, которая предотвращает случайную запись. Эта последовательность выполняется при отключенных прерываниях, чтобы избежать вмешательства в процесс записи. 5.9. Тактовый осциллятор Тактовый осциллятор — это устройство, которое постоянно вырабатывает электрические импульсы. При каждом новом электрическом импульсе микропроцессорная система выполняет элементарное действие. Компоненты системы (процессор, ПЗУ, ОЗУ и т. п.) взаимодействуют между собой в определенные такты. На рисунках 5.22 и 5.23 представлены резонаторы, на основе которых создают кварцевые и керамические тактовые осцилляторы. Рис. 5.22 Кварцевый резонатор Рис. 5.23 Керамический резонатор 153
Микроконтроллеры PIC оснащены встроенным осциллятором, который может работать в одном из режимов: – LP — низкочастотный резонатор; – XT — обычный резонатор; – HS — высокочастотный резонатор; – RC — внешняя RC-цепочка. В режимах LP, XT и HS внешний осциллятор может быть подключен ко входу OSC1 (рис. 5.24). При использовании внешнего кварца ко входам OSC1 и OSC2 микроконтроллера подключают два конденсатора (рис. 5.25). Например, при частоте кварца 4 МГц можно использовать два конденсатора на 22 пФ. Номиналы конденсаторов могут быть выбраны согласно таблице 5.9. Рис. 5.24 Использование внешнего осциллятора Рис. 5.25 Схема с кварцевым осциллятором Таблица 5.9 Выбор конденсатора для работы кварцевого осциллятора Режим LP LP XT XT XT HS HS Частота 32 кГц 200 кГц 100 кГц 2 МГц 4 МГц 4 МГц 10 МГц С1, С2 68–100 пФ 15–33 пФ 100–150 пФ 15–33 пФ 15–33 пФ 15–33 пФ 15–33 пФ Керамические резонаторы работают в диапазоне частот от 4 до почти 8 МГц. Они уступают по точности кварцевым осцилляторам, и обычно представляют собой устройства с тремя выводами, два из которых связаны со входами 154
OSC1 и OSC2 микроконтроллера, а третий — с «землей» (рис. 5.26). Для приложений, в которых точность синхронизации неважна, ко входу OSC1 микроконтроллера можно подключить внешний резистор и конденсатор (рис. 5.27). Рис. 5.26 Подключение керамического резонатора Рис. 5.27 Подключение RC-цепочки Отметим, что некоторые микроконтроллеры PIC оснащены встроенным осциллятором, не требующим никаких внешних компонентов. Он обычно работает с частотой 4 МГц и выбирается в ходе программирования устройства. Например, микроконтроллеры могут работать от внутреннего RC-осциллятора на 4 МГц. Регистр для управления внутренним осциллятором называется OSCCAL. 7 CAL3 6 5 4 3 2 CAL2 CAL1 CAL0 CALFST CALSLW 1 - 0 - Биты регистра OSCCAL биты 7–4: CAL3:CAL0: Биты калибровки внутреннего RC-генератора 0000 = наименьшая частота в пределах окна калибровки 1111 = наивысшая частота в пределах окна калибровки бит 3: CALFST: Бит смещения окна калибровки внутреннего RC-генератора 1 = увеличение частоты тактового генератора 0 = смещения нет бит 2: CALSLW: Бит смещения окна калибровки внутреннего RC-генератора 1 = уменьшение частоты тактового генератора 0 = смещения нет Примечание. Если бит CALFST = 1, то значение бита CALSLW игнорируется биты 1–0: Не реализованы: читаются как 0 155
Внутренний тактовый генератор формирует тактовый сигнал с частотой 4 МГц при напряжении питания. Запись калибровочной константы в регистр OSCCAL позволяет устранить технологический разброс параметров внутреннего RC-генератора. Биты CAL3:CAL0 используются для настройки частоты тактового генератора в пределах окна калибровки. 5.10. Основы языка программирования Си для микроконтроллеров Язык программирования Си (англ. C) — это универсальный процедурный язык, разработанный в 1972 г. Деннисом Ритчи в Bell Labs. Он оказал огромное влияние на современные языки (C++, Java, C#, Python и др.) и до сих пор широко используется в системном программировании, embedded-разработке, ОС (например, ядро Linux написано на Си). Среди особенностей языка Си можно выделить следующие особенности. Язык является процедурным языком, то есть программа состоит из функций. Для языка характерна статическая типизация — типы переменных определяются при компиляции. Существует возможность низкоуровневого обращения к данным (прямой доступ к памяти через указатели. Язык обладает относительной простотой и гибкостью. Программы можно компилировать, используя разные архитектуры. В данном разделе мы рассмотрим основные конструкции языка, которые позволят нам писать программы для микроконтроллеров PIC. В таблице ниже представлены основные типы данных, которые мы будем использовать в программах. 1 2 3 4 5 Тип данных int float double char void Размер (байт) 4 (обычно) 4 8 1 – Описание Целое число Число с плавающей точкой «Двойная» точность Символ «Пустой» тип (для указателей) Пример int x = 10; float y = 3.14; double z = 2.71; char c = 'A'; – Общая структура программы Программа на Си в основном состоит из заголовочного файла #include (одного или нескольких), обязательной функции main(), с которой начинается выполнение, функции вывода printf() (из <stdio.h>). ___________________________________________________________________ #include <stdio.h> // Подключение библиотеки ввода/вывода int main() { // Главная функция (точка входа) printf("Hello, World!\n"); // Вывод текста return 0; // Возврат кода завершения ___________________________________________________________________ 156
Далее приведем несколько примеров наиболее часто используемых структурных элементов: переменные, указатели, условные операторы, циклы, функции, массивы, структуры и препроцессор. 1. Переменные и константы Переменные — именованные области памяти, хранящие данные, которые можно изменять во время выполнения программы. Константы — неизменяемые значения, заданные на этапе компиляции. ___________________________________________________________________ int number = 5; const float PI = 3.1415; // Инициализация переменной // Константа (нельзя изменить) int a = 1, b = 2, c; ___________________________________________________________________ Переменные используются для хранения различных типов данных. Имена переменных чувствительны к регистру (var ≠ Var). 2. Указатели (Pointers) Переменные, хранящие адреса других переменных или областей памяти. Позволяют работать с памятью напрямую, передавать данные по ссылке и создавать динамические структуры. ___________________________________________________________________ int x = 10; int *ptr = &x; // ptr хранит адрес x printf("%d", *ptr); // Вывод значения по адресу (разыменование) ___________________________________________________________________ & — оператор взятия адреса. * — оператор разыменования. 3. Условные операторы Конструкции (if, else, switch), позволяющие выполнять разные участки кода в зависимости от условий. ___________________________________________________________________ // Конструкция if-else int age = 18; if (age >= 18) { printf("Взрослый\n"); } else { printf("Ребенок\n"); 157
} // Конструкция switch-case int day = 3; switch (day) { case 1: printf("Понедельник\n"); break; case 2: printf("Вторник\n"); break; default: printf("Другой день\n"); } ___________________________________________________________________ 4. Циклы Механизмы (for, while, do-while) для многократного выполнения блока кода, пока выполняется условие. ___________________________________________________________________ // Цикл for for (int i = 0; i < 5; i++) { printf("%d ", i); } // 0 1 2 3 4 // Цикл while int i = 0; while (i < 5) { printf("%d ", i++); } // 0 1 2 3 4 // Цикл do-while int i = 0; do { printf("%d ", i++); // 0 1 2 3 4 } while (i < 5); ___________________________________________________________________ 5. Функции Подпрограммы, выполняющие определенную задачу. Позволяют структурировать код, избегать дублирования и упрощают отладку. ___________________________________________________________________ int sum(int a, int b) { return a + b; } // Объявление функции 158
int main() { int result = sum(2, 3); // Вызов функции printf("%d", result); // 5 return 0; } ___________________________________________________________________ Функции могут возвращать значения (void, если ничего не возвращают). Параметры передаются по значению (если не используются указатели). 6. Массивы Структуры данных, хранящие набор элементов одного типа в непрерывной области памяти. Обеспечивают удобный доступ по индексу. ___________________________________________________________________ int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}}; ___________________________________________________________________ 7. Структуры (struct) Пользовательские типы данных, объединяющие несколько переменных (возможно разных типов) под одним именем. Используются для моделирования сложных объектов. ___________________________________________________________________ struct Person { char name[20]; int age; }; // Объявление структуры int main() { struct Person p1 = {"Alice", 25}; // Создание экземпляра printf("%s: %d лет", p1.name, p1.age); return 0; } ___________________________________________________________________ 8. Препроцессор Этап обработки кода до компиляции. Директивы (#include, #define, #ifdef) позволяют подключать файлы, задавать макросы и условно компилировать код. ___________________________________________________________________ #define PI 3.1415 #define SQUARE(x) (x * x) // Макрос // Макрос с параметром #if DEBUG == 1 printf("Режим отладки\n"); 159
#endif ___________________________________________________________________ Далее мы рассмотрим примеры написания программ на языке Си для микроконтроллеров PIC. Будут подробно рассмотрено специальное программное обеспечение для этого: программа mikroC PRO и программа MPLAB IDE. 5.11. Компилятор mikroC PRO для PIC-микроконтроллеров При программировании микроконтроллеров создается специальная программа, которая загружается в его flash-память. Эта программа называется исполняемый код и состоит из последовательности нулей и единиц. Она состоит из 12-, 14- или 16-битных слов, в зависимости от архитектуры микроконтроллера. Каждое слово считывается центральным процессором как команда и выполняется во время работы микроконтроллера. Все инструкции, которые микроконтроллер может распознать, называются набором команд. Первым языком, позволяющим создавать программы для загрузки в память микроконтроллера, является язык ассемблер. Основное преимущество этого языка программирования является его простота. Каждая команда программы соответствует одной ячейке памяти в микроконтроллере. Это позволяет полностью контролировать работу чипа. Однако этот язык не универсален. Программа, написанная одним программистом, трудна для понимания другим. Поэтому со временем появилось большое количество языков более высокого уровня организации. Одним из таких языков является язык Си. Основным преимуществом этого языка является простота написания программы. Написанная программа проста для понимания любого программиста, знающего языки программирования, близкие к языку Си. Процесс создания программы на языке Си и последующая запись кода в память микроконтроллера показан на рисунке 5.28. Рис. 5.28 Процесс программирования микроконтроллера 160
Подобно ассемблеру, существует множество программ на ЭВМ, которые позволяют преобразовать написанную программу в машинный код, понимаемый микропроцессорной системой. 5.11.1. Компилятор mikroC PRO для программирования PIC Программа mikroC PRO предназначена для написания программ для PICмикроконтроллеров на языке Си. Компилятор имеет все данные о внутренней архитектуре микроконтроллеров, наборе команд, именах регистров и их точных адресах, распиновке и т. д. Далее подробно будут рассмотрены основные функциональные особенности программы mikroC PRO v.4.60. Так выглядит основное окно программы после ее запуска. Рис. 5.29 Основное окно программы mikroC PRO Менеджер проекта (Project manager). Программа, написанная в программе mikroC, не является отдельным файлом, а является частью проекта, который включает в себя Hex код, код на ассемблере, заголовок и другие файлы. Некоторые из них создаются в процессе работы компилятора, некоторые из них импортируются из других программ. Окна Project manager (рис. 5.30) позволяют редактировать их все. Для редактирования файлов необходимо нажать правой кнопкой мыши любую папку и выбрать нужную опцию для вашего проекта. Окно «Навигация кода» (Code Explorer) позволяет легко найти функции и процедуры в рамках большой программы. Например, если вы посмотрите на функции, используемые в программе, просто дважды щелкните на ее имя в этом окне, и курсор будет автоматически установлен в соответствующее место программы. 161
Рис. 5.30 Окно менеджера проекта (Project manager) Настройки проекта (Project Settings). Для того чтобы компилятор мог успешно работать, необходимо указать базовую информацию о микроконтроллере, а также информацию о том, что требуется от него после процесса компиляции (рис. 5.31). Рис. 5.31 Окно настройки проекта (Project Settings) Устройство (Device) — при выборе типа микроконтроллера программа автоматически установит необходимые заголовки, настроит регистры специальных функций и адреса памяти устройства. Осциллятор (Oscillator) — эта опция используется для выбора скорости работы микроконтроллера. На основе этого выбора компилятор вносит изменения в регистр конфигурации устройства. Скорость работы устанавливается таким образом, чтобы настроить внутренний генератор микроконтроллера совместно с выбранным кристаллом кварца. Тип сборки Release — после окончания компиляции программы компилятор не может влиять на выполнение программы. Для отладки может быть использовано специальное программное обеспечение. 162
Тип сборки ICD debug. Когда процесс компиляции завершен и микроконтроллер запрограммирован, компилятор остается подключенным к микроконтроллеру и все еще может влиять на его работу. Соединение устанавливается через программатор, который подключен к компьютеру с помощью кабеля USB. Программное обеспечение, выполняющее настройку, называется внутрисхемный отладчик. Редактор кода (Code Explorer). Редактор кода является центральной частью окна компилятора и используется для написания программы. Для настройки этого блока можно вызвать специальное меню (нажав F12). До запуска программной отладки проекта необходимо выбрать соответствующий режим в окне настройки проекта (Build type — Release) и выбрать опцию Run/Start Debagger. Компилятор будет автоматически установлен в режиме симуляции. В этом режиме контролируется состояние всех битов регистра. Она также позволяет выполнить программу пошагово, контролируя работу микроконтроллера на экране. Симулятор и отладчик позволяют наблюдать за состоянием регистров во время выполнения программы. Разница в том, что симулятор выполняет программу на ПК, в то время как отладчик использует микроконтроллер. Окно Watch Window (Shift+F5) позволяет отслеживать состояние всех регистров микроконтроллера (рис. 5.32). Рис. 5.32 Просмотр регистров микроконтроллера (Watch Window) Дополнительные инструменты компилятора mikroC PRO USART — терминал. Терминал USART является заменой стандартному Hyper Terminal Windows. Он может быть использован для проверки работы микроконтроллера, который использует USART-связь. Такой микроконтроллер может быть подключен к разъему RS232 на ПК через последовательный кабель. Окно терминала USART, показанного на рисунке 5.33, содержит параметры для настройки последовательного соединения и для отображения переданных/полученных данных. 163
Рис. 5.33 USART-терминал Редактор семисегментного индикатора (Seven Segment Editor). Редактор семисегментного индикатора позволяет легко выяснить, какой номер необходимо установить на выходной порт, чтобы отобразить нужный символ. Необходимо поместить курсор на любой сегмент экрана и щелкнуть по нему. Необходимый для копирования номер будет показан сразу (рис. 5.34). Рис. 5.34 Редактор семисегментного индикатора Создание нового LCD-символа (LCD Custom Character). Помимо стандартных символов, микроконтроллер может также отправлять произвольные символы. Для создания символа необходимо нажать на квадратик в окне ЖК дисплея, а затем нажать на кнопку «Создать». Необходимый код появляется в другом окне (рис. 5.35). Использование специальных библиотек. Одной из самых полезных опций этой программы является Менеджер библиотек (Library Manager). Ранее было отмечено, что основным преимуществом языка Си является то, что проекты на этом языке с легкостью могут быть использованы другими программистами. Функциональные библиотеки являются лучшим примером этой особенности. 164
Если требуется функция для выполнения определенной задачи, можно просто найти ее в библиотеке, которая интегрирована в компилятор. Например, если нужна функция для генерации звука на некоторых выводах, можно открыть библиотеку Sound и дважды щелкнуть соответствующую функцию Sound_Play. Функции этой библиотеки автоматически зарегистрированы в процессе компиляции программного кода, так что не надо использовать команду #include. В таблице 5.10 представлены основные библиотеки, используемые в программе mikroC PRO v.4.60. Рис. 5.35 Создание нового LCD-символа Таблица 5.10 Библиотеки mikroC PRO Библиотека ADC Library CAN Library CANSPI Library Compact Flash Library EEPROM Library EthernetPIC18FxxJ60 Library Flash Memory Library Graphic Lcd Library I2C Library Keypad Library Lcd Library Manchester Code Library Multi Media Card Library One Wire Library Port Expander Library PS/2 Library PWM Library RS-485 Library Краткое описание Используется для управления АЦП Используется для управления CAN-модулем Используется для управления внешнего CAN-модулем (MCP2515 или MCP2510) Используется для работы с flash-картой Используется для управления EEPROM Используется для управления Ethernet-модулем Используется для работы с внутренней flash-памятью Используется для управления LCD-модуля Используется для управления модуля I2C Используется для управления клавиатурой (44 кнопки) Используется для управления LCD-дисплея (216 символов) Используется для работы с Manchester Code Используется для работы с MMC flash-картами Используется для управления One Wire serial соединением Используется для работы с MCP23S17 Используется для работы со стандартной клавиатурой PS/2 Используется для работы со встроенным ШИМ-модулем Используется для работы с модулями, использующими последовательную связь RS485 165
Продолжение табл. 5.10 Библиотека Software I2C Library Software SPI Library Software UART Library Sound Library SPI Library SPI Ethernet Library Краткое описание Используется для работы с I2C Используется для работы с SPI Используется для работы с UART Используется для генерации звуковых сигналов Используется для работы со встроенным SPI-модулем Используется для работы с SPI с ETHERNET-модулем Используется для работы с 4-битным SPI соединением SPI Graphic Lcd Library с LCD-дисплеем Используется для работы с 4-битным SPI соединением SPI Lcd Library с LCD-дисплеем (2x16 символов) Используется для работы с 8-битным SPI соединением SPI Lcd8 Library с LCD-дисплеем SPI 6963C Graphic Lcd Library Используется для работы с SPI и LCD-дисплеем UART Library Используется для работы со встроенным UART-модулем USB Hid Library Используется для работы со встроенным USB-модулем 5.11.2. Создание нового проекта и компиляция программы в mikroC PRO Для создания нового проекта лучше всего воспользоваться помощью New Project Wizard. Пользователю будут предложены варианты настройки будущего проекта, что существенно упрощает работу разработчика. В главном меню программы необходимо выбрать Project/New Project (Shift+Ctrl+N). После этого на экране должно появиться следующее окно (рис. 5.36). Рис. 5.36 Окно создания нового проекта 166
1. На первом шаге (рис. 5.37) помощник предлагает выбрать тип микроконтроллера, для которого планируется написание программы. Выберите в выпадающем списке модель PIC16F877A и нажмите кнопку Далее (Next). Рис. 5.37 Выбор типа микроконтроллера 2. На втором шаге (рис. 5.38) требуется выбрать частоту генератора, с которой будет работать микроконтроллер. Можно оставить предлагаемую частоту 8 МГц и нажать кнопку Далее (Next). Рис. 5.38 Выбор частоты тактового осциллятора 3. На следующем шаге требуется присвоить имя проекту. Назовите, например, свой проект Hello World. В окне должно быть указано: C:\путь к проекту\Hello World.mcppi. Нажмите кнопку Далее (Next). 167
4. На следующем шаге требуется добавить новые файлы в проект. Мы сознательно пропускаем этот шаг. Нажмите кнопку Далее (Next). 5. На пятом шаге (рис. 5.39) необходимо подключить дополнительные библиотеки. По умолчанию программа предлагает подключить все библиотеки. Оставьте все без изменений и нажмите кнопку Далее (Next). Рис. 5.39 Подключение библиотек 5. Далее помощник поздравляет нас с успешно созданным проектом (рис. 5.40). Необходимо отметить «галкой» поле для редактирования битов конфигурации (Open Edit Project window to set Configuration bits) и нажать кнопку Далее (Next). Рис. 5.40 Создание проекта 168
6. Заключительное окно (рис. 5.41) позволяет настроить биты конфигурации. Можно выбрать тип внешнего тактового генератора, задать работы сторожевого таймера, изменить частоту генератора и т. д. Оставьте все без изменений и нажмите кнопку ОK. Рис. 5.41 Настройка битов конфигурации 7. После создания проекта открывается окно, представленное на рисунке 5.29. Здесь нас интересует область редактора кода. Для первой программы предлагается использовать следующий код: __________________________________________________________________ void main() { // Главная функция программы TRISB = 0x00; PORTB = 0; // Настройка порта B на вывод данных // Очистка порта B do { PORTB = 0x01; Delay_ms(500); PORTB = 0x00; Delay_ms(500); } while (1); // // // // // // Начало бесконечного цикла Запись в RB0 логической единицы Временная задержка в 500 мс Запись в RB0 логического нуля Временная задержка в 500 мс Зацикливание программы } __________________________________________________________________ Подробно рассмотрим код нашей первой программы. Программа начинается с void main(). Каждая программа на C имеет один вход, с которого начинается выполнение программы, — главную программу. В программах на C оператор void main(void) указывает стартовую точку вашей программы. Далее указывается использование двух регистров. Регистра управления TRISB и регистра 169
данных PORTB. Знак = свидетельствует о присвоении этим регистрам определенных данных. В нашем случае присвоение TRISB нулей в шестнадцатеричной системе. Поскольку TRISB определяет направление работы портов ввода/вывода, то PORTB будет настроен на вывод. Запись нуля в PORTB очищает этот порт от каких-либо данных. Далее следует условный оператор do while, с бесконечным условием. Внутри оператора выполняется следующая операция: сначала в PORTB записывается логическая 1, потом функция Delay_ms(1000) задерживает выполнение программы на 0,5 с, далее в PORTB записывается логический 0 с последующей временной задержкой. И так до бесконечности, поскольку условий выхода из программы нет. Работу данной программы можно увидеть, если к выводу микроконтроллера RB0 через резистор подключить светодиод, который будет мигать с частотой 1 Гц. 8. Но нам известно, что это лишь программа на языке Си. Для компиляции машинного кода в меню необходимо выбрать пункт Build/Build или нажать на клавиатуре Ctrl+F9. Если проект создан без ошибок, то в итоге программа сформирует специальный файл с расширением *.hex, который следует загрузить в память микроконтроллера. На этом изучение основ создания, отладки и компиляции программы для микроконтроллера в программе mikroC PRO можно закончить. В следующих разделах будут рассмотрены программа и устройство для загрузки машинного кода в память микроконтроллера. 5.11.3. Программатор K150. Программная часть программатора microbrn Для программирования микроконтроллера PIC использован K150 USBпрограмматор (рис. 5.42). Рис. 5.42 Внешний вид программатора K150 USB Подключите программатор к компьютеру, используя кабель USB. Убедитесь в том, что устройство подключено правильно и готово к работе. На плате K150 USB должен загореться светодиод L3. 170
1. На начальном этапе, после подключения программатора K150 USB, необходимо выяснить, к какому COM-порту подключен программатор. Для этого откройте Мой компьютер/Управление/Диспетчер (Windows 7) устройств (рис. 5.43). В списке устройств найдите порты COM и LPT. Нас интересует устройство Prolific USB-to-Serial Comm Port (COM8) (в случае W10 и W11 необходимо использовать драйверы Prolific v.1.5). Запоминаем адрес COMпорта, к которому подключено устройство. В нашем случае COM8. Рис. 5.43 Диспетчер устройств в Windows 7 2. Далее на рабочем столе найдите ярлык программы DIY K150 PICmicro Programmer — microbrn.exe. На рисунке 5.44 представлено главное окно программы после запуска. Рис. 5.44 Главное окно программы DIY K150 PICmicro Programmer 171
3. Для настройки соединения программы DIY K150 PICmicro Programmer с устройством K150 необходимо указать номер COM-порта, к которому подключено устройство. В нашем случае это COM8. В программе File/Port/Serial Port Value. Укажите номер порта и нажмите кнопку ОК (рис. 5.45). Рис. 5.45 Выбор COM-порта в программе DIY K150 PICmicro Programmer 4. Далее необходимо указать марку программируемого микроконтроллера. В выпадающем списке выберите 16F877A (рис. 5.46). Рис. 5.46 Выбор марки программируемого микроконтроллера 5. После выбора микроконтроллера требуется загрузить файл с расширением *.hex в программу DIY K150 PICmicro Programmer. Для этого нажмите кнопку Load и выберите ранее созданный файл Hello World.hex. На рисунке 5.47 показан вид главного окна программы после загрузки машинного кода. Рис. 5.47 Окно главной программы после загрузки машинного кода в программу 172
6. Для начала программирования микроконтроллера нажмите кнопку Program. При правильном подключении и отсутствии ошибок в системе программа выдаст следующее окно (рис. 5.48). Рис. 5.48 Окно программирования микроконтроллера На данном этапе программа автоматически очистит память микроконтроллера и запишет в нее новую программу. На этом процесс программирования микроконтроллера в программе DIY K150 PICmicro Programmer можно закончить. Результат работы запрограммированного микроконтроллера представлен на рисунке 5.49. К выходу микроконтроллера RB7 подключен светодиод. Согласно программе на вывод RB7 подается логическая 1 (5В), далее следует временная задержка длительностью 0,5 с. При этом загорается светодиод, который подключен к выводу RB7. На следующем шаге на вывод RB7 подается логический 0 (0В). Светодиод, подключенный к RB7, гаснет. Рис. 5.49 Результат выполнения программы 5.12. Среда программирования MPLAB IDE и программатор Pickit для PIC-микроконтроллеров В данном разделе мы рассмотрим использование еще одной популярной IDE, которая позволяет программировать микроконтроллеры. Программа называется MPLAB X IDE, и будет полезна, если вы работаете с микроконтроллерами Microchip (PIC, dsPIC, AVR). На официальном сайте https://www.microchip. com/ можно скачать дистрибутив для установки программы на компьютер. До173
полнительно разработчик предлагает набор компиляторов на языке Си, позволяющих компилировать программы для микроконтроллеров с разной архитектурой: MPLAB XC8 (для 8-битных микроконтроллеров PIC10/12/16/18), MPLAB XC16 (для 16-битных микроконтроллеров dsPIC30/33 и PIC24), MPLAB XC32 (для 32-битных микроконтроллеров PIC32). Далее будут представлены примеры написания программ в MPLAB X IDE версии 6.25, а компиляция программ будет выполнена с помощью компилятора MPLAB XC8 версии 2.5. 5.12.1. Среда программирования MPLAB IDE для программирования PIC Программа MPLAB X IDE позволяет создавать программы для PICмикроконтроллеров на языке Си. В программе сохранена информация о внутренней архитектуре микроконтроллеров, наборе команд, имен регистров и их точных адресах и т. д. Далее подробно будут рассмотрены основные функциональные особенности программы MPLAB X IDE v.6.25. На рисунке 5.50 представлен внешний вид программы. Рис. 5.50 Основное окно программы MPLAB X IDE Основные элементы программы MPLAB. В верхней части программы расположено главное меню (1) (Menu Bar), которое содержит выпадающие элементы меню для выполнения различных задач. Панель инструментов (4) (Toolbar) расположена под главным меню. Содержит значки для быстрого доступа к наиболее часто используемым командам. Окно проектов (2) (Projects Window) находится слева. Отображает структуру открытого проекта. Окно редактора (5) (Editor Window) предназначено для написания и редактирования кода. Данный редактор поддерживает подсветку синтаксиса, автозавершение кода и другие полезные функции. В окне вывода (6) (Output Window) отображаются сообщения компилятора, линкера и отладчика. Показываются ошибки, предупреждения и другая информация о процессе сборки и отладки. На панели инструментов (3) (Dashboard) отображается информация о статусе проекта, со174
стоянии подключенного отладчика и другая полезная информация (может отсутствовать или иметь другое название, в зависимости от версии MPLAB X IDE). В окне отладчика (Debugger Windows) выполняется отладка проекта. 5.12.2. Создание нового проекта и компиляция программы в MPLAB IDE Для создания нового проекта рекомендуется воспользоваться New Project Wizard. Пользователю будут предложены варианты настройки будущего проекта, что существенно упрощает подготовку нового проекта. В главном меню программы необходимо выбрать File/New Project (Shift+Ctrl+N). После этого на экране должно появиться следующее окно (рис. 5.51). В новом окне выбираем Microchip Embedded → Application Project(s) и нажимаем кнопку Далее (Next). Рис. 5.51 Окно создания нового проекта 1. На следующем шаге (рис. 5.52) помощник предлагает выбрать тип микроконтроллера, для которого планируется написание программы. Выберите в выпадающем списке модель PIC16F877A и нажмите кнопку Далее (Next). Рис. 5.52 Выбор типа микроконтроллера 175
2. Далее (рис. 5.53) требуется выбрать компилятор. В проекте используется 8-битный микроконтроллер PIC16F877A, а значит, можно использовать компилятор XC8. Нажимаем кнопку Далее (Next). Рис. 5.53 Выбор компилятора 3. После выбора компилятора необходимо дать название проекту и указать корневую директорию для сохранения файлов (рис. 5.54). Нажимаем кнопку Далее (Next). Рис. 5.54 Выбор директории для сохранения проекта 4. В открывшемся основном окне программы необходимо перейти в раздел редактора проекта и создать новый файл *.c. Выбираем Source Files → New → main.c. Можно оставить название файла по умолчанию. В окне редактора кода откроется файл программы, в который мы добавим код на следующем этапе. 5. Далее необходимо скопировать и вставить код программы в файл main.c. Основные части программы имеют комментарий. __________________________________________________________________ #include <xc.h> #define _XTAL_FREQ 20000000 // Стандартная библиотека для PIC // Частота кварцевого резонатора (20 МГц) // Конфигурация микроконтроллера (укажите свои настройки) 176
#pragma #pragma #pragma #pragma #pragma #pragma #pragma #pragma config config config config config config config config FOSC = HS WDTE = OFF PWRTE = OFF BOREN = ON LVP = OFF CPD = OFF WRT = OFF CP = OFF // // // // // // // // HS Oscillator, High Speed Watchdog Timer disabled Power-up Timer disabled Brown-out Reset enabled Low-Voltage Programming disabled Data EE memory code protection off Flash Program Memory Write Enable off Flash Program Memory Code Prot. off // Определяем вывод, к которому подключен светодиод (RB0 в этом примере) #define LED_PIN RB0 void main(void) { // Настройка выводов TRISB0 = 0; // Устанавливаем RB0 (LED_PIN) как выход while (1) { // Включаем светодиод LED_PIN = 1; // __delay_ms(500); // или PORTBbits.RB0 = 1 Задержка 500 мс (0,5 с) // Выключаем светодиод LED_PIN = 0; // __delay_ms(500); // или PORTBbits.RB0 = 0; Задержка 500 мс (0,5 с) } return; // Эта строка не обязательна } __________________________________________________________________ Подробно рассмотрим код нашей первой программы. Программа начинается с void main(). Каждая программа на C имеет один вход, с которого начинается выполнение программы, — главную программу. В программах на C оператор void main(void) указывает стартовую точку вашей программы. Далее указывается использование двух регистров. Регистра управления TRISB и регистра данных PORTB. Знак «=» свидетельствует о присвоении этим регистрам определенных данных. В нашем случае присвоение TRISB нулей в шестнадцатеричной системе. Поскольку TRISB определяет направление работы портов ввода/вывода, то PORTB будет настроен на вывод. Запись нуля в PORTB очищает этот порт от каких-либо данных. Далее следует условный оператор do while, с бесконечным условием. Внутри оператора выполняется следующая операция: сначала в PORTB записывается логическая 1, потом функция Delay_ms(1000) задерживает выполнение программы на 0,5 с, далее в PORTB записывается логический 0 с последующей временной задержкой. И так до бесконечности, поскольку условий выхода из программы нет. Замените _XTAL_FREQ на фактическую частоту вашего кварцевого резонатора (в Гц). Например, если у вас кварц на 4 МГц, оставьте 4000000. Если у вас кварц на 20 МГц, измените на 20000000. Это очень важно для точной работы функций задержки __delay_ms(). Обязательно учитывайте данный параметр в будущих проектах. 177
Определите вывод LED_PIN правильно. В коде LED_PIN RB0 указывает, что светодиод подключен к выводу RB0 микроконтроллера. Если вы подключили светодиод к другому выводу, например, к RB5, то замените RB0 на RB5. Проверьте схему подключения. Настройка выводов TRIS. TRISB0 = 0; или TRISBbits.TRISB0 = 0; (устанавливает вывод RB0 как выход). Биты в регистре TRISB определяют направление работы выводов порта B. Значение 0 означает «выход», а значение 1 означает «вход». По аналогии: TRISB = 0xFF (все выводы порта B как вход). Настройка проекта осуществляется установкой конкретных значений в конфигурационных битах. В секции #pragma config настроены конфигурационные биты микроконтроллера. Эти биты определяют, как будет работать микроконтроллер (частота тактирования, сторожевой таймер, защита памяти и т. д.). Если вы не уверены, какие настройки конфигурационных битов нужны, обратитесь к документации на PIC16F877A. Ошибки в настройке этих битов могут привести к неработоспособности микроконтроллера. В программе MPLAB можно выполнить генерации данной части программы автоматически. Для этого выберите в главном меню Production -> Set Configurations Bits. Укажите нужные параметры для настройки и нажмите кнопку Generate Source Code to Output. Сгенерированный код программы можно будет скопировать и добавить в основную программу. В таблице 5.11 представлены основные биты конфигурации для микроконтроллера PIC16F877A. Таблица 5.11 Биты конфигурации для PIC16F877A Биты конфигурации FOSC = HS WDTE = OFF PWRTE = OFF BOREN = ON LVP = OFF CPD = OFF WRT = OFF CP = OFF Краткое описание Выбор типа генератора тактовой частоты (в данном случае высокоскоростной кварцевый резонатор). Если у вас используется внутренний генератор, выберите соответствующую опцию Отключает сторожевой таймер (Watchdog Timer) Отключает таймер включения питания Включает схему сброса при понижении напряжения (Brownout Reset) Отключает программирование низким напряжением. Если вы используете программатор PICKit, убедитесь, что этот бит настроен правильно Отключает защиту EEPROM-памяти Отключает защиту флэш-памяти от записи Отключает защиту программной памяти 6. Для компиляции машинного кода в меню необходимо выбрать пункт Production/Build Main Project или нажать на клавиатуре F11. Если проект создан без ошибок, то в итоге программа сформирует специальный файл с расширением *.hex, который следует загрузить в память микроконтроллера. Загрузить программу в память микроконтроллера можно с помощью программатора K150 178
или PICKit. Последний вариант позволит сделать это непосредственно в программе MPLAB. Работу данной программы можно увидеть, если к выводу микроконтроллера RB0 через резистор подключить светодиод. На этом изучение основ создания, отладки и компиляции программы для микроконтроллера в программе MPLAB X IDE можно завершить. В следующих разделах будут рассмотрены программа и устройство для загрузки машинного кода в память микроконтроллера. 5.12.3. Программатор PICkit. Программная часть программатора PICkit Для программирования микроконтроллера PIC будет использован программатор PICkit 2 (рис. 5.55). Можно выбрать и более позднюю версию программатора, например, PICkit 3. Рис. 5.55 Внешний вид программатора PICkit версии 2 и 3 Подключите программатор к компьютеру, используя кабель USB (рис. 5.56). Убедитесь в том, что устройство подключено правильно и готово к работе. На плате PICkit должен загореться светодиод POWER, который сигнализирует о подключении устройства. Рис. 5.56 Подключение программатора PICkit 2 к компьютеру 179
1. На первом этапе, после подключения программатора PICkit к компьютеру, убедитесь в том, что светодиод POWER светится. Устройство использует активное USB-подключение. По этой причине установка специальных драйверов не требуется. 2. Далее на рабочем столе найдите ярлык программы PICkit 2.exe. На рисунке 5.57 показано главное окно программы после запуска. Убедитесь, что подключенное устройство к компьютеру определяется программой. Рис. 5.57 Главное окно программы PICkit 2 В программе должен быть статус активного подключения (connected). Дополнительно отображается ID устройства. Если устройство не определено в системе, то отключите устройство от компьютера, а потом подключите заново. Тест подключения выполните с помощью команды Check Communication, проверку подключения. Для этого в главном меню выберите инструменты (Tools). На рисунке 5.58 показан выбор теста. Для чтения, записи и стирания программы можно использовать соответствующие кнопки в главном окне программы PICkit 2. 4. Далее необходимо подключить микроконтроллер к программатору PICkit и повторно проверить статус подключения устройства. Программа должна указать прежний статус подключения устройства. Дополнительно в программе отобразится информация о подключенном микроконтроллере. В нашем случае используется 180
микроконтроллер PIC16F877A. На рисунке 5.59 показано главное окно программы при подключении микроконтроллера. Рис. 5.58 Тест подключенного устройства PICkit 2 Рис. 5.59 Подключение МК к программатору 5. После выбора микроконтроллера требуется загрузить файл с расширением *.hex в программу PICkit. Для этого нажмите кнопку File → Import Hex (или CTRL + I) и выберите ранее созданный файл. В нашем случае файл имеет название project_0.X.production.hex. Файл прошивки, как правило, по умолчанию находится в папке для проектов MPLAB для текущего пользователя из группы Users. На рисунке 5.60 показана директория, в которой находится файл с расширением *.hex. Далее необходимо нажать кнопку Write. Будет выполнена загрузка программы в память устройства. На рисунке 5.61 показан вид главного окна программы после загрузки машинного кода. 181
Рис. 5.60 Размещение файла с расширением *.hex на компьютере Рис. 5.61 Окно главной программы после загрузки машинного кода в программу При правильном подключении, программировании и отсутствии ошибок в PICkit будет показан успешный статус Programming Successeful. Результат работы запрограммированного микроконтроллера представлен на рисунке 5.62. К выходу микроконтроллера RB7 подключен светодиод. В программе на вывод RB7 подается логическая 1 (5В), далее следует временная задержка длительностью 1 с. При этом загорается светодиод, который под182
ключен к выводу RB7. На следующем шаге на вывод RB7 подается логический 0 (0В). Светодиод, подключенный к RB7, гаснет. Рис. 5.62 Результат выполнения программы 5.13. Практические работы 5.13.1. Практическая работа № 1. Программирование портов В данной работе предлагается ознакомиться с работой портов ввода/ вывода микроконтроллеров PIC. В качестве объекта исследований используются порты общего назначения — порт B и порт C. Порт C настраивается на вывод данных, порт B — на ввод. К первому (RB0) и второму выводу (RB1) порта B подключаются кнопки. К первому (RC0) и второму выводу (RC1) порта C подключаются светодиоды. Если на выход RB0 подать логическую 1, то мы увидим, что светодиод загорелся. Если на выход RB0 подать логический 0, то мы увидим, что светодиод гаснет. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 Кнопка Макетная плата x1 x1 Дополнительный блок компонентов: Светодиод x2 Резистор 220–330 Ом Резистор 10 кОм x2 x2 183 Кнопка Проводники x2 x1
1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.63. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Светодиоды необходимо подключить к порту C, а не к порту A, как это показано на схеме. Дополнительное задание. Требуется изменить схему так, чтобы ко входу RB1 была подключена кнопка, а к выходу RС1 были подключены дополнительные светодиоды. При этом при нажатии на кнопку микроконтроллер выполняет функцию последовательного включения и выключения светодиодов. Временная задержка между переключением светодиодов составляет 500 мс. 2. Принципиальная схема Рис. 5.63 Программирование портов ввода/выводов 3. Пример программного кода __________________________________________________________________ void main() { TRISС PORTС TRISB PORTB = = = = 0x00; 0; 0xFF; 255; do { if (RB0_bit == 0) { PORTС = 0x01; Delay_ms(1000); // // // // Все входы Начальное Все входы Начальное порта С настроены как выходы состояние порта С порта B настроены как входы состояние порта B // Начало бесконечного цикла // Если кнопка, подключенная к RB0, нажата // Передать в порт С значение 0x01 // Временная задержка в 1000 мс 184
} if (RB1_bit == 0) { PORTС = 0x02; Delay_ms(1000); } PORTС = 0x0; // Если кнопка, подключенная к RB1, нажата // Передать в порт С значение 0x02 // Временная задержка в 1000 мс // Очистка порта С } while (1); } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Для чего нужны порты ввода/выводов микроконтроллеров? 2. Связь памяти МК и портов ввода/вывода. 3. Опишите схему взаимодействия портов ввода/выводов с центральным процессором. 4. Какое количество портов имеет МК PIC16F877A? Какие альтернативные функции они реализуют? 5. Каково назначение регистра направления передачи порта? 6. Для чего нужны дополнительные регистры управления? 7. Какой разрядности бывают порты? 8. Можно ли обрабатывать 16-разрядные числа, если микроконтроллер имеет только 8-разрядные порты? 9. Для чего используются подтягивающие резисторы? 10. Какие типы буферов используются при создании портов ввода/вывода? 5.13.2. Практическая работа № 2. Использование таймера В лабораторной работе рассматривается практическое использование различных таймеров и прерывания. Таймер TMR0 используется с предварительным делителем. Прерывание происходит каждый раз в результате переполнения регистра таймера. При каждом прерывании автоматически увеличивается переменная “counter” на 1. Когда значение “counter” достигает 1000, порт B увеличивается на 1. Вся процедура осуществляется независимо от основной программы, что позволяет микроконтроллеру выполнять другие процедуры. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 185 Кнопка Макетная плата x1 x1
Дополнительный блок компонентов: Светодиод x8 Резистор Проводники 220–330 Ом x8 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.64. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Рассчитайте значение TMR0 и значение переменной “counter”, которые удовлетворяли бы условию программного прерывания с интервалом 1 с. Докажите, что выполнение программы прерывания не нарушает выполнение основной программы. 2. Принципиальная схема Рис. 5.64 Использование таймеров микроконтроллера 3. Программный код __________________________________________________________________ unsigned counter; // Определение переменной counter void interrupt() { counter++; TMR0 = 100; INTCON = 0x20; } // В случае прерывания увеличить cnt на 1 // Возврат TMR0 в начальное состояние // Бит T0IE установлен, bit T0IF очищен 186
void main() { OPTION_REG = 0x84; TRISB = 0; PORTB = 0x0; TMR0 = 100; INTCON = 0xA0; counter = 0; // // // // // // Назначение предделителя для TMR0 Все входы порта B настроены на вывод Сброс порта B TMR0 считает от 100 до 255 Разрешить прерывания по TMR0 Установить переменную cnt в нуль do { // Бесконечный цикл if (counter == 1000) { // После 1000 прерываний PORTB = PORTB++; // Увеличить число в порте B на единицу counter = 0; // Сбросить переменную counter } } while (1); } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Для чего нужны таймеры? 2. Какие таймеры имеют микроконтроллеры семейства PIC16? Каковы их основные отличия? 3. Назовите биты регистров управления таймерами OPTION_REG, T1CON, T2CON. 4. Для чего нужен предделитель таймера? Опишите схему настройки предделителя. 5. Найдите время переполнения TMR0, если: кварц на 8 МГц, а коэффициент деления равен 64. Также примем, что в регистр TMR0 загружено десятичное число 100. 6. Найдите значение TMR0, если: кварц на 12 МГц, а коэффициент деления равен 32. Также примем, что время переполнения наступило через 250 мкс. 7. Каким образом используется TMR1 в режиме таймера? 8. Опишите схему использования TMR1 в режиме счетчика. 9. Могут ли таймеры использовать внешний тактовый генератор? 10. Опишите схему функционирования TMR2. 5.13.3. Практическая работа № 3. Использование сторожевого таймера В лабораторной работе исследуется функционирование сторожевого таймера (WDT). В программе, представленной ниже, показано, как не следует использовать сторожевой таймер. Команда для сброса таймера специально вставлена в основной цикл программы. Подобный подход позволяет WDT сбросить состояние микроконтроллера. В ходе выполнения программы микроконтроллер будет сбрасываться все то время, пока происходит мигание светодиода на выходе порта B. 187
Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 Кнопка Макетная плата x1 x1 x2 Дополнительный блок компонентов: Светодиод Резистор 220–330 Ом Проводники x8 x8 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.65. Записать в память микроконтроллера программу, приведенную в п. 3. Для того чтобы программа работала правильно, необходимо включить сторожевой таймер. Убедиться в работоспособности схемы. Дополнительное задание. Необходимо изменить программу микроконтроллера так, чтобы сброс сторожевого таймера происходил независимо от выполнения основной программы. 2. Принципиальная схема Рис. 5.65 Использование сторожевого таймера 188
3. Программный код __________________________________________________________________ void main() { OPTION_REG = 0x0E; // Установка предделителя для WDT (1:64) asm CLRWDT; // Ассемблерная команда для очистки WDT PORTB = 0x0F; TRISB = 0; // Начальное состояние регистров порта B // Все входы порта B настроены на вывод Delay_ms(500); PORTB = 0xF0; // 500 мс задержка // Состояние порта B отличное от начального while (1); // Бесконечный цикл } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Какую функцию выполняет сторожевой таймер? 2. Отличие сторожевого таймера от TMR0, TMR1, TMR2. 3. Назовите биты регистра управления сторожевого таймера. 4. Для чего нужен предделитель сторожевого таймера? Опишите схему настройки предделителя. 5. Какие функции выполняет сторожевой таймер в режиме энергосбережения SLEEP? 6. Какие функции выполняет сторожевой таймер при выходе из режима энергосбережения SLEEP? 7. Какие функции выполняет сторожевой таймер при выходе из режима энергосбережения SLEEP по прерыванию? 8. Если используется предделитель WDT на 8, 32, 128, то как при этом будут выглядеть биты настройки регистра OPTION_REG? 9. Назовите ассемблерную команду для работы с WDT. 10. В чем недостаток использования сторожевого таймера в основном цикле программы? 5.13.4. Лабораторная работа № 4. Модуль CCP как ШИМ-генератор В лабораторной работе исследуется функционирование CCP1 модуля в режиме ШИМ. Чтобы сделать схему более интересной, длительность выходных импульсов RC2 может быть изменена с помощью кнопок, отмеченных как «ТЕМН.» и «СВЕТЛ.». Во время работы модуль находится под контролем специальных функций, принадлежащих специализированной библиотеке PWM. Некоторые из них: 189
PWM1_init имеет прототип: void Pwm1_Init(long freq); PWM1_Start имеет прототип: void Pwm1_Start(void); PWM1_Set_Duty имеет прототип: void Pwm1_Set_Duty (unsigned short duty_ratio). Параметр freq задает частоту PWM-сигнала и выражается в герцах. Параметр duty_ratio устанавливает длительность импульса в последовательности импульсов. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 Кнопка Макетная плата x1 x1 x2 Дополнительный блок компонентов: Светодиод Резистор 220–330 Ом Резистор 10 кОм Кнопка Проводники x2 x2 x2 x2 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.66. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Необходимо изменить программу микроконтроллера так, чтобы алгоритм новой программы позволял подключать и настраивать дополнительный ШИМ-модуль (CCP2). Для реализации проекта предлагается использовать следующие функции: PWM2_init прототип void Pwm2_Init(long freq_2); PWM2_Start имеет прототип: void Pwm2_Start(void); PWM2_Set_Duty имеет прототип: void Pwm2_Set_Duty (unsigned short duty_ratio_2). Установить значение переменной freq_2 = 2000, что соответствует частоте генератора 2 КГц. К выходу микроконтроллера RC1 подключить дополнительный светодиод. 190
2. Принципиальная схема Рис. 5.66 Модуль CCP как ШИМ-генератор 3. Программный код __________________________________________________________________ unsigned short current_duty, old_duty; // Определение переменных void initMain() { // Функция настройки портов PORTA = 0; TRISA = 0; PORTB = 255; TRISB = 255; PORTC = 0; TRISC = 0; PWM1_Init(5000); // Инициализация PWM-модуля (5KHz) } void main() { initMain(); current_duty = 100; // Начальное состояние current_duty 191
old_duty = 0; PWM1_Start(); PWM1_Set_Duty(current_duty); // Сбросить переменную old_duty // Запуск PWM1-модуля // Установка параметров PWM1-модуля while (1) { if (RB0_bit == 0) current_duty++; // Кнопка, подключенная к RB0, нажата // Увеличить параметр current_duty if (RB1_bit == 0) current_duty--; // Кнопка, подключенная к RB1, нажата // Уменьшить параметр current_duty // Если current_duty и old_duty не равны if (old_duty != current_duty) { PWM1_Set_Duty(current_duty); // Новые параметры PWM old_duty = current_duty; // Cохранить новое значение PORTA = old_duty; // Показать его в порте B } Delay_ms(200); } } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Для чего нужна широтно-импульсная модуляция? 2. Связь таймеров и модуля ШИМ. 3. Регистры управления модуля ШИМ. 4. Опишите схему функционирования модуля ШИМ. 5. Опишите схему функционирования модуля ШИМ в режиме захвата. 6. Опишите схему функционирования модуля ШИМ в режиме сравнения. 7. Основные характеристики ШИМ-сигнала: скважность, период. Временная диаграмма ШИМ-сигнала. 8. Расчет максимального разрешения ШИМ для заданной частоты. 9. Связь частоты модуля ШИМ и частоты микроконтроллера. 10. Последовательность включения модуля ШИМ. 5.13.5. Практическая работа № 5. Изучение работы аналогового компаратора В лабораторной работе исследуется работа встроенных аналоговых компараторов. Предлагается реализовать режим, при котором в микроконтроллере будет активирован один независимый компаратор. 192
Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 Кнопка Макетная плата x1 x1 Дополнительный блок компонентов: Светодиод x1 Резистор Потенциометр Проводники 220–330 Ом x1 x2 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.67. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял подключать и настраивать два независимых аналоговых компаратора. 193
2. Принципиальная схема Рис. 5.67 Использование модуля аналогового компаратора 3. Программный код __________________________________________________________________ void main() { TRISC = 0; TRISA = 0x0F; CMCON = 0x05; // // // // Все входы порта C настроены на вывод RA0–RA3 входы порта A настроены на ввод RA4–RA5 входы порта A настроены на вывод Настройка 1-го компаратора while (1) { PORTC.B1 = CMCON.C1OUT;// RB1 настроить на выход C1OUT Delay_ms(100); // Задержка 100 мс } } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Для чего нужен компаратор? 2. Опишите схему преобразования аналогового сигнала в дискретный. 3. Приведите временную диаграмму работы одного компаратора. 4. Регистры управления модуля компараторов. 5. Режим работы одного независимого компаратора. 6. Режим работы двух независимых компараторов. 7. Режим работы компараторов с четырьмя мультиплексируемыми входами. 8. Работа компараторов от одного источника опорного напряжения. 194
9. Работа компараторов от одного источника опорного напряжения и внешнего выхода. 10. Три мультиплексируемых входа для двух компараторов. 5.13.6. Практическая работа № 6. Использование аналого-цифрового преобразователя В лабораторной работе рассматривается использование АЦП микроконтроллера PIC16F877A. Переменный аналоговый сигнал подается на канал AN2, в то время как 10-битный результат преобразования отображается на портах B и D (8 младших разрядов порта D и 2 старших бита порта B). В качестве отрицательного опорного напряжения Vref- используется регулируемый источник напряжения. Положительное опорное напряжение подается на вывод AN3. Использование двух независимых источников напряжения позволяет изменять диапазон АЦП. АЦП всегда генерирует 10-битный двоичный результат, который имеет 1024 уровня напряжения. Чем меньше разница между Vref + и Vref-, тем меньше разница между двумя соседними уровнями. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 Кнопка Макетная плата x1 x1 Дополнительный блок компонентов: Светодиод x 10 Резистор Потенциометр Проводники 220–330 Ом x 10 x2 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.68. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял подключать и настраивать два независимых входа модуля АЦП. Результаты аналого-цифрового преобразования от первого входа отображаются в порте B, а результаты второго — в порте D. 195
2. Принципиальная схема Рис. 5.68 Использование модуля аналого-цифрового преобразователя 3. Программный код __________________________________________________________________ unsigned int value; // Определение переменной void main() { TRISA = 0xFF; TRISB = 0x3F; TRISD = 0; ADCON1.F4 = 1; // // // // Выводы AN2 и AN3 аналоговые RB7 и RB6 настроены на вывод Порт D настроен на вывод Установить опорное напряжение с RA3 do { value PORTD PORTB } while // // // // Результат преобразования в value 8 разрядов отображены в порт D 2 разряда в битах RB6 и RB7 порта B Бесконечный цикл = ADC_Read(2); = value; = value >> 2; (1); } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Чем отличается аналоговый сигнал от цифрового? 2. Дискретизация сигнала, частота выборки и эффект наложения частот. 3. Аналого-цифровой преобразователь. Виды АЦП. Области применения АЦП. 4. Параметры систем АЦП: разрядность, усиление, разрешающая способность. 196
5. АЦП последовательного приближения. 6. Регистры управления модуля АЦП. 7. Использование регулируемого источника опорного напряжения. 8. Режимы тактирования АЦП. 9. Как реализовать отображение 10-разрядного числа в 2-разрядное в 8битных портах микроконтроллера? 10. Назовите основные настройки модуля АЦП для МК PIC16F877A. 5.13.7. Практическая работа № 7. Последовательная связь (RS232) В работе рассматривается использование USART-модуля микроконтроллера. Подключение к ПК происходит через двунаправленный последовательный порт RS232. Программа работает следующим образом. Каждый байт, полученный через последовательный интерфейс, отображается с помощью светодиода, подключенного к порту B, и автоматически возвращается к передатчику. Если произойдет ошибка при приеме, то об этом будут сигнализировать переключения светодиода. Самый простой способ проверить работу устройства — это воспользоваться стандартной программой Windows — Hyper Terminal. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 Кнопка Макетная плата x1 x1 Дополнительный блок компонентов: Светодиод Резистор 220–330 Ом x9 x9 RS232–USB Проводники x1 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, использовать за основу схему, приведенную на рисунке 5.69. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял отправлять и принимать данный в/из COM-порта. К микроконтроллеру необходимо подключить 3 кнопки 197
и 3 светодиода. Для отправки значений в СОМ-порт с ПК необходимо использовать программу USART test.exe. Нажатие кнопки Bled1 в программе инициирует отправку 1 (единицы) в последовательный порт, Bled2 отправку 2, Bled3 отправку 3. Принимая полученные значения, микроконтроллер должен включать светодиод 1, 2 или 3. Нажатие кнопки B1, подключенной к микроконтроллеру, инициирует отправку 1 (единицы) в последовательный порт, кнопки B2 отправку 2, кнопки B3 отправку 3. Принимая полученные значения, программа на ПК должна включать индикаторы. Важно. Обратите внимание, что скорость порта микроконтроллера и программы на ПК должны совпадать. Примечание. В качестве альтернативы для работы с COM-портом можно использовать любую аналогичную программу. Например, Terminal 1.9b. Внешний вид программы Terminal 1.9b В этом случае работа с программой будет использовать окно Transmit для передачи данных. Номер порта можно выбрать в окне COM port, в окне Baud rate — скорость передачи данных. Скорость передачи данных порта микроконтроллера и программы на ПК должны совпадать. 198
2. Принципиальная схема Рис. 5.69 Последовательная связь (RS232) — общий вид схемы 3. Программный код __________________________________________________________________ unsigned short i; void main() { UART1_Init(19200); // Инициализация модуля USART // (8 бит, 19200 скорость передачи) while (1) { if (UART1_Data_Ready()) { i = UART1_Read(); UART1_Write(i); } } // Инициализация модуля USART // Если данные получены, // читать их и отправить обратно } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Чем отличается синхронный от асинхронного режима передачи данных? 2. Модуль USART, используемый в микроконтроллерах. 3. Режимы модуля USART. 4. Асинхронный режим USART. 5. Синхронный ведущий режим USART. 6. Синхронный ведомый режим USART. 7. Регистры управления модуля USART. 8. Параметры настройки USART модуля микроконтроллера. 9. Настройка модуля USART. 10. Схема подключения микроконтроллера к ПК. 199
5.13.8. Практическая работа № 8. Использование памяти EEPROM В работе рассматривается запись и чтение данных во встроенную память микроконтроллера EEPROM. Программа работает следующим образом. Основной цикл постоянно читает EEPROM-память по адресу 5 (десятичное). Затем программа входит в бесконечный цикл, в котором увеличивается значение порта B, при этом проверяются состояния входа RA.2. В момент нажатия кнопки MEMO номер, сохраненный в порт B, будет сохранен в EEPROM и отображен в порт D в двоичной форме. Для того чтобы проверить эту схему, достаточно нажать на кнопку MEMO и выключить устройство. После перезагрузки устройства программа будет отображать сохраненные значения в порте D. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 Кнопка Макетная плата x1 x1 x2 Дополнительный блок компонентов: Светодиод Резистор 220–330 Ом Кнопка Резистор 10 кОм Проводники x 16 x 16 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.70. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял записывать номер n (n = 0...3) в память EEPROM. Номер n определяет, какой из четырех светодиодов, подключенных к выводам порта В, будет включен. Номер n определяется нажатием кнопки, подключенной к одному из входов порта A. После перезагрузки устройства программа будет включать светодиод, номер которого определен встроенной памятью. 200
2. Принципиальная схема Рис. 5.70 Использование памяти EEPROM 3. Программный код __________________________________________________________________ void main() { TRISB PORTB PORTD TRISD TRISA = = = = = 0; 0; 0; 0; 0xFF; PORTD = EEPROM_Read(5); do { PORTB = PORTB++; Delay_ms(100); if (PORTA.B2) { EEPROM_Write(5, PORTB); PORTD = EEPROM_Read(5); do; while (PORTA.B2); } } while (1); // // // // // Все входы Начальное Все входы Начальное Все входы порта B настроены на вывод состояние порта B порта D настроены на вывод состояние порта D порта A настроены на вход // Чтение EEPROM-памяти по адресу 5 // Увеличить порт B на единицу // Если MEMO нажата, сохраняем в PORTB // Чтение записанных данных // Оставаться в цикле при нажатии кнопки // Бесконечный цикл } __________________________________________________________________ 201
4. Вопросы для самоконтроля 1. В чем отличие принстонской и гарвардской архитектуры микропроцессорных систем? 2. Память данных и память команд. 3. Отличие FLASH-памяти от EEPROM-памяти. 4. Особенности памяти EEPROM. 5. Отличие памяти EEPROM от EPROM. 6. Чтение из EEPROM-памяти данных. 7. Запись в EEPROM-память данных. 8. Регистры управления памяти EEPROM микроконтроллера PIC16F877A. 9. Настройка микроконтроллера для работы с памятью EEPROM. 10. Поясните схему для проверки работы памяти EEPROM, приведенную в данной лабораторной работе. 5.13.9. Практическая работа № 9. Генерация звука с помощью МК В лабораторной работе предлагается использовать микроконтроллер в качестве генератора низких частот. Звуковые сигналы часто используются, когда необходимо привлечь внимание пользователя, подтвердить нажатие кнопки, предупредить, что минимальные или максимальные значения достигаются и т. д. Это может быть просто звуковой сигнал, а может быть мелодия. В работе представлен пример, который демонстрирует генерацию звука с помощью встроенных функций программы mikroC. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 Кнопка Макетная плата x1 x1 x2 Дополнительный блок компонентов: Излучатель Конденсатор x1 x1 Кнопка Резистор 10 кОм Проводники x4 x4 x1 202
1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.71. При использовании пьезоизлучателя вместо динамика установка конденсатора не требуется. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял воспроизводить другую музыкальную мелодию. 2. Принципиальная схема Рис. 5.71 Генерация звука с помощью МК 3. Программный код __________________________________________________________________ void Tone1() { Sound_Play(659, 250); // Частота = 659 Hz, длительность = 250 мс } void Tone2() { Sound_Play(698, 250); // Частота = 698 Hz, длительность = 250 мс } void Tone3() { Sound_Play(784, 250); // Частота = 784 Hz, длительность = 250 мс } void Melody1() { Tone1(); Tone2(); Tone3(); Tone1(); // Мелодия 1 Tone3(); Tone2(); 203
Tone3(); Tone2(); Tone2(); Tone1(); Tone3(); Tone2(); Tone3(); Tone3(); Tone3(); Tone2(); Tone3(); Tone1(); Tone1(); Tone1(); Tone3(); Tone3(); Tone2(); } void ToneA() { Sound_Play(880, 50); } void ToneC() { Sound_Play(1046, 50); } void ToneE() { Sound_Play(1318, 50); } void Melody2() { unsigned short i; for (i = 9; i > 0; i--) { ToneA(); ToneC(); ToneE(); } } void main() { TRISB = 0xF0; // Тон A // Тон С // Тон E // Мелодия 2 // Входы RB7–RB4 настроены на вход, // RB3 на вывод Sound_Init( & PORTB, 3); Sound_Play(1000, 500); while (1) { if (Button( & PORTB, 7, Tone1(); while (PORTB & 0x80); if (Button( & PORTB, 6, Tone2(); while (PORTB & 0x40); if (Button( & PORTB, 5, Melody2(); while (PORTB & 0x20); if (Button( & PORTB, 4, Melody1(); while (PORTB & 0x10); } 1, 1)) // RB7 генерирует Тон 1 1, 1)) // RB6 генерирует Тон 2 1, 1)) // RB5 генерирует Мелодию 2 1, 1)) // RB4 генерирует Мелодию 1 // Ждем нажатия кнопки } __________________________________________________________________ 204
4. Вопросы для самоконтроля 1. Опишите процесс генерации звука с помощью микроконтроллера. 2. Схема для воспроизведения звука. 3. Программа для воспроизведения звука. 4. Библиотеки mikroC для генерации низкочастотных сигналов. 5. Приведите области применения исследуемой схемы. 5.13.10. Лабораторная работа № 10. Сопряжение МК с аналоговым датчиком В работе предлагается исследовать схему, позволяющую принимать сигнал от аналогового датчика и передавать полученные данные в память МК. В качестве датчика используется датчик для измерения температуры LM35. Измерение температуры является одной из распространенных задач, выполняемых микроконтроллером. Основной блок компонентов: МК PIC 16F877A Резистор 10 кОм x1 x1 Резонатор Конденсатор, кв., 20 МГц 20–30 пФ x1 x2 Кнопка Макетная плата x1 x1 Дополнительный блок компонентов: Светодиод x 10 Резистор Датчик темRS232–USB Потенциометр Проводники 220–330 Ом пературы x 10 x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, лабораторную станцию NI ELVIS, собрать схему, приведенную на рисунке 5.72. Записать в память микроконтроллера программу, приведенную в п. 3. Убедиться в работоспособности схемы. Дополнительное задание. Измените программу микроконтроллера так, чтобы алгоритм новой программы позволял принимать сигнал от аналогового датчика, оцифровывать его и передавать по двунаправленному последовательному порту RS232 на ПК (см. рис. 5.72). Для отображения полученных данных использовать программу USART test.exe. 205
2. Принципиальная схема Рис. 5.72 Сопряжение МК с аналоговым датчиком 3. Программный код __________________________________________________________________ unsigned int value; void main() { TRISA = 0xFF; TRISB = 0x3F; TRISD = 0; // Выводы AN2 и AN3 аналоговые // RB7 и RB6 настроены на вывод 206
ADCON1.F4 = 1; // Установить опорное напряжение с RA3 do { value PORTD PORTB } while // // // // = ADC_Read(2); = value; = value >> 2; (1); Результат преобразования в value 8 разрядов отображены в порт D 2 разряда в битах RB6 и RB7 порта B Бесконечный цикл } __________________________________________________________________ 4. Вопросы для самоконтроля 1. Опишите процесс обработки сигнала от датчика температуры с помощью микроконтроллера. 2. Схема для регистрации температуры датчика. 3. Схема передачи оцифрованных данных на ПК. 4. Программа для оцифровки и передачи данных на ПК. 5. Библиотеки mikroC для работы с АЦП и USART-модулями. 207
ГЛАВА 6 ПРОГРАММИРОВАНИЕ КОНТРОЛЛЕРОВ 6.1. Применение контроллеров Arduino 6.1.1. Применение контроллеров для разработки электроники Если сравнить, например, контроллер и микроконтроллер, то их принципиальное отличие заключается в использовании дополнительной аппаратной части. Ранее мы подробно рассмотрели применение микроконтроллеров PIC, которые выполнены в виде отдельной микросхемы, имеющей свои основные аппаратные узлы: процессорное ядро и память. Дополнительно микроконтроллер имеет периферийные устройства (порты ввода/вывода, таймеры, АЦП, UART и т. д.) и другие компоненты, необходимые для автономной работы. Создание контроллеров можно назвать логическим развитием микропроцессорной техники. По сравнению с микроконтроллерами, контроллеры выполнены на одной плате, могут содержать модули управления питанием схемы, дополнительные модули памяти и различные интерфейсы сопряжения с другими устройствами, например, FTDI-микросхему. Существуют и более сложные модули, которые могут содержать различные устройства для передачи данных по Wi-Fi или Bluetooth. Среди современных контроллеров можно выделить следующие серийно выпускаемые устройства: Arduino, Teensy, NodeMCU, Particle Photon, STM, Iskra JS. На рисунке 6.1 показаны некоторые из этих устройств. Teensy Particle Photon Рис. 6.1 Примеры современных контроллеров NodeMCU Современные контроллеры могут стать основой для большого количества проектов в области электроники, робототехники и IoT (Internet of Things, на рус. интернет вещей). Хотя все они могут быть использованы для цели управления внешними устройствами, они имеют существенные различия в архитектуре, возможностях и областях применения. Популярность использования контроллеров прежде всего обусловлена их относительной простотой, возможностью использования уже готовых программных решений, для реализации собственных программ, использования до208
ступного ПО для написания программ и большого сообщества в сети Интернет для обсуждения разных вопросов проектирования электронных схем с использованием данных устройств. Последующее изучение моделей контроллеров рекомендуется начинать с популярных моделей STM32 и ESP32. Именно эти решения являются хорошо востребованными среди разработчиков электронных схем. Безусловно, можно создать собственное решение, основой которого будет один из популярных микроконтроллеров. Далее мы обсудим архитектуру контроллера Arduino и рассмотрим некоторые примеры использования устройства, используя программное обеспечение Arduino IDE. 6.1.2. История создания контроллера Arduino В начале 2000-х гг. в итальянском городе Ивреа существовала экспериментальная школа дизайна Interaction Design Institute Ivrea (IDII), специалисты которой занимались вопросами создания дизайна интерактивных продуктов. Идея заключалась в том, что пользователю предлагается не просто решение или продукт, а то, как пользователь будет взаимодействовать с этим решением. Именно в стенах школы IDII преподаватели столкнулись с проблемой: студентам-дизайнерам без опыта в электронике было сложно создавать интерактивные прототипы, требующие использования микроконтроллеров. Существующие платформы были дорогими, сложными в использовании и требовали глубоких знаний в области программирования устройств. В 2005 г. команда преподавателей и студентов IDII начали работу над созданием более доступной и простой в использовании платформы, позволяющей быстро реализовать электронную схему. В качестве прототипа был использован физический вычислительный прототип Wiring. Система была сложной, но именно она послужила основой для создания первой модели устройства — Arduino v1.0. Первая версия Arduino использовала микроконтроллер фирмы Atmel AVR ATmega8. Разработчики смогли достигнуть главной цели проекта — получить программноаппаратную платформу, позволяющую быстро создавать устройства и программы для них. Отметим основные достоинства полученной системы. Платформа имеет открытый исходный код. Решение является open-source решением, что способствовало его популярности. Пользователь с любым уровнем знаний может скачать схемы, изучить код и создать свою собственную схему на основе скетчейшаблонов. Для написания программ используется Arduino IDE. Данная среда разработки (IDE) упростила написание и загрузку кода в память устройства. За основу языка программирования Arduino был выбран и использован высокоуровневый язык программирования C/C++, но с упрощенным синтаксисом и большим количеством готовых библиотек. Разнообразие существующей платформы. Arduino имеет множество различных плат (на сайте разработчика можно изучить все доступные устройства: https://www.arduino.cc/en/hardware), основанных на разных микроконтроллерах, способных выполнять задачи разного уровня сложности. Большое сообщество разработчиков. Благодаря простоте использования и открытому исходному коду, сформировалось огромное и активное сообщество 209
пользователей, которое делится опытом, знаниями и своими проектами на базе данной платформы. Особую популярность платформа имеет в образовательной сфере. Arduino быстро завоевал популярность в образовательных учреждениях по всему миру, став стандартом для обучения основам электроники, программирования и робототехники. Раньше платформу использовали в специальных учебных заведениях. На данный момент никого не удивляет тот факт, что конструктор на основе платы Arduino используют в средних школах. Nano Micro Mini Mega Leonardo Uno Due M0 LilyPad Рис. 6.2 Примеры контроллеров Arduino На рисунке 6.2 представлены основные платы Arduino. В качестве примера в следующих разделах мы подробно рассмотрим модель Uno. Рассмотрим основные характеристики данной модели, цифровые порты и аналоговые порты, периферийные интерфейсы подключения и другие особенности. На данный момент существует много реплик этого устройства. Например, самый популярный отечественный аналог называется Iskra Uno от компании «Амперка» (на сайте разработчика можно найти всю информацию об этом устройстве: https://amperka.ru). 210
6.1.3. Основные характеристики контроллера Arduino UNO Плата Arduino UNO R3 является отличным выбором, если вы только начинаете изучение подобных устройств. Она имеет достаточную функциональность и простоту в использовании. В качестве основного устройства вычислений используется микроконтроллер ATmega328P (8-битный) от компании Microchip (ранее Atmel). На рисунке 6.3 представлен контроллер Arduino UNO R3 и пины ввода/вывода. Аппаратные характеристики. Базовая тактовая частота составляет 16 МГц. Flash-память 32 Кб (0,5 Кб используются загрузчиком), SRAM 2 Кб. EEPROM 1 Кб. Входы/выходы (I/O). Цифровые пины ввода/вывода: 14 (из них 6 могут использоваться как выходы ШИМ). Выходы ШИМ (PWM): 6 (пины 3, 5, 6, 9, 10, 11). Рис. 6.3 Контроллер Arduino UNO R3 и пины ввода/вывода (ист.: https://content.arduino.cc/assets/A000066–pinout.png) Аналоговые входы: 6 (A0–A5). Разрешение: 10 бит (1024 уровня). Интерфейсы связи. UART (Serial): пины 0 (RX) и 1 (TX). SPI: используются пины 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). Для подключения модуля необходимо использовать специальную библиотеку SPI. I2C: используются пины A4 (SDA) и A5 (SCL) или пины SDA и SCL рядом с AREF. Для подключения модуля необходимо использовать специальную библиотеку Wire. Питание платы. Напряжение питания (рекомендуемое): 7–12 В. Напряжение питания (предельное): 6–20 В. Напряжение логического уровня: 5 В. Ток на пин I/O: 20–50 мА. Дополнительные аппаратные характеристики. Питание (Power). Контакты для подачи и заземления питания (VCC/Vin, GND). Arduino может питаться от USB, внешнего источника питания (напри211
мер, батареи или адаптера) через разъем DC Jack или через контакты Vin/GND. Также на плате обычно есть контакт 5V и 3.3V для питания внешних устройств. USB-интерфейс. Данный интерфейс используется для программирования платы и для обмена данными с компьютером. Разъем питания (DC Jack), который можно использовать для подключения внешнего источника питания. Кнопка Reset для перезагрузки микроконтроллера. Светодиоды на плате. Обычно на плате есть несколько светодиодов для индикации состояния, например, светодиод питания (Power) и светодиод, подключенный к одному из цифровых выходов (например, светодиод, подключенный к D13 на Arduino UNO). В зависимости от модели платы, могут быть дополнительные компоненты, такие как Wi-Fi модуль, Bluetooth-модуль, Ethernet-контроллер, SD-кардридер и т. д. Программные характеристики. Для программирования устройства используется специальная среда разработки Arduino IDE (Integrated Development Environment), которую можно скачать на сайте разработчика и установить на компьютер (https://www.arduino.cc/en/software). В качестве альтернативы можно воспользоваться облачным решением Arduino IDE online. Для создания программ используется язык программирования Arduino, который основан на высокоуровневом языке C/C++, но имеет более простой синтаксис. Arduino UNO R3 является универсальной платформой среди контроллеров Arduino. Платформа может быть использована в следующих областях. 1. Создание роботизированных систем. Возможность управления роботами, создание роботизированных манипуляторов. 2. Организация умного дома. Автоматизация освещения, отопления, вентиляции, управления шторами. 3. Интернет вещей (IoT). Подключение устройств к интернету, сбор и передача данных. 4. Подключение датчиков. Сбор данных с различных датчиков (температура, влажность, давление, освещенность и т. д.). 5. Автоматизация процессов. Автоматизация различных процессов, например, управление вентиляцией и температурой в помещении. 6. Изучение основ аналоговой и цифровой электроники. Обучение основам электроники, программирования и робототехники. 6.2. Создание программ в среде разработки Arduino IDE Для создания программ для контроллера Arduino используется специальное программное обеспечение, которое состоит из среды разработки Arduino IDE, используемого языка программирования, набора библиотек, компилятора и загрузчика. Актуальную версию программы можно скачать на сайте разработчика: https://www.arduino.cc/en/software. В данной среде программирования можно создавать новые программы, которые разработчики называют «скетч». По умолчанию в программе уже представлено большое количество скетчейшаблонов, на которых можно создать собственное решение. 212
Среда разработки Arduino IDE — это кросс-платформенная среда разработки, основанная на Processing IDE. Она имеет графический интерфейс для написания, компиляции и загрузки программ в память плат Arduino. При создании программ для платформы Arduino используют упрощенный язык C/C++. Arduino IDE предоставляет набор библиотек и функций, которые упрощают работу с аппаратной частью платы. Программа позволяет создавать решения для управления цифровыми и аналоговыми входами/выходами, для работы с последовательным портом и интерфейсами передачи данных SPI, I2C. Использование готовых библиотек. Библиотеки — это наборы функций, которые позволяют упростить процесс написания программ для работы с разными устройствами и протоколами. Библиотеки позволяют использовать в проекте различные датчики, дисплеи, модули связи и т. д. Компилятор программ. Arduino IDE использует компилятор avr-gcc для преобразования исходного кода скетча в машинный код, понятный микроконтроллеру. Загрузчик программ (Bootloader). Загрузчик — это небольшая программа, предварительно записанная в память микроконтроллера. Он позволяет загружать новые скетчи в память устройства через USB-интерфейс без использования внешнего программатора. 6.2.1. Среда разработки Arduino IDE Для создания скетчей для Arduino используется среда разработки Arduino IDE. На рисунке 6.4 показан внешний вид программы Arduino IDE версии 2.3.4. Условно главное окно программы можно разделить на несколько частей: 1 — меню навигации и элементы создания, редактирования и анализа программы; 2 — дополнительные элементы управления проектом; 3 — окно для вывода служебной информации и информации о статусе отладки и программирования устройства; 4 — панель для отладки программы и загрузки программы в память устройства, выбора типа устройства и использование плоттера и монитора последовательного порта; 5 — окно для создания и редактирования программы. Рис. 6.4 Внешний вид среды разработки Arduino IDE 213
Для создания новой программы в главном меню необходимо выбрать File → New Sketch. При первом знакомстве с программой рекомендуется использовать примеры готовых программ. Чтобы использовать готовый пример в главном меню, необходимо выбрать File → Examples. На рисунке 6.5 показан вариант выбора примера. Рис. 6.5 Выбор готовой программы в среде Arduino IDE Далее мы посмотрим, как осуществляется подключение Arduino UNO к компьютеру, как выполняется настройка соединения компьютера и устройства, проверим работу устройства на примере скетча Blink из готовых решений. 6.2.2. Подключение Arduino UNO и запуск IDE При подключении Arduino UNO к компьютеру используется USB-кабель (тип A–B). Если на компьютере установлена операционная система Linux или Mac OS, то, скорее всего, драйверы для устройства будут определены автоматически. В случае операционной системы Windows, возможно, драйверы нужно будет установить дополнительно. Обычно пакет установщика среды программирования уже их содержит. Предлагается использовать следующую последовательность действий для подключения устройства. 1. Подключите Arduino к компьютеру. Убедитесь, что система определила устройство. Для этого перейдите в управление компьютером, выберите диспетчер устройств, а потом выпадающий пункт Порты (COM и LPT). В выпадающем списке найти название порта, к которому подключилось устройство. В нашем случае устройство подключено к COM8 (см. рис. 6.6). Если все было выполнено правильно и устройство определено в системе, то при подключении кабеля к USB-порту компьютера на плате загорится красный светодиод, который свидетельствует о запуске устройства. На рисунке 6.7 показано подключенное к компьютеру устройство Arduino UNO R3. 214
Рис. 6.6 Определение номера порта подключенного устройства в диспетчере устройств Рис. 6.7 Arduino UNO R3 после подключения к компьютеру 2. На втором шаге необходимо открыть среду разработки Arduino IDE и указать в настройках версию используемого устройства. Укажем в настройках номер порта подключенного устройства. Переходим в главном меню Tools → Port → Serial ports и выбираем нужный порт. В нашем случае это COM8. На рисунке 6.8 показан выбор необходимого порта в программе. 3. На третьем шаге нужно выбрать модель устройства, которое подключено к компьютеру, и для которого мы будем создавать программы. Сделать 215
это можно несколькими способами. Можно указать модель в главном меню Tools → Board, а можно использовать менеджер устройств, который доступен в главном окне программы на панели отладки и загрузки программы. На рисунке 6.9 показан второй способ выбора модели. Рис. 6.8 Выбор порта в программе Arduino IDE Рис. 6.9 Выбор модели устройства в программе Arduino IDE Если программа определила устройство без ошибок, то можно переходить к созданию первой программы. В качестве примера будем использовать готовую программу для мигания светодиодом. 216
6.2.3. Анализ тестовой программы для мигания светодиода Используем программу для мигания светодиодом из набора готовых примеров среды разработки Arduino IDE. Чтобы использовать готовый пример, в главном меню необходимо выбрать File → Examples → 01. Basics → Blink. На рисунке 6.10 показана используемая программа, но с небольшими изменениями. Ниже представлен листинг данной программы. Рис. 6.10 Программа для мигания светодиодом Arduino IDE __________________________________________________________________ // Функция для настройки устройства void setup() { // Инициализация встроенного цифрового пина на вывод pinMode(LED_BUILTIN, OUTPUT); } // Основная функция программы для мигания светодиодом void loop() { digitalWrite(LED_BUILTIN, HIGH); // Светодиод включен, LED ON delay(1000); // Задержка 1000 мс digitalWrite(LED_BUILTIN, LOW); // Светодиод выключен, LED OFF delay(1000); // Задержка 1000 мс } __________________________________________________________________ 217
Данная программа позволяет включать/выключать встроенный светодиод на плате Arduino, реализовать мигание с частотой один раз в секунду (включен на одну секунду, выключен на одну секунду). Это простой пример, который часто используется как “Hello, World!” для Arduino, чтобы убедиться, что плата подключена без ошибок и может работать согласно заданному алгоритму программы. Программа состоит из двух основных функций: setup() и loop(). Первая функция выполняется только один раз, когда Arduino включается или перезагружается. В ней выполняется инициализация. Вторая функция выполняется непрерывно (по кругу) после завершения функции setup(). Здесь выполняется основная логика программы. Рассмотрим программу подробнее: 1. В 1, 3 и 7 строках приведены комментарии. Они не используются при выполнении основной программы и игнорируются. Здесь они приведены для пояснений. 2. В 4 строке используется функция pinMode(LED_BUILTIN, OUTPUT). Данная строка кода настраивает цифровой пин, к которому подключен встроенный светодиод (обычно пин 13 на Arduino UNO), как выходной. Это означает, что Arduino может управлять напряжением на этом пине. LED_BUILTIN — предопределенная константа в Arduino IDE, соответствующая номеру пина, к которому подключен встроенный светодиод. 3. В 9 строке функция digitalWrite(LED_BUILTIN, HIGH) устанавливает высокий уровень напряжения (обычно 5 В или 3,3 В, в зависимости от платы) на пине, к которому подключен светодиод. Это включает светодиод. Функция delay(1000) приостанавливает выполнение программы на 1000 мс (1 с). В течение этого времени светодиод остается включенным. 4. В 11 строке функция digitalWrite(LED_BUILTIN, LOW) устанавливает низкий уровень напряжения (0 В) на пине, к которому подключен светодиод. Это выключает светодиод. Функция delay(1000) снова приостанавливает выполнение программы на 1000 мс (1 с). В течение этого времени светодиод остается выключенным. После выполнения этих шагов функция loop() начинается заново, и светодиод снова включается, светит секунду, гаснет на секунду, и так далее бесконечно. В программе мы использовали предопределенную константу, которая настраивает пин с подключенным диодом. По умолчанию это 13 пин. Далее необходимо загрузить программу в память устройства. Для этого последовательно нажимаем кнопку Verify, а потом Upload. Если в программе нет ошибок и программа загружена, то на плате будет мигать зеленый светодиод. Для демонстрации можно использовать дополнительный светодиод, подключенный к пину 13. На рисунке 6.11 показано подключение внешнего светодиода к плате Arduino UNO. Не забываем, что для подключения светодиода потребуется резистор, который будет ограничивать ток, протекающий через него. Нам известно, что напряжение пина составляет 5 В, тогда можно использовать токоограничивающий резистор, номинал которого можно рассчитать по следующей формуле: R= U пит – U диода . I диода 218
Рис. 6.11 Подключение внешнего светодиода В нашем случае использован резистор 220 Ом. Далее будут подробно рассмотрены более сложные примеры использования цифровых и аналоговых портов контроллера, различные интерфейсы передачи информации. 6.2.4. Основы программирования C/C++ для Arduino В основе языка программирования для микроконтроллеров Arduino используется высокоуровневый язык программирования C/C++. Для глубокого изучения языка рекомендуется использовать специальную литературу по программированию. В данном разделе мы рассмотрим основные конструкции языка, которые позволят нам писать программы для контроллеров Arduino. В таблице ниже представлены основные типы данных, которые используются в программах. № Тип данных 1 int 2 unsigned int 3 long Описание типа данных Целые числа (обычно 16 бит на Arduino). Диапазон: –32768 to 32767. Используйте long для больших чисел Положительные целые числа (обычно 16 бит). Диапазон: 0 to 65535. Используйте unsigned long для больших положительных чисел Целые числа (обычно 32 бита). Диапазон: –2147483648 to 2147483647. Положительные целые числа (обычно 32 бита). Диапазон: 0 to 4294967295. Часто используется для хранения времени (например, millis() и micros()) 219
Продолжение табл. № Тип данных 4 unsigned long 5 byte 6 boolean (или bool) 7 char 8 float 9 String Описание типа данных Положительные целые числа (обычно 32 бита). Диапазон: 0 to 4294967295. Часто используется для хранения времени (например, millis() и micros()) Беззнаковое целое число (8 бит). Диапазон: 0 to 255. Эффективно для хранения информации о состоянии одного пина или маленьких чисел Логический тип данных. Может быть либо true (истина), либо false (ложь) Символ (8 бит). Используется для хранения одного символа (например, ‘A’, ‘5’, ’ ‘) Числа с плавающей запятой (32 бита). Используют для представления дробных чисел. Менее эффективно, чем int Строка (текст). В Arduino часто используется класс String, но рекомендуется избегать его использования из-за проблем с памятью. Используйте массивы символов (char[]) вместо этого для обработки строк 1. Переменные Переменная — это контейнер для хранения различных данных с определенными типами. В Arduino IDE для объявления переменной указывают тип данных и имя переменной. ___________________________________________________________________ int count; // Объявляем переменную "count" float temp = 25.5; // Объявляем переменную типа float boolean isRunning = true; // Объявляем логическую переменную ___________________________________________________________________ Инициализация переменной — это присваивание начального значения переменной при ее объявлении. Для присваивания значения переменной используется оператор «=». ___________________________________________________________________ count = 10; // Присваиваем значение 10 переменной "count" temp = temp + 1.0; // Увеличиваем значение переменной "temp" на 1.0 ___________________________________________________________________ Рассмотрим область видимости переменной. Переменные, объявленные внутри setup() или loop(), являются локальными и доступны только внутри этих функций. Переменные, объявленные вне setup() и loop() (глобальные), доступны во всей программе. 220
2. Операторы Для выполнения операций над переменными используются специальные операторы. Различают следующие группы операторов: арифметические операторы, операторы присваивания, операторы сравнения, логические операторы и операторы инкремента/декремента. В таблице ниже представлены основные операторы и пояснение к ним. № 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 6 1 2 3 1 2 Оператор Выполняемые операции Арифметические операторы + Сложение Вычитание * Умножение / Деление % Остаток от деления — полезен для циклических операций Операторы присваивания = Присваивание += Прибавить и присвоить -= Вычесть и присвоить *= Умножить и присвоить /= Разделить и присвоить Операторы сравнения == Равно != Не равно < Меньше > Больше <= Меньше или равно >= Больше или равно Логические операторы && (И — AND) Пример: true && true = true, все остальные комбинации false || (ИЛИ — OR) Пример: false || false = false, все остальные комбинации true ! (НЕ — NOT) Пример: !true = false, !false = true Операторы инкремента/декремента Инкремент — увеличить на 1 ++ count++ эквивалентно count = count + 1; или count += 1 Декремент — уменьшить на 1 – count– эквивалентно count = count – 1; или count -= 1 3. Управляющие структуры (Control Structures) Для обработки данных используются управляющие структуры. Далее будут приведены примеры использования таких структур. Среди структур можно выделить: условный оператор if ... else, цикл for, цикл while, цикл do ... while, оператор разветвленного выбора switch ... case. 221
Оператор if ... else позволяет выполнить часть программы по условию. ___________________________________________________________________ if (sensorValue > 500) { // Включить светодиод, если значение датчика больше 500 digitalWrite(LED_BUILTIN, HIGH); } else { // Выключить светодиод в противном случае digitalWrite(LED_BUILTIN, LOW); } ___________________________________________________________________ Цикл for позволяет повторять блок кода заданное количество раз. ___________________________________________________________________ // Цикл от 0 до 9 (10 итераций) for (int i = 0; i < 10; i++) { // Выводим текущее значение "i" в серийный порт Serial.println(i); } ___________________________________________________________________ Цикл while позволяет повторять блок кода, пока условие истинно. ___________________________________________________________________ int count = 0; while (count < 10) { // Повторять, пока count < 10 Serial.println(count); count++; } ___________________________________________________________________ Цикл do ... while позволяет выполнить часть программы хотя бы один раз, а затем повторяется, пока условие истинно. ___________________________________________________________________ int count = 0; do { Serial.println(count); count++; } while (count < 10); // Повторять, пока count < 10 ___________________________________________________________________ 222
Структура switch ... case позволяет реализовать многовариантное разветвление, альтернатива последовательной серии if ... else if ... else. ___________________________________________________________________ int state = 2; switch (state) { case 0: // Код для состояния (state) 0 break; case 1: // Код для состояния (state) 1 break; case 2: // Код для состояния (state) 2 break; default: // Код для обработки других состояний } ___________________________________________________________________ 4. Функции Функция — это часть программы, которая может быть использована несколько раз. При работе с функциями выделяют два этапа: объявление функции и ее вызов. Объявление функции определяет тип возвращаемого значения, имя функции и параметры. ___________________________________________________________________ // Функция, складывающая два целых числа int addNumbers(int a, int b) { int sum = a + b; return sum; // Возвращаем результат сложения } ___________________________________________________________________ Вызов функции позволяет использовать созданную функцию с определенными аргументами. ___________________________________________________________________ // Вызываем функцию "addNumbers" с аргументами 5 и 3 int result = addNumbers(5, 3); // Выводим значение переменной "result" Serial.println(result); ___________________________________________________________________ Очень часто в программах используется тип возвращаемого значения void, означающий, что функция ничего не возвращает. 223
5. Массивы Массивы используются для хранения нескольких значений одного типа данных под одним именем. Доступ к элементам массива осуществляется по индексу (начиная с 0). ___________________________________________________________________ int myArray[5]; myArray[0] = 10; myArray[1] = 20; // Объявляем целочисленный массив из 5 элементов // Присваиваем значение 10 первому элементу // Присваиваем значение 20 второму элементу // Инициализация массива при объявлении int anotherArray[] = {1, 2, 3, 4, 5}; ___________________________________________________________________ 6. Строки (Strings) Использование char[] (массив символов) является более предпочтительным способом работы со строками в Arduino (вместо String-класса). Данный подход можно назвать более эффективным, позволяющим предотвратить проблемы с памятью. ___________________________________________________________________ // Объявляем строку "Hello" (заканчивается нулевым символом '\0') char myString[] = "Hello"; // Объявляем строку, в которой можно хранить до 9 символов + '\0' char anotherString[10]; // Копируем строку "World" в anotherString strcpy(anotherString, "World"); ___________________________________________________________________ Основные функции для работы с char[] (нужно подключить #include <string.h>). ___________________________________________________________________ // Копирует строку source в destination strcpy(destination, source) // Добавляет строку source в конец строки destination strcat(destination, source) // Возвращает длину строки (количество символов до нулевого символа) strlen(string) 224
// Сравнивает две строки, возвращает 0, если строки равны strcmp(string1, string2) // Находит первое вхождение подстроки needle в строке haystack strstr(haystack, needle) ___________________________________________________________________ 7. Препроцессор (Preprocessor) Препроцессор #define создает макросы, заменяет идентификаторы (имена) на значения во время компиляции. Полезно для определения констант и упрощения кода. ___________________________________________________________________ #define LED_PIN 13 // Определяем LED_PIN как пин 13 #define PI 3.14159 // Определяем PI как число 3.14159 ___________________________________________________________________ Зарезервированное слово #include вставляет содержимое указанного файла в код. Используется для подключения библиотек. ___________________________________________________________________ #include <SPI.h> // Подключаем библиотеку SPI #include <Wire.h> // Подключаем библиотеку Wire ___________________________________________________________________ 8. Комментарии Однострочный комментарий. Все, что следует после // до конца строки, игнорируется компилятором. Многострочный комментарий. Все, что находится между /* ... */, игнорируется компилятором. 6.3. Особенности архитектуры контроллера Arduino 6.3.1. Цифровые порты и широтно-импульсная модуляция Arduino UNO Цифровые входы/выходы (на англ. Digital I/O). Могут быть настроены как входы для чтения высокого или низкого логического уровня (5В/0В) или как выходы для установки высокого или низкого логического уровня. Часто имеют встроенные подтягивающие резисторы (pull-up resistors), которые можно подключить, используя программные средства. Обозначаются номерами (например, D0, D1, D2 и др.). На рисунке 6.3 входы/выходы обозначены оранжевым цветом. Рассмотрим несколько типичных схем для исследования работы цифровых портов ввода/вывода Arduino. На рисунке 6.12 показана схема для тестирования программы. 225
Рис. 6.12 Схема подключения светодиода 1. Скетч для изменения яркости светодиода с использованием цикла. __________________________________________________________________ // Контакт 4 для подключения светодиода const int LED = 4; void setup() { // Инициализация цифрового пина с номером 4 pinMode(LED, OUTPUT); } void loop() { // Выполнение цикла for for (int i = 100; i <= 1000; i = i + 100) { digitalWrite(LED, HIGH); Светодиод включен, LED ON delay(i); digitalWrite(LED, LOW); Светодиод выключен, LED OFF delay(i); } } __________________________________________________________________ Программа на начальном этапе программирует пин 4 на выход. Затем в функции loop() с помощью цикла for программа перебирает значения i от 100 до 1000 с шагом 100. Для каждого значения i выполняется включение светодиода, затем пауза в i миллисекунд, далее выполняется выключение светодиода и снова пауза в i миллисекунд. Таким образом, светодиод мигает с задержкой, которая увеличивается от 100 мс до 1000 мс, а затем цикл повторяется. В процессе работы устройства будет видно, как светодиод сначала мигает быстро, затем медленнее. 226
Важной функцией цифровых портов является возможность считывания данных. Подобная особенность позволяет создавать схемы, например, с использованием кнопок. На рисунке 6.13 показана схема подключения кнопки. Рис. 6.13 Схема подключения светодиода и кнопки 2. Скетч для считывания данных с цифрового порта и использование кнопки. __________________________________________________________________ // Контакт 8 для подключения светодиода const int LED = 8; // Контакт 2 для подключения кнопки const int BUTTON = 2; void setup() { // Сконфигурировать контакт светодиода как выход pinMode(LED, OUTPUT); // Сконфигурировать контакт кнопки как вход pinMode(BUTTON, INPUT); } void loop() { if (digitalRead(BUTTON) == LOW) { digitalWrite(LED, HIGH); // Если кнопка нажата (LOW), LED ON } else { digitalWrite(LED, LOW); // Если кнопка не нажата (HIGH), LED OFF } } __________________________________________________________________ 227
Программа управляет светодиодом, подключенным к пину 4, с помощью кнопки, подключенной к пину 2. Когда кнопка нажата, пин 2 замыкается на землю. В этот момент пин 4 получает высокий уровень напряжения (5 В), светодиод загорается. Если кнопка не нажата, тогда пин 4 получает низкий уровень напряжения (0 В), светодиод гаснет. Программа постоянно проверяет состояние кнопки. Во избежание короткого замыкания кнопку необходимо подключать через резистор 10 кОм. Номинал резистора для светодиода 220 Ом. Широтно-импульсная модуляция (на англ. Pulse Width Modulation, PWM). Некоторые цифровые выходы имеют возможность генерации PWM сигнала. Это позволяет имитировать аналоговые напряжения, быстро переключая выход между высоким (HIGH) и низким (LOW) уровнем с разной скважностью. Используется для управления яркостью светодиодов, скоростью двигателей и т. п. Обычно обозначаются символом «~» рядом с номером (например, ~3, ~5, ~6). На рисунке 6.3 входы/выходы обозначены оранжевым цветом. На рисунке 6.14 показана схема для тестирования программы. Рис. 6.14 Схема для тестирования ШИМ-модуля Arduino UNO 3. Скетч для реализации широтно-импульсной модуляции. __________________________________________________________________ // Пин для ШИМ-сигнала (только определенные выходы) const int pwmPin = 9; void setup() { // Настройка пина PWM как выхода (выполняется автоматически) // pinMode(pwmPin, OUTPUT); } 228
void loop() { // Увеличиваем яркость светодиода (коэф. ШИМ от 0 до 255) for (int i = 0; i <= 255; i++) { analogWrite(pwmPin, i); // Записываем значение ШИМ delay(5); } // Уменьшаем яркость светодиода (коэф. ШИМ от 255 до 0) for (int i = 255; i >= 0; i--) { analogWrite(pwmPin, i); // Записываем значение ШИМ delay(5); } } __________________________________________________________________ Программа генерирует ШИМ-сигнал на пине 9. Функция analogWrite() изменяет коэффициент заполнения этого сигнала. Когда коэффициент заполнения увеличивается (от 0 до 255), то светодиод светит ярче. Когда коэффициент заполнения уменьшается (от 255 до 0), то светодиод светит тусклее. Светодиод будет плавно увеличивать яркость, а затем плавно уменьшать ее, повторяя этот процесс бесконечно. 6.3.2. Аналоговые порты и подключение датчиков Arduino UNO имеет 6 аналоговых входов (портов), обозначенных как A0, A1, A2, A3, A4, A5. Рассмотрим основные характеристики аналоговых портов. Аналоговые порты используются для измерения аналогового напряжения. Устройство имеет встроенный аналого-цифровой преобразователь (АЦП), который преобразует аналоговое напряжение в цифровое значение. Модуль АЦП имеет разрешение 10 бит. Это означает, что аналоговый вход может различать 210 = 1024 уровня напряжения. На вход порта можно подавать напряжение в диапазоне от 0 В до 5 В, что соответствует дискретным значениям от 0 до 1023. Входное сопротивление очень высокое и может достигать величины 100 мОм. Arduino UNO. Аналоговые порты могут быть подключены к внешним аналоговым датчикам, потенциометрам, фоторезисторам и другим аналоговым устройствам. Отметим некоторые особенности использования модуля. Аналоговые входы можно также использовать как цифровые порты ввода/вывода. Однако в большинстве случаев для цифровых операций лучше использовать предназначенные для этого цифровые порты. Опорное напряжение AREF можно изменять. Внешнее опорное напряжение используется для повышения точности измерений. Для этого необходимо настроить вывод AREF и использовать в программе функцию analogReference(). Для демонстрации работы модуля АЦП мы рассмотрим схему, в которой используется потенциометр. На рисунке 6.15 представлена схема с подключенным потенциометром. 229
Рис. 6.15 Схема подключения потенциометра к Arduino UNO 1. Скетч для измерения напряжения потенциометра. ___________________________________________________________________ void setup() { // Инициализируем последовательный интерфейс Serial.begin(9600); } void loop() { // Читаем значение напряжения на входе A0 int sensorValue = analogRead(A0); // Преобразуем значение в вольты float voltage = sensorValue * (5,0 / 1023,0); Serial.print("Цифровое значение: "); Serial.println(sensorValue); // Выводим цифровое значение Serial.print("Напряжение: "); Serial.println(voltage); // Выводим напряжение delay(100); // Задержка 100 мс } ___________________________________________________________________ В программе представлены две новые функции, с которыми мы пока незнакомы. Serial.begin() — это функция, которая инициализирует последовательный порт. Она позволяет плате общаться с компьютером или другими устройствами через последовательное соединение. Значение в круглых скобках определяет скорость передачи данных. Serial.print() — это функция, используемая для отправки данных (текста, чисел, переменных) на последовательный порт. Для анализа работы схемы потребуется использование последовательного монитора для отображения результатов. В главном меню необходимо выбрать 230
Tools → Serial Monitor. Далее необходимо загрузить программу в память устройства. Для этого последовательно нажимаем кнопку Verify, а потом Upload. Если в программе нет ошибок и программа загружена, то в Serial Monitor будет выведено цифровое значение и значение напряжения. На рисунке 6.16 показана программа для чтения данных АЦП по последовательному порту. Рис. 6.16 Программа для чтения данных АЦП по последовательному интерфейсу Для вывода результатов чтения аналогового сигнала на экран можно использовать Serial Plotter. В главном меню необходимо выбрать Tools → Serial Plotter. При отправке данных в последовательный порт нужно оставить только числовые значения, иначе данные выводиться не будут. На рисунке 6.17 представлен график изменения напряжения во времени. Для сглаживания графика можно использовать специальный режим. Активировать данный режим можно с помощью переключателя Interpolate. Не забываем, что скорости передачи данных в программе и в Serial Plotter должны совпадать. В нашем случае установлена скорость 9600 бод. Бод (baud) — это единица измерения скорости передачи данных, которая показывает количество изменений сигнала в секунду. В простейшем случае (в случае UART) каждый символ (элемент сигнала) представляет собой один бит данных. 231
Рис. 6.17 График изменения напряжения от времени в Serial Plotter Поэтому в большинстве случаев, когда говорят про UART и 9600 бод, подразумевают, что передается 9600 бит в секунду (bps). На практике это может не соответствовать действительности. В более сложных схемах один символ может представлять несколько бит. Но для простых UART-соединений, используемых с Arduino, можно считать, что бод равен битам в секунду. Если у вас установлена скорость 9600 бод для UART, вы можете передавать 9600 бит данных каждую секунду. Чтобы передать один символ (например, букву A), требуется обычно 8 бит данных (хотя иногда используются 7 или 9 бит). Также добавляются стартовый и стоповый биты. Тогда для передачи одного символа требуется обычно 10 бит. Это означает, что при скорости передачи данных 9600 бод/с вы можете передать примерно 9600/10 = = 960 символов в секунду. 6.3.3. Использование элементов мехатроники В данном разделе мы изучим схему, которая позволяет создать на основе управляющей электроники и DC-мотора устройство мехатроники. Для этого будет использована плата Arduino, потенциометр, полевой транзистор и мотор. На рисунке 6.18 приведена принципиальная схема предлагаемого устройства. При организации схемы питание аналоговой части и мотора следует разделить. Общее питание схемы составляет 5 В, питание мотора осуществляется от пин Vin контроллера. Для управления скоростью вращения используется N-канальный полевой транзистор. 232
Рис. 6.18 Схема подключения DC-мотора к Arduino UNO 1. Скетч для управления скоростью вращения DC-мотора. __________________________________________________________________ // Пины Arduino const int motorPin = 9; const int potPin = A0; // Пин ШИМ для управления скоростью // Пин для подключения потенциометра // Переменные int potValue = 0; int motorSpeed = 0; // Значение, считанное с потенциометра // Скорость мотора (от 0 до 255) void setup() { // Настройка пинов на вывод pinMode(motorPin, OUTPUT); pinMode(enablePin, OUTPUT); // Инициализируем Serial Monitor для отладки Serial.begin(9600); } void loop() { // Чтение значения с потенциометра potValue = analogRead(potPin); // Перевод значения потенциометра (0–1023) в значение ШИМ (0–255) motorSpeed = map(potValue, 0, 1023, 0, 255); 233
// Установка скорости мотора с помощью ШИМ analogWrite(motorPin, motorSpeed); // Вывод значений в Serial Monitor для отладки Serial.print("Потенциометр: "); Serial.println(potValue); Serial.print("Скорость мотора: "); Serial.println(motorSpeed); delay(10); // Задержка 10 мс } __________________________________________________________________ Программа предназначена для управления скоростью вращения DCмотора с помощью потенциометра. Она считывает значение с потенциометра, преобразует его в диапазон значений, подходящих для ШИМ (широтноимпульсной модуляции), и использует этот ШИМ-сигнал для управления полевым транзистором, который позволяет регулировать скорость мотора. Информация о значениях потенциометра и скорости мотора выводится в монитор последовательного порта для отладки. 6.3.4. Последовательная асимметричная шина I2C Шина I2C (Inter-Integrated Circuit) — это последовательный протокол передачи данных, который используется для связи между микроконтроллером и различными периферийными устройствами (датчики, память, дисплеи и т. д.). По протоколу I2C несколько зависимых устройств могут совместно использовать одну шину, под управлением главного устройства. Плата Arduino может быть использована главным или зависимым устройством. Начало обмена данными всегда начинается главным устройством. Зависимые устройства не могут самостоятельно начинать передачу данных, они лишь отвечают на запросы, поступающие от главного устройства. К одной шине можно подключить много зависимых устройств, но только мастер устанавливает соединение. Все команды и запросы, транслируемые главным устройством, принимаются всеми зависимыми устройствами, которые подключены к шине. Каждое ведомое устройство идентифицируется уникальным 7-битным адресом (ID). При старте обмена данными главное устройство передает идентификатор ведомого устройства. Ведомые устройства обрабатывают только те данные, которые адресованы исключительно им. Уникальность адреса каждого устройства на шине I2C является обязательным условием. Некоторые устройства позволяют настраивать адреса, в то время как другие имеют фиксированный адрес, установленный производителем. При подключении нескольких I2C устройств к одной шине необходимо убедиться в различии их идентификаторов. На рисунке 6.19 представлена схема подключения устройств к шине I2C. 234
Рис. 6.19 Схема подключения устройств к шине I2C В Arduino UNO для организации связи по шине I2C можно использовать пины A4 (SDA) и A5 (SCL). SDA используется для передачи данных, а SCL для синхронизации сигнала. При использовании пина A4 и A5 следует помнить, что данные выводы мультиплексированы с аналоговыми входами. По этой причине для работы с модулем лучше использовать специальную библиотеку Wire, которая автоматически выполнит все необходимые преобразования для правильной настройки пинов. Рассмотрим схему взаимодействия двух устройств по шине I2C. Главным устройством будем использовать Arduino UNO, зависимым устройством будем использовать аналогичное устройство. На рисунке 6.20 показана схема сопряжения этих устройств. Устройства выполняют следующие функции. Главное устройство генерирует последовательно с задержкой числа от 1 до 3 и передает их ведомому устройству. В зависимости от полученного номера ведомое устройство зажигает 1, 2 или 3 светодиод. Схема подключения устройств. Arduino 1 (Main) SDA (пин A4) подключаем к Arduino 2 (Replica) SDA (пин A4). Arduino 1 (Main) SCL (пин A5) подключаем к Arduino 2 (Replica) SCL (пин A5). Arduino 1 (Main) GND подключаем к Arduino 2 (Replica) GND. Светодиоды Arduino 2 подключены к пин 2, 3 и 4. 1. Скетч для сопряжения двух устройств по шине I2C (для Main). __________________________________________________________________ #include <Wire.h> #define REPLICA_ADDRESS 9 // Адрес зависимого устройства int dataToSend = 1; // Изначальное значение 235
void setup() { Wire.begin(); Serial.begin(9600); } // Инициализация I2C как главного void loop() { // Отправляем данные ведомому Wire.beginTransmission(REPLICA_ADDRESS); // Начинаем передачу Wire.write(dataToSend); // Отправляем данные Wire.endTransmission(); // Заканчиваем передачу Serial.print("Отправлено: "); Serial.println(dataToSend); // Меняем значение для следующей итерации dataToSend++; if (dataToSend > 3) { dataToSend = 1; } delay(1000); // Задержка 1000 мс } __________________________________________________________________ Рис. 6.20 Схема сопряжения двух устройств по шине I2C 2. Скетч для сопряжения двух устройств по шине I2C (для Replica). ___________________________________________________________________ #include <Wire.h> #define #define #define #define REPLICA_ADDRESS 9 LED1 2 // Пин для LED2 3 // Пин для LED3 4 // Пин для // Адрес зависимого устройства светодиода 1 светодиода 2 светодиода 3 236
int receivedData = 0; // Переменная для хранения полученных данных void setup() { Wire.begin(REPLICA_ADDRESS); // Инициализация I2C как зависимого Wire.onReceive(receiveEvent); // Функция, вызываемая при получении данных pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); Serial.begin(9600); } void loop() { // Основной цикл ничего не делает, все происходит в receiveEvent } // Функция, вызываемая при получении данных по I2C void receiveEvent(int howMany) { if (Wire.available() > 0) { receivedData = Wire.read(); // Читаем полученные данные Serial.print("Получено: "); Serial.println(receivedData); // Выключаем все светодиоды digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); digitalWrite(LED3, LOW); // Зажигаем соответствующий светодиод switch (receivedData) { case 1: digitalWrite(LED1, HIGH); break; case 2: digitalWrite(LED2, HIGH); break; case 3: digitalWrite(LED3, HIGH); break; default: // Обработка некорректного значения Serial.println("Некорректное значение!"); break; } } } ___________________________________________________________________ 237
Особенность использования протокола I2C заключается в том, что к контроллеру можно подключать цифровые устройства. Например, датчик температуры TC74. В этом случае нет необходимости предварительной подготовки и преобразования аналогового сигнала. Все предварительные измерения и преобразования выполнит зависимое устройство. 6.3.5. Последовательная синхронная шина SPI SPI (Serial Peripheral Interface) — это синхронный последовательный интерфейс для обмена данными, используемый для связи между микроконтроллером и периферийными устройствами. Он обеспечивает полнодуплексную связь (данные могут передаваться и приниматься одновременно) и обычно работает на более высоких скоростях, чем интерфейс I2C. SPI всегда имеет одно главное устройство (обычно микроконтроллер) и одно или несколько зависимых устройств (периферийные устройства). Ведущий управляет обменом данными. В подобной системе обмена информацией присутствует четыре основных линии связи. SDI (Serial Data In) — последовательный ввод данных, входной сигнал на устройстве, на который данные поступают с другого устройства. SDO (Serial Data Out) — последовательный вывод данных, выходной сигнал устройства, данные которого передаются на другое устройство. SCK (Serial Clock) — последовательный тактовый сигнал. Генерируется главным устройством и синхронизирует передачу данных. CS (Chip Select) — линия выбора зависимого устройства. Ведущий использует эту линию, чтобы активировать конкретное ведомое устройство для связи. В отличие от I2C, протокол SPI является полностью дуплексным и не требует использования подтягивающих резисторов. Для интеграции SPI-устройства с платой Arduino необходимо подключить его к выводам SDI, SDO, SCK и CS. Для более эффективной работы рекомендуется использовать специальную SPIбиблиотеку для Arduino. Стоит учитывать, что интерфейс SPI не является строго стандартизированным, поэтому названия линий связи могут отличаться у разных производителей SPI-компонентов. Передача данных в SPI осуществляется синхронно с тактовым сигналом и управляется состоянием линии CS. Все команды, передаваемые главным устройством, поступают на входы SDI, SDO и SCK всех подчиненных устройств. Состояние вывода CS указывает устройству, следует ли игнорировать или принимать эти данные. Важно помнить, что при передаче данных только одна линия CS должна быть в активном состоянии. На рисунке 6.21 представлена схема подключения устройств к шине SPI. В Arduino UNO для организации связи по шине SPI можно использовать пины 13 (SCK), 12 (SDO), 11 (SDI). Пин 10 будем использовать как CS для одного устройства, а пин 9 как CS для другого устройства. Рассмотрим схему взаимодействия двух устройств по шине SPI. Главным устройством будем использовать Arduino UNO, зависимым устройством будем использовать аналогичное устройство. На рисунке 6.22 показана схема сопряжения этих устройств. Устройства выполняют следующие функции. Главное устройство генерирует последовательно с задержкой числа от 1 до 3 и передает их ведомому устрой238
ству. В зависимости от полученного номера ведомое устройство зажигает 1, 2 или 3 светодиод. Рис. 6.21 Схема подключения устройств к шине SPI Рис. 6.22 Схема сопряжения двух устройств по шине I2C Схема подключения устройств. Arduino 1 (Main) SDI (пин 11) подключаем к Arduino 2 (Replica) SDI (пин 11). Arduino 1 (Main) SDO (пин 12) подключаем к Arduino 2 (Replica) SDO (пин 12). Arduino 1 (Main) SCK (пин 13) подключаем к Arduino 2 (Replica) SCK (пин 13). Arduino 1 (Main) CS (пин 10) подключаем к Arduino 2 (Replica) CS (пин 10) (ВАЖНО!). Arduino 1 (Main) GND подключаем к Arduino 2 (Replica) GND. 239
1. Скетч для сопряжения двух устройств по шине SPI (для Main). ___________________________________________________________________ #include <SPI.h> #define CS_PIN 10 // Адрес зависимого устройства int dataToSend = 1; // Начальные данные void setup() { Serial.begin(9600); pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV8); // Установка тактовой частоты SPI.setDataMode(SPI_MODE0); // Установка режима SPI SPI.setBitOrder(MSBFIRST); // Установка порядка битов } void loop() { digitalWrite(CS_PIN, LOW); SPI.transfer(dataToSend); digitalWrite(CS_PIN, HIGH); / Выбор зависимого устройства // Отправка данных // Отмена выбранного устройства Serial.print("Sent: "); Serial.println(dataToSend); dataToSend++; if (dataToSend > 3) { dataToSend = 1; } delay(1000); } ___________________________________________________________________ 2. Скетч для сопряжения двух устройств по шине SPI (для Replica). ___________________________________________________________________ #include <SPI.h> #define #define #define #define CS_PIN 10 // Адрес зависимого устройства LED1 2 // Пин для светодиода 1 LED2 3 // Пин для светодиода 2 LED3 4 // Пин для светодиода 3 volatile byte receivedData; bool dataReceived = false; 240
void setup() { Serial.begin(9600); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(CS_PIN, INPUT_PULLUP); // Установить CS как INPUT_PULLUP // Настройка SPI SPCR |= _BV(SPE); // Настройка SPI в режиме зависимого устройства // Разрешить прерывания в режиме SPI SPCR |= _BV(SPIE); // Очистка используемых пинов для светодиодов digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); digitalWrite(LED3, LOW); } ISR(SPI_STC_vect) { // Режим прерывания SPI receivedData = SPDR; dataReceived = true; } // Извлекаем байт из регистра данных SPI // Флаг передачи данных void loop() { if (dataReceived) { Serial.print("Полученные данные: "); Serial.println(receivedData); // Выключить все светодиоды digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); digitalWrite(LED3, LOW); // Включить светодиоды, в зависимости от принятого числа switch (receivedData) { case 1: digitalWrite(LED1, HIGH); break; case 2: digitalWrite(LED2, HIGH); break; case 3: digitalWrite(LED3, HIGH); break; default: Serial.println("Некорректное значение!"); break; } dataReceived = false; // Сброс флага передачи данных 241
} } ___________________________________________________________________ Интерфейс SPI можно использовать для многих других видов устройств: акселерометры, цифровые потенциометры, дисплеи. Правда, можно использовать и ранее рассмотренный протокол I2C. Отметим основные преимущества двух способов передачи данных. SPI имеет высокую скорость передачи данных, в системе меньше устройств, больше проводов, менее надежно, простота реализации. I2C имеет меньшую скорость, чем у SPI, в системе может быть больше устройств, меньше проводов, более надежно, сложнее реализация. 6.3.6. Справочник основных функций для Arduino В справочнике представлены основные функции, которые чаще всего используются при программировании Arduino. Он разделен по категориям. Для каждой категории представлен пример использования. 1. Основная структура программы в Arduino IDE Функция setup(). Выполняется один раз при запуске Arduino. Используется для инициализации пинов, подключения библиотек, настройки последовательного порта и т. д. ___________________________________________________________________ void loop() { // Здесь пишем код основной программы } ___________________________________________________________________ Функция loop(). Выполняется непрерывно после выполнения setup(). Содержит основной код программы, который управляет аппаратными блоками Arduino. ___________________________________________________________________ void loop() { // Здесь пишем код основной программы } ___________________________________________________________________ 2. Цифровые Входы/Выходы (Digital I/O) Функция pinMode(pin, mode). Настраивает пин на вход/выход. Номер пина (pin) на стандартных платах 0–13. Число пинов определяется конфигурацией контроллера. Режим работы порта mode: INPUT, OUTPUT, INPUT_PULLUP (вход с подтягивающим резистором к VCC). 242
___________________________________________________________________ pinMode(LED_BUILTIN, OUTPUT); // Встроенный светодиод как выход pinMode(2, INPUT); // Пин 2 как вход pinMode(3, INPUT_PULLUP); // Пин 3 как вход с PULLUP ___________________________________________________________________ Функция digitalWrite(pin, value). Записывает цифровое значение (HIGH или LOW) на выходной пин. Номер пина pin. Значение value: HIGH (5В) или LOW (0В). ___________________________________________________________________ digitalWrite(LED_BUILTIN, HIGH); // Включаем светодиод digitalWrite(LED_BUILTIN, LOW); // Выключаем светодиод ___________________________________________________________________ Функция digitalRead(pin). Считывает цифровое значение с входного пина. Номер пина pin. Возвращает значение HIGH или LOW. ___________________________________________________________________ int sensorValue = digitalRead(2); // Читаем значение с пина 2 if (sensorValue == HIGH) { // Что-то делаем } ___________________________________________________________________ ___________________________________________________________________ int sensorValue = digitalRead(2); // Читаем значение с пина 2 if (sensorValue == HIGH) { // Что-то делаем } ___________________________________________________________________ 3. Цифровые Входы/Выходы (Digital I/O). Функция analogRead(pin). Считывает аналоговое значение с аналогового пина. Номер аналогового пина (pin) на стандартных платах (A0–A5). Возвращает значение от 0 до 1023 (10-битное разрешение). ___________________________________________________________________ int sensorValue = analogRead(A0); // Читаем с пина A0 float voltage = sensorValue * (5.0 / 1023.0); // Преобразуем в вольты ___________________________________________________________________ Функция analogWrite(pin, value). Записывает псевдоаналоговое значение (ШИМ — широтно-импульсная модуляция) на пин, поддерживающий ШИМ. Номер пина (pin), поддерживающего ШИМ (обычно помечены знаком ~). Значение value изменяется в диапазоне от 0 до 255 (8-битное разрешение). 243
___________________________________________________________________ analogWrite(9, 128); // Установка яркости светодиода на пине 9 — 50% ___________________________________________________________________ 4. Время (Time) Функция delay(milliseconds). Приостанавливает выполнение программы на указанное количество миллисекунд. Параметр milliseconds определяет количество миллисекунд. ___________________________________________________________________ delay(1000); // Пауза на 1 с ___________________________________________________________________ Функция millis(). Возвращает количество миллисекунд, прошедших с момента запуска программы. Возвращает unsigned long. ___________________________________________________________________ unsigned long currentTime = millis(); ___________________________________________________________________ Функция micros(). Возвращает количество микросекунд, прошедших с момента запуска программы. Возвращает unsigned long. ___________________________________________________________________ unsigned long currentTime = micros(); ___________________________________________________________________ Функция delayMicroseconds(microseconds). Приостанавливает выполнение программы на указанное количество микросекунд. Менее точная, чем delay(), но полезна для коротких задержек. Параметр microseconds определяет количество микросекунд. ___________________________________________________________________ delayMicroseconds(500); // Пауза на 500 мкс ___________________________________________________________________ 5. Серийный порт (Serial Communication) Функция Serial.begin(baudRate). Инициализирует последовательный порт с указанной скоростью передачи данных (бод). Параметр baudRate определяет скорость передачи данных (обычно 9600, 115200 и т. д.). 244
___________________________________________________________________ delayMicroseconds(500); // Пауза на 500 мкс Serial.begin(9600); // Инициализация порта со скоростью 9600 бод ___________________________________________________________________ Функция Serial.print(data). Отправляет данные в последовательный порт. Параметр data определяет данные для отправки (число, строка, переменная и т. д.). ___________________________________________________________________ Serial.print("Значение датчика: "); Serial.print(sensorValue); ___________________________________________________________________ Функция Serial.println(data). Отправляет данные в последовательный порт, добавляя символ новой строки (\r\n). Параметр data определяет данные для отправки. ___________________________________________________________________ Serial.println("Это сообщение будет на новой строке"); ___________________________________________________________________ Функция Serial.available(). Возвращает количество байтов данных (int), доступных для чтения из буфера последовательного порта. ___________________________________________________________________ if (Serial.available() > 0) { // Есть данные для чтения } ___________________________________________________________________ Функция Serial.read(). Читает один байт данных из буфера последовательного порта. Возвращает значение int (значение байта –1, если нет доступных данных). ___________________________________________________________________ int incomingByte = Serial.read(); if (incomingByte != –1) { // Обрабатываем полученный байт } ___________________________________________________________________ 6. Математические функции Функция abs(x). Возвращает абсолютное значение числа x. 245
Функция constrain(x, a, b). Ограничивает значение x диапазоном от a до b. Если x меньше a, возвращает a. Если x больше b, возвращает b. Иначе возвращает x. Функция map(value, fromLow, fromHigh, toLow, toHigh). Преобразует значение из одного диапазона в другой. Функция pow(base, exponent). Возвращает base в степени exponent. Функция sqrt(x). Возвращает квадратный корень из x. Функция random(min, max). Генерирует псевдослучайное число в диапазоне от min (включительно) до max (не включительно). Перед использованием рекомендуется вызвать randomSeed() для инициализации генератора. Функция randomSeed(seed). Инициализирует генератор псевдослучайных чисел. Используйте аналоговый вход без подключения, чтобы получить действительно случайное число для инициализации. Дополнительные функции Функция tone(pin, frequency). Воспроизводит звук указанной частоты на указанном пине. Функция tone(pin, frequency, duration). Воспроизводит звук указанной частоты на указанном пине в течение указанной продолжительности (в миллисекундах). Функция noTone(pin). Останавливает воспроизведение звука на указанном пине. 6.4. Практические работы Практическая работа № 1. Подключение светодиода В данной работе предлагается изучить принцип подключения светодиодов к контроллеру Arduino UNO. Для сборки схемы потребуются следующие компоненты (и их количество). Все компоненты разбиты на два блока. Первый блок имеет набор стандартных элементов, которые содержат контроллер Arduino UNO и макетную плату. При подключении контроллера к компьютеру используется USB-кабель (тип A–B). Второй блок компонентов может меняться в зависимости от вида практической работы. Основной блок компонентов: Контроллер Arduino UNO Макетная плата x1 x1 246
Дополнительный блок компонентов: Светодиод Резистор 220 Ом Проводники x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.23. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство попеременно управляло включением и выключением трех светодиодов в прямом и обратном направлении (бегущий огонь). 2. Схема подключения Рис. 6.23 Схема подключения светодиода 3. Пример программного кода __________________________________________________________________ // Контакт 4 для подключения светодиода const int LED = 4; 247
void setup() { // Инициализация цифрового пина с номером 4 pinMode(LED, OUTPUT); } void loop() { digitalWrite(LED, HIGH); Светодиод включен, LED ON delay(i); digitalWrite(LED, LOW); Светодиод выключен, LED OFF delay(i); } __________________________________________________________________ Практическая работа № 2. Подключение кнопки В данной работе предлагается изучить принцип подключения кнопок к контроллеру Arduino UNO. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Светодиод Резистор 220 Ом Кнопка Проводники x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.24. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в разделе 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство попеременно управляло включением и выключением двух светодиодов при нажатии кнопки 1 и кнопки 2. 248
2. Схема подключения Рис. 6.24 Схема подключения кнопки __________________________________________________________________ // Контакт 4 для подключения светодиода const int LED = 4; // Контакт 2 для подключения кнопки const int BUTTON = 2; void setup() { // Сконфигурировать контакт светодиода как выход pinMode(LED, OUTPUT); // Сконфигурировать контакт кнопки как вход pinMode(BUTTON, INPUT); } void loop() { if (digitalRead(BUTTON) == LOW) { digitalWrite(LED, HIGH); // Если кнопка нажата (LOW), LED ON } else { digitalWrite(LED, LOW); // Если кнопка не нажата (HIGH), LED OFF } } __________________________________________________________________ Практическая работа № 3. Схемы на основе счета В данной работе предлагается изучить схему счета нажатия кнопки с использованием контроллера Arduino UNO. Количество нажатий кнопки отображается в виде двоичного кода с помощью четырех светодиодов (инкремент). Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. 249
Дополнительный блок компонентов: Светодиод Резистор 220 Ом Кнопка Проводники x4 x4 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.25. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство регистрировало уменьшение счета. Для этого на схеме используйте дополнительную кнопку, которая будет выполнять операцию декремента. При достижении максимального счета программа должна обнулять счет. 2. Схема подключения Рис. 6.25 Схема для подсчета нажатий кнопки 3. Пример программного кода __________________________________________________________________ // Определяем пины для кнопки и светодиодов const int buttonPin = 8; // Пин кнопки 250
const int ledPins[] = {2, 3, 4, 5}; // Пины светодиодов // Переменная для хранения количества нажатий int buttonPressCount = 0; // Переменная для хранения предыдущего состояния кнопки int lastButtonState = HIGH; void setup() { // Настраиваем пины светодиодов на вывод for (int i = 0; i < 4; i++) { pinMode(ledPins[i], OUTPUT); } // Настраиваем пин кнопки на ввод pinMode(buttonPin, INPUT); } void loop() { // Считываем текущее состояние кнопки int buttonState = digitalRead(buttonPin); // Проверяем, изменилось ли состояние кнопки if (buttonState != lastButtonState) { // Если кнопка нажата (состояние HIGH) if (buttonState == LOW) { // Увеличиваем счетчик нажатий buttonPressCount++; // Ограничиваем счетчик до 15 (максимальное значение для 4 бит) if (buttonPressCount > 15) { buttonPressCount = 0; } // Обновляем состояние светодиодов updateLEDs(buttonPressCount); } // Задержка для устранения дребезга контактов delay(50); } // Сохраняем текущее состояние кнопки для следующего цикла lastButtonState = buttonState; } // Функция для обновления состояния светодиодов void updateLEDs(int count) { for (int i = 0; i < 4; i++) { // Устанавливаем состояние светодиода в соответствии с битом числа digitalWrite(ledPins[i], bitRead(count, i)); } } __________________________________________________________________ 251
Практическая работа № 4. Подключение датчиков В данной работе предлагается изучить принцип подключения датчиков к контроллеру Arduino UNO. Тестирование схемы выполняется с использованием датчика температуры LM35 или его аналога. Результат оцифровки данных и перевода напряжения в значение температуры необходимо отобразить в мониторе порта программы Arduino IDE. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Светодиод Резистор 220 Ом Датчик LM35 Проводники x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.26. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Измените программу и доработайте схему, которая позволяет сопровождать световым сигналом от светодиода при превышении (или уменьшении) заданного критического значения температуры (значение устанавливается произвольно). 2. Схема подключения Рис. 6.26 Схема подключения датчика температуры 252
3. Пример программного кода __________________________________________________________________ // Определяем пин, к которому подключен датчик LM35 const int sensorPin = A0; // Аналоговый пин A0 void setup() { // Инициализируем последовательный порт Serial.begin(9600); } void loop() { // Читаем аналоговое значение с датчика int sensorValue = analogRead(sensorPin); // Преобразуем аналоговое значение в напряжение float voltage = (sensorValue * 5.0) / 1023; // Преобразуем напряжение в температуру (в градусах Цельсия) float temperature = (voltage / 0.01); // Отображаем температуру в последовательном порту Serial.print("Температура: "); Serial.print(temperature); Serial.println(" °C"); delay(1000); // Задержка в 1 с } __________________________________________________________________ Практическая работа № 5. Мехатронный модуль В данной работе предлагается изучить принцип подключения сервопривода к контроллеру Arduino UNO. Программа для контроллера позволяет выполнить поворот вала сервопривода на заданный угол. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Сервопривод Кнопка Проводники x1 x2 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.27. В операционной системе Windows/Linux/MacOS откройте про253
грамму Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство имело функцию управления сервоприводом с помощью двух кнопок. Нажатие кнопки 1 позволяет осуществить поворот вала на угол 90, нажатие кнопки 2 — поворот вала на угол –90. 2. Схема подключения Рис. 6.27 Схема подключения сервопривода 3. Пример программного кода __________________________________________________________________ #include <Servo.h> // Подключаем библиотеку для сервопривода // Определяем пины для сервопривода и кнопки const int servoPin = 2; // Пин сервопривода const int buttonPin = 8; // Пин кнопки // Создаем объект для управления сервоприводом Servo myServo; // Переменная для хранения текущего угла сервопривода int angle = 0; // Переменная для хранения предыдущего состояния кнопки 254
int lastButtonState = HIGH; void setup() { // Настраиваем пин кнопки как вход pinMode(buttonPin, INPUT); // Привязываем сервопривод к указанному пину myServo.attach(servoPin); // Устанавливаем начальное положение сервопривода (0 градусов) myServo.write(angle); } void loop() { // Считываем текущее состояние кнопки int buttonState = digitalRead(buttonPin); // Проверяем, изменилось ли состояние кнопки if (buttonState != lastButtonState) { // Если кнопка нажата (состояние HIGH) if (buttonState == LOW) { // Поворачиваем сервопривод на 90 градусов angle = 90; myServo.write(angle); } else { // Возвращаем сервопривод в исходное положение (0 градусов) angle = 0; myServo.write(angle); } // Задержка для устранения дребезга контактов delay(50); // Задержка в 50 мс } // Сохраняем текущее состояние кнопки для следующего цикла lastButtonState = buttonState; } __________________________________________________________________ Практическая работа № 6. Подключение дисплея В данной работе предлагается изучить принцип подключения кнопок к контроллеру Arduino UNO. Программа для контроллера выводит на экран дисплея сообщение. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. 255
Дополнительный блок компонентов: ЖК дисплей Потенциометр Проводники x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.28. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы к контроллеру был подключен потенциометр, изменение напряжения которого выводилось на экран ЖК дисплея. Для реализации схемы рекомендуется использовать дисплей с модулем I2C (в этом случае для подключения используется пин A4 и A5). 2. Схема подключения Рис. 6.28 Схема подключения ЖК дисплея 256
3. Пример программного кода Скетч для поиска устройств на шине I2C. __________________________________________________________________ #include <Wire.h> // Подключаем библиотеку для работы с I2C void setup() { Wire.begin(); Serial.begin(9600); Serial.println("Сканирование I2C устройств..."); } void loop() { byte error, address; for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("Устройство найдено по адресу 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } delay(5000); } __________________________________________________________________ Скетч для вывода на экран дисплея сообщения. __________________________________________________________________ #include <Wire.h> #include <LiquidCrystal_I2C.h> // Подключаем библиотеку для дисплея // Инициализация дисплея с адресом I2C (обычно 0x27 или 0x3F) // Адрес 0x27, 16 символов в строке, 2 строки LiquidCrystal_I2C lcd(0x27, 16, 2); void setup() { // Инициализация дисплея lcd.begin(); // Включаем подсветку дисплея (если есть) lcd.backlight(); 257
// Выводим сообщение на дисплей lcd.setCursor(0, 0); // Устанавливаем курсор в начало lcd.print("Hello, World!"); // Выводим текст } void loop() { // В этом примере loop пустой, так как сообщение выводится в setup() } __________________________________________________________________ Практическая работа № 7. Схема звукового генератора В данной работе предлагается изучить принцип генерации звука с помощью Arduino UNO. Программа позволяет генерировать сигнал заданной частоты. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Излучатель Кнопка Проводники x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.29. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство позволяло генерировать и воспроизводить три сигнала разной частоты. Вывод сигнала осуществляется на пьезоизлучатель с помощью кнопки (перебор частот по нажатию кнопки). 258
2. Схема подключения Рис. 6.29 Схема подключения излучателя для генерации тока 3. Пример программного кода __________________________________________________________________ const int outputPin = 8; нал const int frequency = 1000; // Пин, на котором будет генерироваться сиг// Частота сигнала в герцах (1 кГц) void setup() { // Настройка пина как выхода pinMode(outputPin, OUTPUT); } void loop() { // Генерация сигнала заданной частоты tone(outputPin, frequency); // Генерация сигнала // Бесконечный цикл, так как сигнал генерируется непрерывно while (true) { // Можно добавить другие действия, если необходимо } } __________________________________________________________________ Практическая работа № 8. Управление схемой через USB В данной работе предлагается изучить принцип управления Arduino UNO, используя подключение по USB к ПК. Для управления контроллером рекомендуется использовать программу Arduino IDE и Serial Plotter. Отправка чисел от 1 до 3 в монитор порта позволяет включить один из трех светодиодов. Отправка 0 выключает все светодиоды. Для сборки схемы потребуются следующие ком259
поненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Светодиод Резистор 220 Ом Проводники x3 x3 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.30. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство дополнительно выводило информацию о статусе включения/выключения светодиода. Вывод информации осуществить на экран ЖК дисплея. 2. Схема подключения Рис. 6.30 Схема управления светодиодами через USB 260
3. Пример программного кода __________________________________________________________________ // Определяем пины для светодиодов const int led1Pin = 2; // Пин для 1-го светодиода const int led2Pin = 3; // Пин для 2-го светодиода const int led3Pin = 4; // Пин для 3-го светодиода void setup() { // Настраиваем пины светодиодов как выходы pinMode(led1Pin, OUTPUT); pinMode(led2Pin, OUTPUT); pinMode(led3Pin, OUTPUT); // Инициализация последовательного порта Serial.begin(9600); // Выключаем все светодиоды при старте digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, LOW); digitalWrite(led3Pin, LOW); // Выводим инструкцию в монитор порта Serial.println("Введите число от 0 до 3:"); Serial.println("1 — Включить LED 1"); Serial.println("2 — Включить LED 2"); Serial.println("3 — Включить LED 3"); Serial.println("0 — Выключить все LED"); } void loop() { // Проверяем, есть ли данные в последовательном порту if (Serial.available() > 0) { // Считываем введенное число int command = Serial.parseInt(); // Чтение числа из порта // Обрабатываем команду switch (command) { case 0: // Выключаем все светодиоды digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, LOW); digitalWrite(led3Pin, LOW); Serial.println("Все светодиоды выключены."); break; case 1: // Включаем первый светодиод digitalWrite(led1Pin, HIGH); digitalWrite(led2Pin, LOW); digitalWrite(led3Pin, LOW); Serial.println("Включен LED 1."); 261
break; case 2: // Включаем второй светодиод digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, HIGH); digitalWrite(led3Pin, LOW); Serial.println("Включен LED 2."); break; case 3: // Включаем третий светодиод digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, LOW); digitalWrite(led3Pin, HIGH); Serial.println("Включен LED 3."); break; default: // Некорректная команда Serial.println("Некорректная ввод. Введите число от 0 до 3."); break; } } } __________________________________________________________________ Практическая работа № 9. Передача данных по I2C В данной работе предлагается изучить принцип сопряжения Arduino UNO с другими устройствами по интерфейсу I2С. В работе реализуется процесс регистрации температуры с помощью датчика, который подключен к Arduino nano. Данные между Arduino UNO и Arduino nano передаются с помощью I2С интерфейса. Представлен скетч для работы nano в режиме ведомого устройства. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Датчик LM35 Светодиод Резистор 220 Ом x1 x2 x2 Arduino nano Проводники x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.31. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите 262
кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство Arduino UNO, которое является главным устройством, после получения информации от Arduino nano сигнализирует об изменении температуры относительно заданного значения. При превышении заданного значения начинает мигать светодиод 1. Если измеренное значение температуры ниже заданного, то начинает мигать светодиод 2. 2. Схема подключения Рис. 6.31 Схема сопряжения двух устройств по I2C 3. Пример программного кода Скетч для регистрации температуры Arduino nano в режиме Replica. __________________________________________________________________ #include <Wire.h> // Подключаем библиотеку для работы с I2C const int lmPin = A0; const int i2cAddress = 0x08; // Пин для датчика LM35 // Адрес Arduino nano на шине I2C void setup() { // Инициализация I2C в режиме Replica с указанным адресом Wire.begin(i2cAddress); // Регистрация обработчика события запроса данных от Main Wire.onRequest(requestEvent); } 263
void loop() { // Основной цикл пустой, так как данные отправляются по запросу } // Функция для обработки запроса данных от Main void requestEvent() { // Считываем аналоговое значение с датчика LM35 int analogValue = analogRead(lmPin); // Преобразуем аналоговое значение в напряжение (в вольтах) float voltage = analogValue * (5.0 / 1023.0); // Переводим напряжение в температуру (LM35 выдает 10 мВ на градус Цельсия) float temperature = (voltage * 0.01); // Отправляем температуру как два байта (целая и дробная части) byte tempInt = (byte)temperature; // Целая часть температуры byte tempFrac = (byte)((temperature - tempInt) * 100); // Дробная часть температуры Wire.write(tempInt); Wire.write(tempFrac); // Отправляем целую часть // Отправляем дробную часть } __________________________________________________________________ Скетч для регистрации температуры Arduino UNO в режиме Main. __________________________________________________________________ #include <Wire.h> // Подключаем библиотеку для работы с I2C const int replicaAddress = 0x08; void setup() { Serial.begin(9600); Wire.begin(); } // Адрес Arduino nano // Инициализация последовательного порта // Инициализация I2C в режиме Main void loop() { // Запрашиваем данные от Replica Wire.requestFrom(replicaAddress, 2); // Чтение данных if (Wire.available() == 2) { byte tempInt = Wire.read(); byte tempFrac = Wire.read(); // Запрос 2 байт данных // Целая часть температуры // Дробная часть температуры // Вычисление температуры float temperature = tempInt + (tempFrac / 100.0); 264
// Вывод температуры в монитор порта Serial.print("Температура: "); Serial.print(temperature); Serial.println(" °C"); } delay(1000); // Задержка между запросами } __________________________________________________________________ Практическая работа № 10. Передача данных по SPI В данной работе предлагается изучить принцип сопряжения Arduino UNO с другими устройствами по интерфейсу SPI. В работе реализуется процесс регистрации температуры с помощью датчика, который подключен к Arduino nano. Данные между Arduino UNO и Arduino nano передаются с помощью SPI. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов может меняться в зависимости от вида практической работы. Дополнительный блок компонентов: Датчик LM35 x1 Излучатель Arduino nano Проводники x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 6.32. В операционной системе Windows/Linux/MacOS откройте программу Arduino IDE, создайте новый файл с расширением *.ino и запишите в него программу, приведенную в п. 3. Для тестирования программы нажмите кнопку «Проверить» на панели инструментов. Если ошибок в программе нет, то можно переходить к программированию контроллера. Подключите контроллер к компьютеру, выполните настройку COM-порта (в п. 6.2 указана подробная инструкция). Далее для программирования устройства нажмите кнопку «Загрузка» на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство Arduino UNO, которое является главным устройством, после получения информации от Arduino nano сигнализировало об изменении температуры относительно заданного значения. При превышении заданного значения пьезоизлучатель, подключенный к главному устройству, начинает издавать звук (частота звука выбирается произвольно). 265
2. Схема подключения Рис. 6.32 Сопряжения двух устройств по SPI 3. Пример программного кода Скетч для регистрации температуры Arduino nano в режиме Replica. __________________________________________________________________ #include <SPI.h> // Подключаем библиотеку для работы с SPI const int lmPin = A0; const int сsPin = 10; // Пин датчика LM35 // Пин для выбора Replica (СS) volatile byte receivedData = 0; volatile bool dataReceived = false; // Флаг получения данных void setup() { // Настраиваем пин СS как вход pinMode(сsPin, INPUT); // Инициализация SPI в режиме Replica SPCR |= bit(SPE); // Включаем SPI SPCR |= bit(SPIE); // Включаем прерывания SPI // Включаем глобальные прерывания sei(); } void loop() { // Если данные получены if (dataReceived) { // Считываем аналоговое значение с датчика LM35 int analogValue = analogRead(lmPin); // Преобразуем аналоговое значение в напряжение (в вольтах) float voltage = analogValue * (5.0 / 1023.0); 266
float temperature = voltage * 100.0; // Отправляем температуру как два байта (целая и дробная части) byte tempInt = (byte)temperature; // Целая часть температуры byte tempFrac = (byte)((temperature - tempInt) * 100); // Дробная часть температуры // Отправляем данные Main устройству SPI.transfer(tempInt); // Отправляем целую часть SPI.transfer(tempFrac); // Отправляем дробную часть // Сбрасываем флаг получения данных dataReceived = false; } } // Обработчик прерывания SPI ISR(SPI_STC_vect) { // Чтение полученных данных receivedData = SPDR; dataReceived = true; } __________________________________________________________________ Скетч для регистрации температуры Arduino UNO в режиме Main. __________________________________________________________________ #include <SPI.h> // Подключаем библиотеку для работы с SPI const int csPin = 10; // Пин для выбора Replica (SS) void setup() { Serial.begin(9600); pinMode(csPin, OUTPUT); digitalWrite(csPin, HIGH); SPI.begin(); } // // // // Инициализация последовательного порта Настраиваем пин CS как выход Деактивируем Replica Инициализация SPI в режиме Main void loop() { // Активируем Replica digitalWrite(csPin, LOW); // Запрашиваем данные от Replica устройства byte tempInt = SPI.transfer(0); // Получаем целую часть температуры byte tempFrac = SPI.transfer(0); // Получаем дробную часть температуры // Деактивируем Replica digitalWrite(csPin, HIGH); 267
// Вычисление температуры float temperature = tempInt + (tempFrac / 100.0); // Вывод температуры в монитор порта Serial.print("Температура: "); Serial.print(temperature); Serial.println(" °C"); delay(1000); // Задержка между запросами } __________________________________________________________________ 268
ГЛАВА 7 ПРОГРАММИРОВАНИЕ МИКРОКОМПЬЮТЕРОВ 7.1. Особенности микрокомпьютеров Raspberry Pi 7.1.1. История создания микрокомпьютера Raspberry Pi — это одноплатный микрокомпьютер, имеющий на своей платформе множество различных модулей. Среди модулей можно выделить следующие: Remote GPIO, Camera, SPI, I2C, Serial Port, 1-wire, Ethernet, Wi-Fi, Bluetooth. Особенностью Raspberry Pi является то, что он обладает собственным графическим ядром с возможностью подключения внешних устройств через HDMI. Микрокомпьютер имеет малые размеры, соизмеримые с банковской картой. Изначально система разрабатывалась для использования в учебных целях по информатике, но позже получила широкое применение в разных областях электроники. История создания микрокомпьютера берет начало с 2006 г. Именно в это время сотрудники и преподаватели компьютерной лаборатории Кембриджского университета начали реализацию проекта доступного одноплатного компьютера, способного быть вычислительной платформой для обучения программированию широкого круга людей. Разработчики, в первую очередь, ориентировались на школы и другие образовательные учреждения. В 2009 г. была создана благотворительная организация Raspberry Pi Foundation, которая занималась сбором средств, разработкой и продвижением идеи одноплатного микрокомпьютера. И вот, наконец, в 2011 г. британский программист Дэвид Брэбен (David Jonh Braben) представил концепт первого микрокомпьютера Raspberry Pi. Серийное производство микрокомпьютера началось в 2012 г., но имело существенное ограничение на количество выпускаемых устройств (первая партия составляла 10 тыс. экземпляров). Сейчас данное устройство может купить любой заинтересованный пользователь. Внешний вид одноплатного компьютера представлен на рисунке 7.1. Рис. 7.1 Модель Raspberry Pi ver.4 B 269
К моменту написания данного материала (2020 г.) насчитывается более 10 модификаций и доработок первого устройства, а последнее имеет индекс модели под номером 4 (Raspberry Pi 4). Основная задача, которую решают современные разработчики данного устройства — это улучшение его характеристик при сохранении размеров. Отметим, что размеры первой и последней версии устройства практически одинаковые. Далее мы рассмотрим технические особенности разных моделей Raspberry Pi. 7.1.2. Технические характеристики и возможности Bluetooth Wi-Fi Ethernet USB GPIO ОЗУ Ядер Частота Архитектура Ver. Дата выхода Raspberry Pi является компьютером, поэтому правильно будет начинать описание технических характеристик с базовых элементов микропроцессорной системы: процессор и память. Первые модели были оснащены ARM11 процессором Broadcom BCM2835 с тактовой частотой 700 МГц и модулем оперативной памяти на 256 Мб. Модель Raspberry Pi 4, по сравнению с первой версией, имеет более мощный четырехъядерный процессор Cortex-A72 (ARM v8) с тактовой частотой до 1,5 ГГц и памятью ОЗУ 1, 2 или 4 Гб. В таблице ниже представлена сравнительная характеристика всех доступных на сегодняшний день микрокомпьютеров Raspberry. апрель 2012 B ARM1176JZ-F 700 МГц 1 512 МБ 26 пинов 2 порта есть — — февраль 2013 A ARM1176JZ-F 700 МГц 1 256 МБ 26 пинов 1 порт — — — июнь 2014 B+ ARM1176JZ-F 700 МГц 1 512 МБ 40 пинов 4 порта есть — — ноябрь 2014 A+ ARM1176JZ-F 700 МГц 1 256 МБ 40 пинов 1 порт — — — февраль 2015 2B ARM Cortex-A7 900 МГц 4 1 ГБ 40 пинов 4 порта есть — — ноябрь 2015 Zero ARM1176JZ-F 1 ГГц 1 512 МБ 40 пинов 1 порт [20] — — — февраль 2016 3B Cortex-A53 (ARM v8) 1,2 ГГц 4 1 ГБ 40 пинов 4 порта есть 802.11n 4.1 февраль 2017 Zero W ARM1176JZ-F 1 ГГц 1 512 МБ 40 пинов 1 порт — 802.11n 4.0 март 2018 3B+ Cortex-A53 (ARM v8) 1,4 ГГц 4 1 ГБ 40 пинов 4 порта Gigabit через 802.11ac 4.2 USB2 октябрь 2018 3A+ Cortex-A53 (ARM v8) 1,4 ГГц 4 512 МБ 40 пинов 1 порт — июнь 2019 4B Cortex-A72 (ARM v8) 1,5 ГГц 4 1, 2, 4 ГБ 40 пинов 4 порта Gigabit 802.11ac 5.0 270 802.11ac 4.2
Для вывода видеосигнала в микрокомпьютере имеются следующие разъемы: композитный разъем RCA и цифровой HDMI-интерфейс. Существует возможность перехода на традиционный VGA- и DVI-разъем через переходник. В поздних версиях есть разъем для подключения аудиоустройств 3,5 мм. На устройство можно установить полноценную операционную систему, которая будет размещаться на карте памяти SD (microSD), MMC (в моделях A и B). Возможна загрузка с USB-носителя или по сети. С развитием технологий USB, Ethernet, Wi-Fi и Bluetooth на каждой новой версии Raspberry Pi устанавливают обновленные версии указанных интерфейсов. Особый интерес представляют низкоуровневые интерфейсы: GPIO, I2C, SPI, 1-wire, UART. Позднее мы познакомимся с языком программирования Python и научимся создавать приложения для работы с этими интерфейсами. Raspberry Pi может работать на разных операционных системах. В основном это системы на Linux-ядре. В поздних версиях устройства появилась возможность установки Windows 10. Для установки операционной системы можно воспользоваться специальным модулем NOOBS. Последняя версия образа всегда доступна на сайте официального сообщества по адресу: https://www.rasp berrypi.org/downloads/noobs/. Для тех, кто только начинает знакомство с этой платформой, рекомендуется использовать операционную систему Raspbian. 7.1.3. Настройка операционной системы Raspbian В операционной системе Raspbian предусмотрено несколько режимов для работы с привилегиями. Существуют базовые привилегии и суперпользователь. Если использовать режим общего доступа, то могут быть недоступны некоторые команды и операции, выполняемые на компьютере. На практике очень часто при написании команд в консоли используется префикс sudo. Префикс служит указателем на то, что выполнение команды запрашивает суперпользователь. Теперь рассмотрим несколько базовых команд, которые позволят настроить систему для выполнения поставленных задач. Общие команды Команда apt-get update apt-get upgrade clear find / -name file_name nano file_name raspi-config reboot poweroff shutdown -h now startx lsusb Описание синхронизация списков пакетов на устройстве и в репозитории (используется при установке новых пакетов) обновление всех установленных пакетов в системе очистка всех ранее введенных команд поиск файла в системе открытие файла в текстовом редакторе nano открытие меню настроек конфигурации перезагрузка системы немедленное выключение выключить сейчас (вместо now можно указать время) открытие GUI (графический интерфейс пользователя) список устройств USB, подключенных к устройству 271
Команды для работы с файлами и директориями Команда cat file_name cd dir_name cp file_name ls -l mkdir mv file_name (dir_name) rm file_name rmdir dir_name Описание отображает содержимое файла изменяет текущий каталог на новое название копирование файлов список файлов в текущем каталоге создает новый каталог перемещает файл или каталог удаление файла удаление каталога Сетевые команды для работы с устройствами и интернет Команда ifconfig iwconfig iwlist wlan0 scan nmap ping hostname -I Описание проверка состояния беспроводного соединения проверка сети беспроводного адаптера список беспроводных сетей скан сети и вывод подключенных устройств проверка связи между двумя устройствами IP-адрес вашего Raspberry Pi Для работы с различными интерфейсами необходима их активация в системе. По умолчанию многие модули отключены. Подобный подход позволяет существенно ограничивать энергопотребление устройства (для питания устройства требуется источник 5В с током не менее 1А). Рассмотрим способ настройки устройства. Для этого необходимо запустить Terminal и выполнить следующую команду: __________________________________________________________________ sudo raspi-config __________________________________________________________________ Через консоль будет запущена программа Raspberry Pi Software Configuration Tool. В открытом окне выберите 5 пункт Interfacing Option. Следующее меню позволит вам включить или отключить дополнительный модуль устройства: camera, SSH, VNC, SPI, I2C, Serial, 1-wire, GPIO. Подробную информацию о настройке Raspberry Pi можно узнать на сайте разработчика. Основным преимуществом данного устройства является наличие выводов GPIO (general-purpose input/output), которые позволяют реализовать взаимодействие микрокомпьютера с внешними периферийными устройствами. Модели до 2014 г. имели 26-контактный разъем GPIO. Поздние версии имеют 40-контактный коннектор GPIO (в том числе Pi Zero и Pi Zero W). На рисунке 7.3 представлена распиновка Raspberry Pi. 272
Рис. 7.2 Raspberry Pi Software Configuration Tool (Interfacing Option) Рис. 7.3 Обозначение выводов GPIO Raspberry Pi Большинство выводов могут быть настроены на ввод или вывод (по аналогии с портами ввода/вывода микроконтроллера). На рисунке 7.3 видно, что дополнительно имеются два вывода под питание +5 В, два вывода под питание +3,3 В и несколько общих выводов, которые нельзя запрограммировать. Необходимо запомнить, что выводы общего назначения допускают работу с напряжением не более +3,3 В. Входное напряжение больше этого значения может вывести из строя вывод, на который будет подано это напряжение. Выводы могут быть запрограммированы на высокое +3,3 В или низкое состояние 0 В. Выводы GPIO, запрограммированные на ввод, могут считывать +3,3 В или низкое состояние 0 В. Данный подход возможен при использовании подтягивающих резисторов. Выводы GPIO2 и GPIO3 имеют фиксированные подтягивающие резисторы. Для других выводов подтягивающие резисторы могут быть настроены в программе. GPIO-выводы могут выполнять альтернативные функции. Рассмотрим пример некоторых из них. PWM (pulse-width modulation), или широтно-импульсная модуляция. Программно PWM доступна для всех выводов. Аппаратно PWM можно реализовать на GPIO12, GPIO13, GPIO18, GPIO19. SPI-интерфейс передачи данных. Всего доступно 2 интерфейса. Для SPI0: SDI (GPIO10), SDO (GPIO9), SCK (GPIO11), CE0 (GPIO8), CE1 (GPIO7). 273
Для SPI1: SDI (GPIO20), SDO (GPIO19), SCK (GPIO21), CE0 (GPIO18), CE1 (GPIO17), CE2 (GPIO16). I2C-интерфейс передачи данных: Data (GPIO2), Clock (GPIO3), EEPROM Data (GPIO0), EEPROM Clock (GPIO1). Последовательная передача данных Serial (UART): TX (GPIO14), RX (GPIO15). Иногда очень важно знать, какой вывод за что отвечает. Для того чтобы не ошибиться с правильной распиновкой, в Raspbian всегда можно вызвать специальную команду, которая покажет нумерацию всех выводов именно для вашего устройства. Для просмотра выводов необходимо запустить Terminal и выполнить следующую команду: __________________________________________________________________ pinout __________________________________________________________________ Данная команда — чтобы дополнительно узнать модель устройства, его особенности архитектуры и наличие дополнительных модулей. На рисунке 7.4 представлен результат выполнения команды pinout на одном из устройств. Рис. 7.4 Вызов команды pinout в терминале ОС Raspbian Существует множество справочной литературы и интернет-ресурсов, которые позволяют по модели устройства узнать назначение и порядок обозначения выводов. Особой популярностью пользуется интерактивный ресурс Raspberry Pi Pinout, на котором доступно описание всех интерфейсов выводов GPIO Raspberry Pi. Ресурс доступен по адресу: https://pinout.xyz/. Для программирования и управления выводами GPIO используются различные языки программирования и инструментов: Scratch, C/C++, Python, Processing 3. Ниже представлены примеры применения модуля RPi.GPIO на языке Python для настройки выводов GPIO. Существуют два режима нумерации выводов GPIO. GPIO.BOARD — система нумерации портов на плате Raspberry Pi (не зависит от версии платы). GPIO.BCM — система с уровнем обращения 274
к номерам каналов на процессоре Broadcam. Для установки библиотеки необходимо запустить Terminal и выполнить следующую команду: __________________________________________________________________ sudo apt-get install python-rpi.gpio __________________________________________________________________ Следующий программный код демонстрирует некоторые возможности библиотеки RPi.GPIO на языке Python. __________________________________________________________________ import RPi.GPIO as GPIO # Подключение модуля GPIO GPIO.setmode(GPIO.BOARD) GPIO.setmode(GPIO.BCM) # Установка режима GPIO.BOARD # Установка режима GPIO.BCM GPIO.setup(pin, GPIO.OUT) GPIO.setup(pin, GPIO.IN) # Заданный pin настраиваем на вывод # Заданный pin настраиваем на вход GPIO.setup(pin, GPIO.OUT, GPIO.HIGH) GPIO.setup(pin, GPIO.OUT, GPIO.LOW) # Высокий начальный уровень для pin # Низкий начальный уровень для pin GPIO.setup(pin, GPIO.IN, GPIO.PUD_UP) GPIO.setup(pin, GPIO.IN, GPIO.PUD_DOWN) GPIO.setwarnings(False) # Вывод подтянут к Vcc # Вывод подтянут к GND # Обработка ошибок (True/False) GPIO.output(pin, GPIO.HIGH) # Заданный pin с высоким уровнем напряжения (3.3 В) GPIO.output(pin, GPIO.LOW) # Заданный pin с низким уровнем напряжения (0.0 В) result = GPIO.input(pin) # Чтение состояния pin в result GPIO.cleanup() # Очистка состояния пинов __________________________________________________________________ При работе с выводами GPIO Raspberry Pi необходимо запомнить несколько особенностей. Подключение простых устройств к портам является практически безопасным, но нужно быть внимательным и соблюдать полярность согласно схеме подключения. Светодиоды должны обязательно иметь резисторы для ограничения тока, проходящего через них. Не использовать питание +5 В для устройств, рассчитанных на питание +3,3 В. При подключении различных двигателей необходимо использовать мостовые схемы или специальные драйверы. В последующих разделах мы подробно разберем особенности работы GPIO на конкретных примерах. Программирование устройства будет реализовано на языке программирования Python. 275
7.2. Основы программирования на языке Python 7.2.1. Программное обеспечение для работы с Python Для создания программ на Python нужно предварительно установить интерпретатор (программу для преобразования написанного кода в машинный) и среду разработки. На начальном этапе можно использовать среду разработки, которую можно загрузить вместе с интерпретатором по ссылке с официального сайта разработчика. В Raspbian установку интерпретатора можно выполнить, используя команду в терминале: __________________________________________________________________ sudo apt-get install python3–pip __________________________________________________________________ Начинающим пользователям рекомендуется использовать среду программирования Geany IDE. В ней упрощен процесс написания и отладки программы. Для программной среды существует дополнительная библиотека, которую можно установить заранее. Она позволяет создавать приложения для работы с аппаратной частью микрокомпьютеров Raspberry Pi, используя порты GPIO. Дополнительное рекомендуемое ПО — среда программирования JetBrains PyCharm (Community) и Microsoft Visual Studio Code. Далее рассмотрим пример создания программы на Python в среде программирования Geany IDE. Перейдите в раздел Programming в панели Пуск и выберите соответствующую программу Geany (рис. 7.5). Создайте новый пустой файл и сохраните его. Рис. 7.5 Главное окно программы Geany IDE 276
Для создания файла выберите в главном меню File -> New, файл, например, test.py. Добавим в новый файл одну команду print(), которая предназначена для вывода информации. Пусть программа выводит на экран текст ‘Hello World!’. __________________________________________________________________ print('Hello World!') # Вывод 'Hello World!'на экран __________________________________________________________________ Для запуска программы панели основных инструментов нажмите соответствующую кнопку запуска. После запуска программы будет открыто новое окно и показан результат выполнения программы (рис. 7.6). Рис. 7.6 Вывод результата запуска скрипта в программе Geany IDE Теперь рассмотрим более сложную программу с использованием переменных. Переменная — это контейнер для хранения определенных значений данных. Для ввода данных в программу используется команда input(). Следующий листинг для расчета площади прямоугольника демонстрирует использование этого метода. __________________________________________________________________ # Программа для нахождения площади прямоугольника a = int(input()) # сторона a b = int(input()) # сторона b 277
S = a * b # Площадь прямоугольника print('Площадь прямоугольника = {:.2f}'.format(S)) __________________________________________________________________ Результат программы. __________________________________________________________________ 4 5 Площадь прямоугольника = 20.00 ––––––––– (program exited with code: 0) __________________________________________________________________ В данной программе используется конструкция int(input()). Функция int() преобразует вводимые данные в целое число. По умолчанию тип данных, которые возвращает функция input(), — это строковый тип данных. 7.2.2. Целые числа, ввод/вывод, простые операции со строками Для работы с данными на практике очень часто приходится использовать числовой тип данных. Мы будем использовать три основных вида чисел: целые, с плавающей точкой и комплексные. Целочисленный тип данных. Из математики известно, что под данное определение попадает следующий ряд чисел: 0, –1, 1, –2, 2 ..., –N, N. Посмотрим примеры программ на Python для обработки целых чисел. __________________________________________________________________ print(3 + 2) # (Пример 1) print('3' + '2') # (Пример 2) print('3 + 2 =', 3 + 2) # (Пример 3) print('3 + 2 =', 3 + 2, sep=' ') # (Пример 4) print(4, 3, 2, 1, sep=' + ', end='\n') # (Пример 5) __________________________________________________________________ Давайте рассмотрим эти примеры более подробно. Первое, что следует отметить, это появление новой конструкции, начинающейся с символа #. В Python комментарии обычно обозначают таким образом. Использование комментариев — это правило хорошего тона в программировании, и рекомендуется всегда включать их в свои программы. Пример 1 демонстрирует вывод суммы двух целых чисел на экран. Пример 2 показывает конкатенацию (объединение) двух строк. Обратите внимание, что строка может быть заключена в двойные или одинарные кавычки. В примере 4 используется новая для нас конструкция, называемая именованным параметром sep (разделитель). Его можно использовать, когда нужно разделить результат вывода каким-либо символом. В этом случае разделителем служит пробел. Пример 5 использует еще одну неизвестную для нас конструкцию, называемую именованным параметром end (оконча278
ние). Этот параметр указывает на окончание строки. В нашем примере окончание строки обозначается переходом на новую строку. Создайте новый файл, вставьте в него приведенные примеры и проверьте результаты работы программы. Сравните полученные результаты с предоставленными ответами. __________________________________________________________________ 5 32 3 + 2 = 5 3 + 2 = 5 4 + 3 + 2 + 1 ––––––––– (program exited with code: 0) __________________________________________________________________ Для работы с числами в Python реализована возможность использования арифметических операций, которые можно применить для обработки значений. Ряд других арифметических операций представлен в таблице ниже. Знак + – * // % ** Операция Сложение Вычитание Умножение Целочисленное деление Остаток от деления Возведение в степень Значение 1 5 5 5 15 14 2 Значение 2 4 4 4 4 4 3 Результат 9 1 20 3 2 8 Также существует распространенный тип данных string (строка), который мы рассматривали на примере операции конкатенации строк. Функция str() преобразует данные в тип данных строка. При работе со строками часто используют срезы — способ извлечения части символов или отдельных символов из строки. Создание среза создает новую строку с сохранением структуры старой. Каждый символ строки имеет свой индекс, нумерация может быть двух видов: с индексами от 0 до N и от –N до –1. Рассмотрим пример получения среза. __________________________________________________________________ string = 'abcdefghi' str_1 str_2 str_3 str_4 str_5 str_6 str_7 = = = = = = = string[0] string[0:5] string[3:] string[–1] string[–5:–2] string[:–5] string[::–1] 279
print(str_1, str_2, str_3, str_4, str_5, str_6, str_7, sep='\n') __________________________________________________________________ При использовании срезов строку string можно представить следующим образом. Показан пример использования прямой и обратной индексации. [0 ... N] [–N ... –1] a 0 –9 b 1 –8 c 2 –7 d 3 –6 e 4 –5 f 5 –4 g 6 –3 h 7 –2 i 8 –1 Работа со строками: методы find, replace и count. Первый метод находит индекс первого вхождения подстроки в строке. Второй метод заменяет вхождение подстроки на новое значение в строке. Третий метод считает количество вхождений подстроки в строке. __________________________________________________________________ st = '123123456' s_1 = st.find('123', 3) # Индекс первого вхождения от 3-го индекса s_2 = st.replace('456', '123', 1) # Замена '456' на '123' один раз s_3 = st.count('123') # Подсчет всех вхождений '123' s_4 = len(st) # Нахождение длины строки print(s_1, s_2, s_3, s_4, sep='\n') __________________________________________________________________ Также существует метод rfind, который ищет индекс первого вхождения, начиная с другого конца строки. Функция len() используется для определения длины строки. Она понадобится нам позже при создании циклов, позволяющих последовательно проходить по всем символам строки от начала до конца. 7.2.3. Вещественные числа и операции над ними Вещественное число (число с плавающей точкой) можно представить в виде N = M*qp, где M — мантисса, q — основание, а p — порядок. Вещественные числа отличаются от натуральных тем, что они могут быть представлены с использованием чисел с плавающей точкой. Поскольку вещественных чисел гораздо больше, чем натуральных, в Python для хранения этих чисел требуется ограничение точности. Рассмотрим простой пример сложения двух чисел. __________________________________________________________________ a = 0.1 b = 0.2 # число a # число b print(a + b) __________________________________________________________________ 280
Результат программы. __________________________________________________________________ 0.30000000000000004 ––––––––– (program exited with code: 0) __________________________________________________________________ Результат выполнения программы показал неожиданное значение в одном из разрядов. Это связано с особенностями языка программирования Python и метода хранения чисел в памяти компьютера. При решении задач, требующих высокой точности, необходимо учитывать эту особенность, чтобы избежать дополнительных погрешностей вычислений. Для упрощения обработки данных иногда используются различные функции округления. Пример использования таких функций приведен ниже. В этом случае подключаются дополнительные модули программы, а именно библиотека math для вычисления квадратного корня числа. __________________________________________________________________ import math # Подключение математического модуля print(int(2.5)) # Округление в сторону нуля print(round(2.5)) # Округляет до ближайшего целого print(math.floor(2.5)) # Округление в меньшую сторону print(math.ceil(2.5)) # Округление в большую сторону __________________________________________________________________ В математической библиотеке доступны функции для округления, например trunc(), которая работает подобно int(). Math содержит много других математических функций для работы с действительными числами. Рассмотрим пример использования вещественных чисел при решении задач. Следующий листинг позволяет рассчитать площадь основания и объем геометрической фигуры пирамиды. __________________________________________________________________ import math # Подключение математического модуля # a b c Дана правильная треугольная пирамида = 1.5 # 1 сторона основания = 1.5 # 2 сторона основания = 1.5 # 3 сторона основания h = math.sqrt(3) # Высота пирамиды S = (a * a * math.sqrt(3)) / 4 # Площадь основания V = 1/3 * S * h # Объем фигуры print('Объем пирамиды = {:.2f}'.format(V)) __________________________________________________________________ 281
Полученный результат сравните со своим ответом. __________________________________________________________________ Объем пирамиды = 0.56 ––––––––– (program exited with code: 0) __________________________________________________________________ Попробуйте проверить результат работы скрипта. Для проверки можно использовать ранее рассмотренную программу Geany IDE. Конечно, для написания и отладки скриптов можно использовать и другое программное обеспечение. 7.2.4. Условный оператор, цикл while и цикл for В предыдущих разделах мы изучили два типа данных: числа и строки. Теперь рассмотрим логический тип данных, который может принимать только два значения: True (истина) или False (ложь). Аналогично арифметическим операциям, существуют логические операции. В таблице представлены наиболее часто используемые из них. Знак сравнения < > <= >= == != Описание Условие меньше Условие больше Условие меньше либо равно Условие больше либо равно Условие равно Условие не равно Пример демонстрации использования логических типов данных. __________________________________________________________________ a b c d = = = = 6 1 3 4 # # # # Переменная Переменная Переменная Переменная a b c d result_1 = a <= b and c <= d result_2 = a >= b or c >= d result_3 = a <= b or c >= d and c <= d # 1-е логическое выражение # 2-е логическое выражение # 3-е логическое выражение print(result_1, result_2, result_3) __________________________________________________________________ 282
Результат программы. __________________________________________________________________ >>> %Run example_05.py False True False ––––––––– (program exited with code: 0) __________________________________________________________________ Логический тип данных широко применяется в условных операторах, где проверяется выполнение условия с использованием конструкции if и последующего блока команд. Рассмотрим пример проверки условия для введенного целого числа. Если введенное значение больше нуля, выводится сообщение «Введенное число >0», иначе — «Введенное число <0». Изучите результаты выполнения программы самостоятельно и используйте различные логические выражения для проверки условий оператора if-else. __________________________________________________________________ num = int(input()) # Ввод целого числа if num > 0: # Если число num > 0, то выводим print('Введенное число > 0') else: # Иначе выводим следующее print('Введенное число < 0') __________________________________________________________________ Оператор if позволяет использовать вложенные конструкции. Однако при проверке множества условий многократное применение этого оператора не является наилучшим подходом. В такой ситуации рекомендуется использовать конструкцию if-else вместе с оператором elif. __________________________________________________________________ num = int(input()) # Ввод целого числа if num == 1: # Если число num = 1, то выводим print('Яблоко') elif num == 2: # Если число num = 2, то выводим print('Апельсин') elif num == 3: # Если число num = 3, то выводим print('Банан') else: # Иначе выводим следующее print('Другой фрукт') __________________________________________________________________ 283
Пожалуйста, изучите предоставленный код самостоятельно. Чтобы понять логику работы программы, добавьте дополнительные условия, используя оператор elif. Оператор while используется для создания различных циклов. Она работает следующим образом: при входе в цикл происходит проверка условия while, затем выполняется блок инструкций и осуществляется переход к повторной проверке условия. Если условие не выполняется, цикл завершается и начинается следующий блок программы. Этот подход удобен для создания бесконечных циклов. __________________________________________________________________ num = int(input()) # Ввод целого числа while num != 0: # Пока введенное число не равно нулю print('Вы ввели {}, программа продолжается'.format(num)) num = int(input()) # Ввод нового числа print('Вы ввели 0, программа завершена') __________________________________________________________________ Если нужно принудительно завершить цикл while, используйте оператор break. Хотя этот оператор может быть полезен в некоторых ситуациях, обычно лучше избегать его использования. Далее рассмотрим другую конструкцию для организации циклов, называемую циклом for. Этот цикл позволяет последовательно обрабатывать элементы из некоторого объекта (например, iterable, tuple или list). Часто for используется вместе с функцией range(), которая создает элементы типа iterable. О списках более подробно мы поговорим в следующем разделе. Сейчас скажем о том, что список — это специальный контейнер, который способен хранить в себе данные различных типов. Элементы списка перечисляют через запятую, а по бокам структуры используют квадратные скобки. __________________________________________________________________ print(list(range(10))) # Генерация списка [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] __________________________________________________________________ Приведем пример использования цикла for для обработки данных. Перебор всех элементов списка, в котором данные хранятся в виде строк: __________________________________________________________________ apples = ['red', 'green', 'yellow'] # Список с набором элементов for color in apples: print('Цвет яблока', color, sep=' ') __________________________________________________________________ 284
Результат программы. __________________________________________________________________ Цвет яблока red Цвет яблока green Цвет яблока yellow ––––––––– (program exited with code: 0) __________________________________________________________________ Создание нового списка, используя функцию range(). В качестве результата мы получим набор натуральных чисел: __________________________________________________________________ listn = [] # Создание пустого списка for i in range(1, 10): # Цикл для i от 1 до 9 listn.append(i**2) # Добавления квадрата числа в список print(listn) # Вывод списка на экран __________________________________________________________________ Результат программы. __________________________________________________________________ [1, 4, 9, 16, 25, 36, 49, 64, 81] ––––––––– (program exited with code: 0) __________________________________________________________________ Циклы могут быть вложенными. Не рекомендуется использовать большое количество вложенных циклов, так как это может существенно замедлить скорость выполнения программы. Пример использования сложенных циклов: __________________________________________________________________ # Создание таблицы умножения от 1 до 9 for i in range(1, 10): for j in range(1, 10): print('{: >2.0f}'.format(i*j), end=' ') print() __________________________________________________________________ В следующих разделах мы подробнее изучим обработку данных различных списков. Существуют различные парадигмы программирования. Наши методы записи циклов относятся к императивному программированию. Для изучения других парадигм рекомендуется ознакомиться с дополнительной литературой. 285
7.2.5. Кортежи, списки и их сортировка В этом разделе мы изучим два новых типа данных: кортежи и списки. Кортежи (tuple) состоят из элементов разных типов и являются неизменяемыми. Они заключаются в круглые скобки (). Кортежи могут содержать другие кортежи внутри себя. Списки (list) также включают элементы разных типов, но они являются изменяемыми. Их заключают в квадратные скобки []. Давайте рассмотрим примеры создания кортежей и списков. __________________________________________________________________ string = '12345' # Ввод строки tuplen = tuple(string) # Создание кортежа listn = list(string) # Создание списка print(tuplen) print(listn) # Вывод кортежа # Вывод списка print(tuplen[0]) print(listn[4]) # Вывод элемента кортежа с индексом [0] # Вывод элемента списка с индексом [4] __________________________________________________________________ Результат программы. __________________________________________________________________ ('1', '2', '3', '4', '5') ['1', '2', '3', '4', '5'] 1 5 ––––––––– (program exited with code: 0) __________________________________________________________________ Ранее упоминалось, что список — это изменяемая структура. Рассмотрим методы работы со списком и его элементами. Метод m_list.append(x) m_list.extend(L) m_list.insert(i, x) m_list.remove(x) m_list.pop([i]) m_list.count(x) m_list.sort([key=функция]) m_list.reverse() m_list.clear() Функция Добавление элемента x к списку Добавление списка L в конец существующего списка Вставка на место i-го элемента значения x Удаление первого элемента x в списке Удаление i-го элемента списка Возврат количества элементов со значением x Сортирует список на основе функции Разворачивает список Очищает список 286
Теперь рассмотрим способы сортировки данных на основе использования метода sort(). Числа сортируются по возрастанию, а буквы — по алфавиту. С помощью лямбда-функций можно сортировать данные по различным столбцам списка. Следующий пример показывает возможность сортировки данных более сложной структуры — списка с вложенными списками. Визуально можно представить данные в виде матрицы 33. __________________________________________________________________ # Определение списка целых чисел 3x3 listn = [[5, 3, 1], [4, 5, 8], [7, 2, 5]] # Сортировка списка по 2 столбцу с инверсией listn.sort(key=lambda i: i[1], reverse=True) print(listn) # Вывод нового списка __________________________________________________________________ Результат программы. __________________________________________________________________ [[7, 2, 5], [5, 3, 1], [4, 5, 8]] ––––––––– (program exited with code: 0) __________________________________________________________________ Ранее мы использовали функцию int() для добавления элементов по строкам в нашу программу. Чтобы упростить задачу ввода нескольких символов, можно использовать метод split(), который создает набор элементов из строки. Например, чтобы создать список из введенной строки целых чисел, нужно сделать следующее: __________________________________________________________________ listn = list(map(int, input().split())) listn = [1, 2, 3] print(' '.join(map(str, listn))) __________________________________________________________________ Результат программы. __________________________________________________________________ 1 2 3 4 5 6 287
1 2 3 ––––––––– (program exited with code: 0) __________________________________________________________________ В этом случае функция map() помогает преобразовать каждый новый элемент введенной строки в число типа integer. Также существует обратная функция join(), которая используется для создания строки из списка элементов. В последнем примере в качестве разделителя используется пробел. 7.2.6. Множества и словари В языке Python множества представляют собой тип данных, состоящий из набора элементов без определенного порядка. Они похожи на математические множества. Можно выполнять операции добавления, удаления, перебора элементов и проверки принадлежности к множеству. Множества обозначаются фигурными скобками и создаются с использованием функции set(). Множество может содержать элементы различных типов: кортежей, списков и диапазонов. __________________________________________________________________ nSet_1 = {3, 1, 2, 3} print(nSet_1) # Создание множества nSet_2 = set((3, 1, 2)) print(nSet_2) # Создание множества из кортежа nSet_5 = {1, (1, 2, 3), 'Python'} # Создание множества из разных типов данных print(nSet_5) __________________________________________________________________ Обратите внимание, что при выводе множеств с помощью функции print(), элементы множества располагаются в порядке возрастания (для букв и слов — по алфавиту). Если некоторые элементы повторяются, все повторения будут удалены из множества. Групповые операции для обработки множеств. В таблице ниже представлены операции, которые позволяют обрабатывать не отдельные элементы множества, а множество целиком. Логические операции Операция A|B A&B A-B A^B Описание Объединение множеств Пересечение множеств Множество, элементы которого входят в A, но не входят в B Элементы входят в A | B, но не входят в A & B 288
Операции сравнения Операция A == B A != B A <= B A<B Описание Все элементы совпадают Есть различные элементы Все элементы A входят в B A <= B и A != B Еще одна сложная структура данных в Python — словари. Их удобно использовать, когда нужно сопоставить два элемента, например, футболиста и количество голов, которые он забил за свою карьеру. Первый элемент — это ключ, а второй — значение. __________________________________________________________________ football_players = {'Роналду' : 902, 'Месси' : 840, 'Пеле' : 762} __________________________________________________________________ Давайте разберемся, как создавать словари, добавлять и удалять их элементы. Важно помнить, что словари — это итерируемые объекты. Для работы с ними можно использовать цикл for. __________________________________________________________________ football_players = dict() # Создание пустого словаря football_players ['Роналду'] = 902 football_players ['Месси'] = 840 football_players ['Пеле'] = 762 # Роналду 902 гола за карьеру # Месси 840 голов за карьеру # Пеле 762 гола за карьеру print(football_players) del football_players ['Роналду'] # Удаление элемента с ключом 'Роналду' print(football_players) __________________________________________________________________ Предлагается самостоятельно изучить результат работы программы. Следующий пример показывает использование цикла for для обработки словарей. __________________________________________________________________ football_players = {'Роналду' : 902, 'Месси' : 840, 'Пеле' : 762} for footballer in football_players: дексу print(footballer, football_players[footballer]) for footballer, goals in football_players.items(): items() print(footballer, goals) 289 # Обращение по ин- # Обращение через
for footballer in football_players.keys(): print(footballer) # Обращение к ключам for goals in football_players.values(): ниям print(goals) # Обращение к значе- football_players.setdefault('Ромарио', 725) # Добавления новой пары print(football_players) __________________________________________________________________ В программе представлены два цикла for, демонстрирующих способы доступа к паре «ключ — значение» в указанном словаре. В первом цикле для обращения к элементу используется индекс этого элемента в словаре. Во втором цикле применяется специальная функция items(), позволяющая извлечь из словаря ключ и значение. Для обработки только ключей можно использовать метод keys(), для обработки только значений метод value(). 7.2.7. Функции В Python функция — это часть программы, которая может быть использована несколько раз (не путать с математическими функциями). Функции позволяют разделить код программы на отдельные части и структурировать его, облегчая восприятие другими разработчиками. Особенностью функций является возможность возвращать результаты своей работы или не делать этого. Для определения новой функции используется ключевое слово def. Рассмотрим создание функций для выполнения конкретных задач. __________________________________________________________________ a = int(input()) b = int(input()) def total(n1, n2): # Функция для нахождения суммы result = n1 + n2 return result def differ(n1, n2): # Функция для нахождения разности result = n1 – n2 return result def multip(n1, n2): result = n1 * n2 return result def division(n1, n2): result = n1 / n2 return result # Функция для нахождения произведения # Функция для нахождения частного 290
print('Функция для нахождения суммы двух чисел = ', total(a, b)) print('Функция для нахождения разности двух чисел = ', differ(a, b)) print('Функция для нахождения произведения двух чисел = ', multip (a, b)) print('Функция для нахождения частного двух чисел = ', division (a, b)) __________________________________________________________________ В этой программе определены четыре функции для выполнения математических операций: сложение, вычитание, умножение и деление. Параметры функций — n1 и n2. Аргументы функций — a и b. Разница между параметрами и аргументами заключается в том, что набор параметров функции фиксирован, в то время как значения аргументов могут изменяться при каждом вызове функции. Для возвращения результата функции используется команда return. 7.2.8. Исключения try-except-finally Исключение — это событие, которое возникает во время выполнения программы. Также его называют ошибкой времени выполнения. Когда возникает такая ошибка, Python создает исключение во время выполнения, которое можно обработать, чтобы предотвратить остановку вашей программы. Блок try проверит возникновение исключения. Блок except может обработать ошибку. В блоке else, если исключения нет, то будет выполнен именно он. Блок finally всегда выполняется, независимо от того, генерируется исключение или нет. __________________________________________________________________ try: x = int(input("Введите число: ")) result = 10 / x except ZeroDivisionError: print("Вы не можете делить на нуль.") except ValueError: print("Неправильные входные данные. Введите корректные данные.") except Exception as e: print(f"Произошла ошибка: {e}") __________________________________________________________________ При программировании микрокомпьютера Raspberry Pi на Python очень часто используется конструкция для обработки исключений. Проблема заключается в том, что при программировании портов GPIO обязательно нужно отслеживать состояние портов ввода/вывода. Наличие ошибки в программе может привести к остановке работы не только программы, но и всей системы. Рекомендуется при написании программ на Python и работе c портами GPIO всегда использовать конструкцию try-except. Рассмотрим пример использования обработки исключений. 291
__________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO from time import sleep # Подключение модуля GPIO # Использование метода sleep из модуля time ledpin = 16 # пин 16 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 16 пин настраиваем на вывод # Обработка ошибок def loop(): while True: print('Светодиод включен') GPIO.output(ledpin, GPIO.HIGH) sleep(0.5) print('Светодиод выключен') GPIO.output(ledpin, GPIO.LOW) sleep(0.5) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Основная программа # Светодиод включен # Пауза длительностью 0.5 с # Светодиод выключен # Пауза длительностью 0.5 с # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ В данном примере реализована программа для мигания светодиодом с помощью портов GPIO микрокомпьютера Raspberry Pi. Для реализации основного блока создана функция loop(), которая осуществляет мигание светодиодом. Для остановки программы используется функция destroy(). Обработка исключений в данном случае связана с обработкой прерываний, которое может быть вызвано нажатием кнопки на клавиатуре. Особенностью программы является то, что после завершения программы порты GPIO будут очищены и можно заново их использовать. Если этого не сделать, то доступ к ним будет запрещен и новый запуск программы выдаст ошибку. 7.2.9. Библиотеки numpy, matplotlib, pandas В данном разделе мы изучим несколько популярных библиотек для обработки, анализа и отображения различных массивов данных. Среди них можно выделить следующие: numpy, matplotlib и pandas. Библиотеки не входят в стандартный пакет интерпретатора Python. Перед работой с ними установите их на свой компьютер. 292
Библиотека numpy — это библиотека языка Python, позволяющая обрабатывать многомерные массивы и матрицы. Библиотека обладает множеством высокоуровневых математических функций для операций над данными. Базовым объектом numpy является однородный многомерный массив (numpy.ndarray). Многомерный массив состоит из элементов одного типа (чаще всего чисел). В таблице ниже приведены некоторые атрибуты объектов ndarray. Наиболее простой способ создать массив — это использовать стандартную функцию array(). Массивы обычно создаются из списков или кортежей. __________________________________________________________________ import numpy as np a = np.array([[1, 2, 3], # Массив 3x3 из списков [1, 2, 3], [1, 2, 3]]) b = np.arange(1, 10, 1) # Массив от 1 до 10 с шагом 1 c = np.empty((3, 3)) # Массив 3x3 без заполнения d = np.eye(5) # Единичная матрица 5x5 e = np.linspace(0, 2, 9) # Массив 0–2 всего 9 значений __________________________________________________________________ Базовые операции для работы с массивами. К массивам можно применять следующие операции: арифметические, индексирования, срезов, итерирования, объединение, разбиение, копирование. Более подробную информацию о модуле numpy можно узнать на сайте разработчика по адресу: https://numpy.org/doc/. Очень часто для визуализации данных numpy используется совместно с библиотекой matplotlib. Далее мы рассмотрим возможности этого модуля. Библиотека matplotlib — это библиотека двумерной графики для языка программирования Python, позволяющая создавать рисунки различных форматов. Рассмотрим пример построения двух графиков тригонометрической функции sin(x) и вывод их на экран. __________________________________________________________________ import matplotlib.pyplot as plt import numpy as np t = np.arange(0.0, 3.0, 0.01) # Массив интервалов времени y1 = np.sin(2 * np.pi * t) # Функция y1(t) y2 = 0.1 * np.sin(4 * np.pi * t) # Функция y2(t) fig, ax = plt.subplots() # Создание новых объектов ax.plot(t, y1, t, y2) # Построение графиков ax.set(xlabel='Время (s)', ylabel='Напряжение (V)', title='Пример графика') # Установки для осей координат 293
plt.ylim((-1, 1)) plt.xlim((0, 1)) plt.legend(('sin(x)', '0.1 sin(x)')) # Ограничения по оси ординат # Ограничения по оси абсцисс # Легенда на графике ax.grid() # Добавление сетки fig.savefig('picture.png') # Сохранение графика в формате *.png plt.show() # Вывод графика на экран __________________________________________________________________ При работе с библиотекой matplotlib очень часто используется интерфейс pyplot, который позволяет пользователю существенно упростить процесс создания нового графика. В matplotlib существует строгая иерархия создания графика. В приведенном примере можно наблюдать эту последовательность. В первую очередь будет создан новый объект (Figure), потом задается область для рисования (Axes). Следующий этап — это настройка координатных осей (Axis) и создание текстовых полей. На рисунке 7.7 представлен результат выполнения программы (график функции sin(x)). На рисунке 7.8 показан амплитудный спектр сигнала, который представлен на рисунке 7.7. Теперь усложним предыдущий пример и доработаем программу для реализации Фурье-преобразования и построения спектра сигнала. __________________________________________________________________ import matplotlib.pyplot as plt import numpy as np dt = 0.001 F = 4.5 t = np.arange(0.0, 50.0, dt) y = 2 * np.sin(2 * np.pi * F * t) # Частота сигнала, Hz # Массив интервалов времени # Функция y(t) fig, ax = plt.subplots() fx = np.fft.rfft(y) / (len(t) / 2) fn = 1 / (2 * dt) # Создание новых объектов freq = np.linspace(0, fn, len(fx)) plt.plot(freq, abs(fx)) # Массив частот # Построение графиков ax.set(xlabel='Частота (Hz)', ylabel='Напряжение (V)', title='Спектр сигнала') # Установки для осей координат plt.ylim((0, 2.5)) plt.xlim((0, 10)) ax.grid() # Ограничения по оси ординат # Ограничения по оси абсцисс # Добавление сетки # Частота Найквиста fig.savefig('fft.png') # Сохранение графика в формате *.png plt.show() # Вывод графика на экран __________________________________________________________________ 294
Рис. 7.7 Графики функции sin(x) Рис. 7.8 Амплитудный спектр сигнала В заключение данного раздела остановимся на способах загрузки массивов данных в программу. Создайте новый текстовый документ, добавьте в него следующее содержимое: __________________________________________________________________ 1 1 2 4 3 9 4 16 5 25 __________________________________________________________________ 295
Сохраните документ как mass.txt. Далее рассмотрим способы загрузки этого файла в программу, написанную на языке Python. 1 способ. Без использования сторонних библиотек. Правда, ранее мы уже рассматривали этот способ, когда изучали цикл for. Программа позволяет создать список из элементов текстового файла. __________________________________________________________________ infile = open('input.txt') filen = infile.readlines() # Открытие файла # Чтение всех строк файла columns = [] # Создание пустого списка columns for f in filen: line = f.split() columns.append(line) print(columns) # # # # Построчное чтение данных Применение функции split() к строке Добавление строки к списку Вывод списка на экран infile.close() __________________________________________________________________ 2 способ. Использование библиотеки numpy. Преимуществом данного метода является то, библиотека numpy позволяет не только загрузить данные в программу, но и выполнить над ними определенные операции. __________________________________________________________________ import numpy as np mass = np.loadtxt('input.txt') print(mass.shape) mass = mass * 2 print(mass) np.savetxt('output.txt', mass, fmt = '%3.0d') __________________________________________________________________ 3 способ. Использование библиотеки pandas. Библиотека pandas — это модуль, который позволяет анализировать большие массивы данных. Особенностью библиотеки является возможность работы с разными форматами исходных файлов с данными. В данной части мы ограничимся методами загрузки файлов в программу. __________________________________________________________________ import pandas as pd import matplotlib.pyplot as plt table = pd.read_csv('data.txt', sep='\t') 296
x = table.values[:, 0] y = table.values[:, 1] fig, ax = plt.subplots() ax.plot(x, y) plt.show() __________________________________________________________________ Библиотека pandas имеет большой набор методов для анализа и обработки данных. Необходимо отметить, что данная библиотека является эффективным инструментом для работы именно с табличными данными разных форматов. Для более подробного ознакомления с возможностями данного модуля можно посетить сайт с документацией разработчика https://pandas.pydata. org/docs/ или дополнительно изучить литературу на данную тему. 7.3. Практические работы Практическая работа № 1. Подключение светодиода В данной работе предлагается изучить принцип подключения светодиода к микрокомпьютеру Raspberry Pi, используя T-cobbler переходник. Для сборки схемы потребуются следующие компоненты (и их количество). Все компоненты разбиты на два блока. Первый блок имеет набор стандартных элементов, которые содержит комплект Raspberry Pi, T-cobbler переходник и макетную плату. Второй блок компонентов может меняться в зависимости от вида практической работы. Основной блок компонентов: Комплект Raspberry Pi T-cobbler переходник Макетная плата x1 x1 x1 Дополнительный блок компонентов: Светодиод Резистор 220 Ом Проводники x1 x1 x1 297
1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 7.9. В операционной системе Raspbian микрокомпьютера Raspberry Pi откройте программу Thonny Python IDE, создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Для запуска скрипта нажмите клавишу F5 или нажмите на соответствующую кнопку на панели инструментов. Убедитесь в работоспособности схемы. Доработайте схему и программу так, чтобы устройство попеременно управляло включением и выключением двух светодиодов. 2. Схема подключения Рис. 7.9 Схема подключения светодиода 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO from time import sleep # Подключение модуля GPIO # Использование метода sleep из модуля time ledpin = 16 # пин 16 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 16 пин настраиваем на вывод # Обработка ошибок def loop(): # Основная программа while True: print('Светодиод включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен sleep(0.5) # Пауза длительностью 0,5 с print('Светодиод выключен') 298
GPIO.output(ledpin, GPIO.LOW) sleep(0.5) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Светодиод выключен # Пауза длительностью 0,5 с # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 2. Подключение кнопки В работе предлагается изучить принцип подключения кнопки к микрокомпьютеру Raspberry Pi, используя T-cobbler-переходник. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов: Светодиод Резистор 220 Ом Кнопка Проводники x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 7.10. В операционной системе Raspbian микрокомпьютера Raspberry Pi откройте программу Thonny Python IDE, создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Для запуска скрипта нажмите клавишу F5 или нажмите на соответствующую кнопку на панели инструментов. Убедитесь в работоспособности схемы. В качестве дополнительного задания необходимо добавить 1 кнопку и 2 светодиода. Первая кнопка запускает режим «бегущего огня» для светодиодов. Вторая кнопка останавливает этот режим. 299
2. Схема подключения Рис. 7.10 Схема подключения кнопки 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO ledpin = 16 btnpin = 20 # пин 16 — светодиод # пин 20 — кнопка def setup(): # Функция настройки портов GPIO.setmode(GPIO.BCM) # Установка режима GPIO.BCM GPIO.setup(ledpin, GPIO.OUT) # 16 пин настраиваем на вывод # 16 пин на ввод и подтянуть через резистор к уровню 3.3 В GPIO.setup(btnpin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен GPIO.setwarnings(False) # Обработка ошибок def loop(): # Основная программа while True: if GPIO.input(btnpin) == GPIO.LOW: # Проверка нажатия кнопки print('Светодиод включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен else: print('Светодиод выключен') GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние if __name__ == '__main__': try: # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- # Начало выполнения программы 300
setup() loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 3. Подключение зуммера Данная практическая работа является продолжением изучения портов ввода/вывода микрокомпьютера Raspberry Pi. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов: Светодиод Резистор 220 Ом Излучатель Проводники x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 7.11. В операционной системе Raspbian микрокомпьютера Raspberry Pi откройте программу Thonny Python IDE, создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Для запуска скрипта нажмите клавишу F5 или нажмите на соответствующую кнопку на панели инструментов. Убедитесь в работоспособности схемы. Для дополнительного задания реализуйте режим включения и выключения сигнализации при нажатии кнопки. Звуковой сигнал сопровождается включением светодиода. 2. Схема подключения Рис. 7.11 Схема подключения пьезоизлучателя 301
3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import time beeppin = 16 # пин 16 def setup(): GPIO.setmode(GPIO.BCM) GPIO.setup(beeppin, GPIO.OUT) GPIO.output(beeppin, GPIO.LOW) GPIO.setwarnings(False) # # # # # Функция настройки портов Установка режима GPIO.BCM 16 пин настраиваем на вывод buzzer выключен Обработка ошибок def loop(): # Основная программа while True: GPIO.output(beeppin, GPIO.HIGH) time.sleep(0.5) GPIO.output(beeppin, GPIO.LOW) time.sleep(0.5) def destroy(): GPIO.output(beeppin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # buzzer выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: setup() loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 4. Измерение напряжения Raspberry Pi является цифровым устройством. Оно не имеет собственного встроенного АЦП и очень часто для обработки аналоговых сигналов используется внешнее устройство. В работе представлена схема для подключения внешнего АЦП PCF8591 к микрокомпьютеру Raspberry Pi. Для сборки схемы потребуются следующие компоненты. Основной блок (см. практическая работа № 1). Дополнительный блок компонентов: Светодиод Резистор 220 Ом Потенциометр АЦП Проводники x1 x1 x1 x1 x1 302
1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 7.12. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. В п. 3 даны две программы (с/без библиотекой PCF8591). Запустите скрипт и убедитесь в работоспособности схемы. Доработайте программу на Python так, чтобы устройство выводило на экран результат оцифровки сигнала с четырех каналов АЦП. 2. Схема подключения Рис. 7.12 Измерение напряжения АЦП PCF8591 3. Пример программного кода Вариант программы без использования специальных библиотек. __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import smbus import time # Подключение модуля GPIO # Подключение модуля smbus для работы I2C # Подключение модуля time ledpin = 21 # пин 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Обработка ошибок address = 0x48 ch = [0x40, 0x41, 0x42, 0x43] bus = smbus.SMBus(1) # Установка адреса АЦП # Определение каналов АЦП # Выбор устройства I2C def loop(): while True: bus.write_byte(address, ch[0]) value = bus.read_byte(address) print(value) time.sleep(0.1) # Основная программа 303 # Выбор канала для чтения данных # Чтение данных # Вывод результата на экран
GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен time.sleep(0.5) # Пауза длительностью 0,5 с GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен time.sleep(0.5) # Пауза длительностью 0,5 с def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Программа с использованием библиотеки PCF8591. __________________________________________________________________ #!/usr/bin/env python import PCF8591 as ADC import RPi.GPIO as GPIO from time import sleep ledpin = 21 # Подключение модуля АЦП (8 бит) # Подключение модуля GPIO # Использование метода sleep из модуля time # GPIO 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Обработка ошибок def setup(): ADC.setup(0x48) # Функция настройки АЦП # Установка адреса АЦП def loop(): # Основная программа while True: code = ADC.read(0) # Значение с канала ch0 val = 3.3 * code / 255 print('Напряжение: {:.2f} В'.format(val)) sleep(0.1) GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен sleep(0.1) GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен sleep(0.1) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- 304
if __name__ == '__main__': # Начало выполнения программы try: setup() loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 5. Измерение температуры В работе представлена схема подключения внешнего АЦП PCF8591 к микрокомпьютеру Raspberry Pi для измерения температуры аналоговым датчиком LM35. Ниже представлен перечень компонентов. Дополнительный блок компонентов: Светодиод Резистор 220 Ом Датчик LM35 АЦП Проводники x1 x1 x1 x1 x1 1. Задание Используя радиоэлектронные компоненты, соберите схему, приведенную на рисунке 7.13. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт и убедитесь в работоспособности схемы. Измените программу и доработайте схему, которая позволяет сопровождать звуковым сигналом от пьезоизлучателя при превышении (или уменьшении) заданного критического значения температуры (значение устанавливается произвольно). 2. Схема подключения Рис. 7.13 Схема измерения температуры датчиком LM35 305
3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import PCF8591 as ADC import RPi.GPIO as GPIO from time import sleep ledpin = 21 # Подключение модуля АЦП (8 бит) # Подключение модуля GPIO # Использование метода sleep из модуля time # GPIO 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Обработка ошибок def setup(): ADC.setup(0x48) # Функция настройки АЦП # Установка адреса АЦП def loop(): # Основная программа while True: analogVal = ADC.read(0) # Значение с канала ch0 (LM35) V = 5 * float(analogVal) / 255 # Перевод в вольт temp = 1000 * V / 10 # Перевод в градусы Цельсия print('Температура = {:.2f} C'.format(temp)) sleep(1.0) GPIO.output(ledpin, GPIO.HIGH) sleep(0.1) GPIO.output(ledpin, GPIO.LOW) sleep(0.1) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Светодиод включен # Светодиод выключен # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: setup() loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 6. Измерение интенсивности света В работе представлена схема подключения внешнего АЦП PCF8591 к микрокомпьютеру Raspberry Pi для измерения интенсивности света фоторезистором. Ниже представлен перечень компонентов. 306
Дополнительный блок компонентов: Светодиод Резистор 220 Ом Фоторезистор АЦП Проводники x1 x1 x1 x1 x1 1. Задание Соберите схему, приведенную на рисунке 7.14. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт и убедитесь в работоспособности схемы. Измените программу и доработайте схему, которая позволяет сопровождать звуковым сигналом от пьезоизлучателя при изменении определенного уровня интенсивности света (значение устанавливается произвольно). 2. Схема подключения Рис. 7.14 Схема измерения интенсивности света 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import PCF8591 as ADC import RPi.GPIO as GPIO from time import sleep ledpin = 21 # Подключение модуля АЦП (8 бит) # Подключение модуля GPIO # Использование метода sleep из модуля time # GPIO 21 307
GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Обработка ошибок def setup(): ADC.setup(0x48) # Функция настройки АЦП # Установка адреса АЦП def loop(): while True: phres = ADC.read(0) sleep(0.2) # Основная программа # Чтение данных if phres > 100: # Проверка освещения print('Свет включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен else: print('Свет включен') GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: setup() loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 7. Широтно-импульсная модуляция Для Raspberry Pi есть возможность реализации широтно-импульсной модуляции программным способом. Важными показателями ШИМ являются частота импульсов и скважность. Изменение скважности, например, позволяет изменить направление вращения электродвигателя или интенсивность излучения источника света. В данной работе для демонстрации изменения скважности используется светодиод. Ниже представлен перечень компонентов для схемы. Дополнительный блок компонентов: Светодиод Резистор 220 Ом Проводники x1 x1 x1 308
1. Задание Соберите схему, приведенную на рисунке 7.15. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт и убедитесь в работоспособности схемы. Для управления циклом изменения скважности добавьте 2 кнопки. Нажатие первой кнопки активирует режим увеличения скважности. Нажатие второй кнопки активирует режим уменьшения скважности. 2. Схема подключения Рис. 7.15 Схема для изучения широтно-импульсной модуляции 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import time # Подключение модуля GPIO # Подключение модуля time ledpin = 16 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) GPIO.setwarnings(False) pwm = GPIO.PWM(ledpin, 1000) pwm.start(0) # Установка режима GPIO.BCM # 16 пин настраиваем на вывод # Обработка ошибок # Установка частоты ШИМ — 1 KHz # Скважность = 0 def loop(): while True: for DC in range(0, 101, 4): pwm.ChangeDutyCycle(DC) time.sleep(0.1) time.sleep(1) for DC in range(100, -1, -4): 309 # Основная программа # Изменение скважности (%): 0–100 # Изменить скважность # Изменение скважности (%): 100–0
pwm.ChangeDutyCycle(DC) time.sleep(0.1) time.sleep(1) # Изменить скважность def destroy(): pwm.stop() GPIO.cleanup() ние # Функция очистки портов # Остановка ШИМ # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 8. Подключение сервопривода К выводам Raspberry Pi можно подключать различные двигатели: электродвигатель, сервопривод и шаговый двигатель. Прямое подключение двигателей может привести к выгоранию портов или нехватке тока. Очень важно использовать специальные драйверы управления. В случае сервопривода допустимо использовать схемы без драйвера. В практической работе рассматривается управление сервоприводом скриптами Python. Ниже представлен перечень компонентов для схемы. Дополнительный блок компонентов: Сервопривод Проводники x1 x1 1. Задание Соберите схему, приведенную на рисунке 7.16. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт и убедитесь в работоспособности схемы. Программа автоматически изменяет угол поворота сервопривода. Измените программу и добавьте в схему кнопку, которая изменит автоматический режим на ручной. 310
2. Схема подключения Рис. 7.16 Схема подключения сервопривода 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import time # Подключение модуля GPIO # Подключение модуля time spin = 17 # пин 17 используется для PWM Freq = 50 # Частота ШИМ # Длительность одного импульса (1/Freq) T = 20 мс imp_dc = # 0.5 мс # 1.5 мс # 2.5 мс [2.5, 5.0, 7.5, -> (0.5/20)*100 -> (1.5/20)*100 -> (2.5/20)*100 10.0, 12.5] # Скважность в % = 2.5% -> 0 градусов = 7.5% -> 90 градусов = 12.5% -> 180 градусов GPIO.setmode(GPIO.BCM) GPIO.setup(spin, GPIO.OUT) GPIO.output(spin, GPIO.LOW) pwm = GPIO.PWM(spin, Freq) pwm.start(7.5) # Установка режима GPIO.BCM # 17 пин настраиваем на вывод # Установка частоты ШИМ – 50 Hz # Скважность = 7.5% def loop(): while True: pwm.ChangeDutyCycle(imp_dc[0]) time.sleep(1.0) pwm.ChangeDutyCycle(imp_dc[1]) time.sleep(1.0) 311 # Основная программа # Угол 0 градусов # Угол 45 градусов
pwm.ChangeDutyCycle(imp_dc[2]) time.sleep(1.0) pwm.ChangeDutyCycle(imp_dc[3]) time.sleep(1.0) pwm.ChangeDutyCycle(imp_dc[4]) time.sleep(1.0) def destroy(): pwm.stop() GPIO.cleanup() ние # Угол 90 градусов # Угол 135 градусов # Угол 180 градусов # Функция очистки портов # Остановка ШИМ # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 9. Подключение шагового двигателя В случае шагового двигателя необходимо использовать специальный драйвер. В практической работе рассматривается управление шаговым двигателем скриптами Python. Ниже представлен перечень компонентов для схемы. Дополнительный блок компонентов: Шаговый двигатель Драйвер ULN2003 Проводники x1 x1 x1 1. Задание Соберите схему, приведенную на рисунке 7.17. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт и убедитесь в работоспособности схемы. Программа автоматически изменяет положение шагового двигателя. Измените программу и добавьте в схему кнопку, которая изменит автоматический режим на ручной. Нажатие кнопки однократно изменяет положение шагового двигателя. 312
2. Схема подключения Рис. 7.17 Схема подключения шагового двигателя 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO # Подключение модуля GPIO import time # Подключение модуля time delay = 0.005 pause = 0.5 steps = 500 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) # Временная задержка 5 мс # Временная задержка 500 мс # Число шагов # Установка режима GPIO.BCM # Обработка ошибок # Определение GPIO выводов для IN1-4 (uln2003) coil_N_1_pin = 16 # GPIO 16 coil_N_2_pin = 19 # GPIO 19 coil_N_3_pin = 20 # GPIO 20 coil_N_4_pin = 26 # GPIO 26 # Настройка GPIO на вывод GPIO.setup(coil_N_1_pin, GPIO.OUT) GPIO.setup(coil_N_2_pin, GPIO.OUT) GPIO.setup(coil_N_3_pin, GPIO.OUT) GPIO.setup(coil_N_4_pin, GPIO.OUT) # Функция для определения шага def setStep(n1, n2, n3, n4): GPIO.output(coil_N_1_pin, n1) 313
GPIO.output(coil_N_2_pin, n2) GPIO.output(coil_N_3_pin, n3) GPIO.output(coil_N_4_pin, n4) # Функция для определения вращения def move(): # Шаговый режим прямой for i in range(0, steps): setStep(1,0,0,0) time.sleep(delay) setStep(0,1,0,0) time.sleep(delay) setStep(0,0,1,0) time.sleep(delay) setStep(0,0,0,1) time.sleep(delay) print('Вращение по часовой стрелке') # Шаговый режим реверсный for i in range(0, steps): setStep(0,0,0,1) time.sleep(delay) setStep(0,0,1,0) time.sleep(delay) setStep(0,1,0,0) time.sleep(delay) setStep(1,0,0,0) time.sleep(delay) print('Вращение против часовой стрелки') def destroy(): GPIO.cleanup() # Функция очистки портов # Возврат пинов в исходное состояние def loop(): while True: move() time.sleep(pause) # Основная программа # Пауза длительностью 0,5 с if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 10. Последовательная связь (UART) Последовательная передача UART используется для обмена данными между устройствами. Можно реализовать обмен между Raspberry Pi и другими устройствами, например, микроконтроллер или контроллер Arduino, поддерживающими последовательную передачу. Для Raspberry Pi 2 B+ или версией выше 314
необходимо добавить пользователя root в группу dialout (из tty). Иначе доступ к интерфейсу будет запрещен. __________________________________________________________________ # Проверка пользователей группы groups root # Добавление пользователя root в группу dialout sudo usermod -aG dialout root (может быть pi, для любого пользователя $USER) newgrp dialout # Отключаем автоматический запуск сервиса serial-getty # Для Raspberry Pi 2 sudo systemctl mask serial-getty@ttyAMA0.service # Для Raspberry Pi 4 sudo systemctl mask serial-getty@ttyS0.service # Проверка доступа к устройству ls -l /dev/tty* # Для включения serial port sudo raspi-config # Interface Options → Serial Port → Enable __________________________________________________________________ В случае Raspberry Pi 4 необходимо использовать порт “/dev/ttyS0”. После добавления пользователя в группу необходимо активировать последовательный порт (используем raspi-config или интерфейс Raspbian). Схема подключения Arduino nano и Raspberry (Pi 2 B v. 1.1). Необходимо учитывать разные уровни напряжения при соединении выводов последовательного порта Arduino и Raspberry Pi. Чтобы не использовать специальных микросхем и делитель напряжения, можно использовать питание Arduino от pin 1 (3,3 В) микрокомпьютера Raspberry Pi по следующей схеме: Arduino nano Raspberry Pi 3.3 V 3.3 V (pin 1) GND GND (pin 6) RX0 TX (pin 8) TX0 RX (pin 10) 315
Дополнительный блок компонентов: Светодиод Резистор 220 Ом x1 x1 Arduino nano Проводники x1 x1 1. Задание В программе Arduino IDE создайте новый проект и запишите в него программу, приведенную в п. 3. Загрузите в память микроконтроллера Arduino новую программу. Соберите схему, приведенную на рисунке 7.18. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт на python и убедитесь в работоспособности схемы. 2. Схема подключения Рис. 7.18 Схема соединения Raspberry Pi и Arduino nano (UART) 3. Пример программного кода Программа для Raspberry Pi. __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import serial import time import os ledpin = 21 # # # # Подключение модуля GPIO Подключение модуля serial Подключение модуля time Модуль работы с операционной системой # пин 21 316
GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Настройка serial порта Raspberry Pi 2 через AMA0 # Настройка serial порта Raspberry Pi 4 через S0 ser = serial.Serial("/dev/ttyAMA0", 9600) def loop(): while True: num = ser.readline() num = int(num) print(num) # Основная программа # Чтение данных из порта # byte -> int if num == 1: # Проверка освещения print('Свет включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен # time.sleep(0.5) elif num == 2: print('Свет выключен') GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен # time.sleep(0.5) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Программа для Arduino nano. __________________________________________________________________ int num_1 = 1; int num_2 = 2; void setup() { Serial.begin(9600); } // Определение переменной num_1 // Определение переменной num_2 // Инициализация Serial (9600 bps) void loop() { Serial.println(num_1); // Передача num_1 по Serial delay(500); // Пауза 0,5 с Serial.println(num_2); // Передача num_2 по Serial delay(500); // Пауза 0,5 с } __________________________________________________________________ 317
Практическая работа № 11. Исследование интерфейса I2C В практической работе рассматривается пример использования интерфейса I2C для обмена данными между устройствами. Реализован обмен данными между Raspberry Pi и контроллером Arduino nano, который оцифровывает показания аналогового температурного датчика LM35. Для подключения и настройки Raspberry Pi 2 B+ необходимо выполнить несколько команд. Прежде всего, через утилиту Software Configuration Tool убедитесь, что интерфейс I2C активирован. Если нужные пакеты для работы с периферийными устройствами недоступны, то их следует установить. __________________________________________________________________ ls /dev | grep i2c // Поиск устройств на шине I2C sudo apt-get update // Обновление пакетов sudo apt-get install i2c-tools // Установка пакета i2c-tools sudo apt-get install python-smbus // Установка пакета smbus для RP PI 2 sudo apt-get install python3–smbus2 // Установка пакета smbus для RP PI 4 sudo i2cdetect -y 1 // Определение адреса устройства __________________________________________________________________ Схема подключения Arduino nano и Raspberry (Pi 2 B v. 1.1). Необходимо учитывать разные уровни напряжения при соединении выводов последовательного порта Arduino и Raspberry Pi. Чтобы не использовать специальных микросхем и делитель напряжения, можно использовать питание Arduino от pin 1 (5 В) микрокомпьютера Raspberry Pi по следующей схеме: Arduino nano Raspberry Pi 5V 5 V (pin 4) GND GND (pin 6) SDA (A4) SDA (pin 3) SCL (A5) SCL (pin 5) Дополнительный блок компонентов: Датчик LM35 x1 Arduino nano Проводники x1 318 x1
1. Задание В программе Arduino IDE создайте новый проект и запишите в него программу, приведенную в п. 3. Загрузите в память микроконтроллера Arduino новую программу. Соберите схему, приведенную на рисунке 7.19. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу из п. 3. Запустите скрипт на python и убедитесь в работоспособности схемы. 2. Схема подключения Рис. 7.19 Схема соединения Raspberry Pi и Arduino nano (I2C) 3. Пример программного кода Программа для Raspberry Pi 2. __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import smbus smbus2) from time import sleep import os bus = smbus.SMBus(1) address = 0x48 # Подключение модуля GPIO # Подключение модуля smbus (для RP PI4 – # Использование метода sleep из модуля time # Модуль работы с операционной системой # Установка адреса устройства # Выбор адреса устройства I2C def read_data(): # Функция чтения данных reading = float(bus.read_byte(address)) print(reading) def write_data(): # Функция записи данных bus.write_byte(address, ord('l')) def loop(): while True: # Основная программа 319
print('Получаем данные по i2c') read_data() sleep(0.5) # Пауза длительностью 0,5 с print('Отправляем данные по i2c') write_data() sleep(0.5) # Пауза длительностью 0,5 с def destroy(): GPIO.cleanup() ние # Функция очистки портов # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Программа для Raspberry Pi 4. __________________________________________________________________ #!/usr/bin/env python3 import smbus2 import time i2c_bus = 1 address = 0x48 # Должен совпадать с адресом в Arduino def read_temperature(): try: bus = smbus2.SMBus(i2c_bus) temp = bus.read_byte(address) bus.close() return temp except Exception as e: print(f"Ошибка: {e}") return None while True: temp = read_temperature() if temp is not None: print(f"Температура: {temp}°C") time.sleep(1) __________________________________________________________________ Программа для Arduino nano. __________________________________________________________________ #include <Wire.h> #define REPLICA_ADDRESS 0x48 // Адрес I2C (используем #define для констант) 320
const int ledPin = 13; boolean ledOn = false; void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Wire.begin(REPLICA_ADDRESS); // Инициализация как replica Wire.onRequest(requestEvent); // Регистрация обработчика запросов Serial.println("I2C Replica готов, адрес 0x48"); } void loop() { // Основные процедуры можно выполнять здесь delay(1000); } // Функция, вызываемая, когда Main запрашивает данные void requestEvent() { int val = analogRead(A0); byte temp = (val * 5.0 / 1024) * 100; Serial.print("Отправляю температуру: "); Serial.println(temp); Wire.write(temp); // Отправка одного байта digitalWrite(ledPin, ledOn = !ledOn); // Индикация передачи } __________________________________________________________________ Практическая работа № 12. Исследование интерфейса SPI В работе рассмотрен пример использования интерфейса SPI для обмена данными между устройствами. Реализован обмен данными между Raspberry Pi и контроллером Arduino nano. Для подключения и настройки Raspberry Pi 2 B+ необходимо выполнить несколько команд. Прежде всего, через утилиту Software Configuration Tool убедитесь, что интерфейс SPI активирован. Если нужные пакеты для работы с периферийными устройствами недоступны, то их следует установить. Используйте следующую схему подключения устройств: Arduino nano Raspberry Pi 5V 5 V (pin 4) GND GND (pin 6) MOSI (D11) SPI_MOSI (pin 19) MISO (D12) SPI_MISO (pin 21) SCK (D13) SPI_CLK (pin 23) 321
Дополнительный блок компонентов: Arduino nano Проводники x1 x1 1. Задание В программе Arduino IDE создайте новый проект и запишите в него программу, приведенную в п. 3. Загрузите в память микроконтроллера Arduino новую программу. Соберите схему, приведенную на рисунке 7.20. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу из п. 3. Запустите скрипт на python и убедитесь в работоспособности схемы. 2. Схема подключения Рис. 7.20 Схема соединения Raspberry Pi и Arduino nano (SPI) 3. Пример программного кода Программа для Raspberry Pi. __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import spidev import time import os # # # # spi = spidev.SpiDev() spi.open(0,0) spi.max_speed_hz = 15200 # Инициализация SPI # Запуск dev = 0 # Скорость передачи 15.2 kHz Подключение модуля GPIO Подключение модуля smbus для работы SPI Подключение модуля time Модуль работы с операционной системой 322
def loop(): # while True: send = [0x01] # spi.xfer(send) time.sleep(1.0) send = [0x02] # spi.xfer(send) time.sleep(1.0) # Для чтения данных resp def destroy(): spi.close() GPIO.cleanup() Основная программа Отправка байта 0x01 по SPI Отправка байта 0x02 по SPI = spi.readbytes(5) # Функция очистки портов # Остановка dev = 0 # Возврат пинов в исходное состояние if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Программа для Arduino nano. __________________________________________________________________ // Определяем пины SPI #define SDI_PIN 11 #define SDO_PIN 12 #define SCK_PIN 13 #define CS_PIN 10 #define LED_PIN 6 // Определяем переменную для получаемого байта byte recievedByte; void setup() { // Обнуляем регистр управления SPI SPCR = B00000000; // Разрешаем работу SPI SPCR = (1<<SPE); // Инициализируем последовательное соединение Serial.begin(9600); //определяем пины для работы с SPI pinMode(SDI_PIN, INPUT); pinMode(SDO_PIN, OUTPUT); pinMode(SCK_PIN, INPUT); pinMode(CS_PIN, INPUT); } void loop() { // Пока replica select имеет низкий уровень while (digitalRead(CS_PIN)==LOW){ 323
// Принимаем байт и записываем его в переменную recievedByte=spi_receive(); // Считывает отправленный байт Serial.println(recievedByte,DEC); if (recievedByte == 0x01) { digitalWrite(LED_PIN, HIGH); } if (recievedByte == 0x02) { digitalWrite(LED_PIN, LOW); } } } // Функция для приема байта byte spi_receive() { // Пока не выставлен флаг окончания передачи, принимаем биты while (!(SPSR & (1<<SPIF))){}; // Возвращаем содержимое регистра данных SPI return SPDR; } __________________________________________________________________ Практическая работа № 13. Сопряжение Arduino и Raspberry Pi Последовательная передача UART используется для обмена данными между Raspberry Pi и Arduino nano. Передача данных осуществляется через USB-подключение по следующей схеме: Arduino nano Raspberry Pi Mini-USB USB Дополнительный блок компонентов: Светодиод Резистор 220 Ом x1 x1 Arduino nano Проводники x1 x1 1. Задание В Arduino IDE создайте новый проект и запишите в него программу, которая принимает данные по последовательному порту. Загрузите в память микроконтроллера Arduino новую программу. Соберите схему, приведенную на ри324
сунке 7.21. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт на python и убедитесь в работоспособности схемы. 2. Схема подключения Рис. 7.21 Схема соединения Raspberry Pi и Arduino nano (UART через USB) 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import serial import time ledpin = 21 # Подключение модуля GPIO # Подключение модуля serial # Подключение модуля time # пин 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Настройка serial порта через USB ser = serial.Serial("/dev/ttyUSB1", 9600) # или USB0 num_1 = [0x01] num_2 = [0x02] def loop(): # Основная программа while True: ser.write(num_1) # Запись данных в порт print('Свет включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен time.sleep(0.5) ser.write(num_2) print('Свет выключен') GPIO.output(ledpin, GPIO.LOW) time.sleep(0.5) 325 # Запись данных в порт # Светодиод выключен
def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 14. Построение системы контроля освещенности Последовательная передача UART используется для обмена данными между Raspberry Pi и Arduino nano. Для Raspberry Pi 2 B+ необходимо добавить пользователя root в группу dialout (из tty). Иначе доступ к интерфейсу будет запрещен. Если используется Raspberry Pi 4, то настройку устройства можно посмотреть в практической работе № 10. __________________________________________________________________ sudo systemctl mask serial-getty@ttyAMA0.service __________________________________________________________________ Схема подключения Arduino nano и Raspberry (Pi 2 B v. 1.1). Необходимо учитывать разные уровни напряжения при соединении выводов последовательного порта Arduino и Raspberry Pi. Чтобы не использовать специальных микросхем и делитель напряжения, можно использовать питание Arduino от pin 1 (3,3 В) микрокомпьютера Raspberry Pi по следующей схеме: Arduino nano Raspberry Pi 3,3 V 3,3 V (pin 1) GND GND (pin 6) RX0 TX (pin 8) TX0 RX (pin 10) Дополнительный блок компонентов: Светодиод Фоторезистор x1 x1 Резистор 220 Ом x1 326 Arduino nano Проводники x1 x1
1. Задание В программе Arduino IDE создайте новый проект и запишите в него программу, которая оцифровывает сигнал от датчика освещенности и передает код по последовательному интерфейсу UART. Загрузите в память микроконтроллера Arduino новую программу. Соберите схему, приведенную на рисунке 7.22. В программе Thonny Python IDE создайте новый файл с расширением *.py и запишите в него программу, приведенную в п. 3. Запустите скрипт на python и убедитесь в работоспособности схемы. 2. Схема подключения Рис. 7.22 Схема соединения Raspberry Pi и Arduino nano (UART) 3. Пример программного кода __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import serial import time ledpin = 21 # Подключение модуля GPIO # Подключение модуля serial # Подключение модуля time # пин 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Настройка serial порта Raspberry Pi 2 через AMA0 # Настройка serial порта Raspberry Pi 4 через S0 ser = serial.Serial( # Настройка serial порта port='/dev/ttyACM0', baudrate = 9600, timeout=1 ) 327
def loop(): while True: phres = ser.readline() phres = int(phres) print(phres) # Основная программа # Чтение данных из порта # byte -> int if phres > 100: # Проверка освещения print('Свет включен') GPIO.output(ledpin, GPIO.HIGH) # Светодиод включен time.sleep(0.5) print('Свет выключен') GPIO.output(ledpin, GPIO.LOW) # Светодиод выключен time.sleep(0.5) def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Практическая работа № 15. Система температурного контроля Для передачи данных используется последовательный интерфейс UART. Arduino считывает показания аналогового датчика LM35, оцифровывает их и передает Raspberry Pi. Схема подключения: Arduino nano Raspberry Pi Mini-USB USB Дополнительный блок компонентов: Светодиод Резистор 220 Ом Датчик LM35 x1 x1 x1 Arduino nano Проводники x1 x1 1. Задание В Arduino IDE создайте новый проект и запишите в него программу, которая отправляет данные по UART (см. п. 3). Загрузите программу в память. 328
Соберите схему, приведенную на рисунке 7.23. По п. 3 создайте новый скрипт на Python. Запустите скрипт. 2. Схема подключения Рис. 7.23 Схема соединения Raspberry Pi и Arduino nano для измерения температуры 3. Пример программного кода Программа для Raspberry Pi. __________________________________________________________________ #!/usr/bin/env python import RPi.GPIO as GPIO import requests import serial from time import sleep # # # # Подключение модуля GPIO Модуль для работы с http Подключение модуля serial Использование метода sleep bp модуля time temp = 0 none = 'none' ledpin = 21 # GPIO 21 GPIO.setmode(GPIO.BCM) GPIO.setup(ledpin, GPIO.OUT) # Установка режима GPIO.BCM # 21 пин настраиваем на вывод # Настройка serial порта через USB ser = serial.Serial("/dev/ttyUSB0", 9600) def loop(): while True: temp = ser.readline() #temp = int(temp) print(temp) # Основная программа # Чтение данных из порта # byte -> int 329
# Отправка данных на сервер по http payload = {'voltage_1': temp, 'voltage_2': none} r = requests.get('http://elteha.ru/temp/temp.php', params=payload) print('Данные отправлены') GPIO.output(ledpin, GPIO.HIGH) sleep(0.1) GPIO.output(ledpin, GPIO.LOW) sleep(0.1) # # # # sleep(10.0) # Пауза длительностью 10 с def destroy(): GPIO.output(ledpin, GPIO.LOW) GPIO.cleanup() ние Светодиод включен Пауза длительностью 0,1 с Светодиод выключен Пауза длительностью 0,1 с # Функция очистки портов # Светодиод выключен # Возврат пинов в исходное состоя- if __name__ == '__main__': # Начало выполнения программы try: loop() except KeyboardInterrupt: # Прерывание при нажатии 'Ctrl+C' destroy() __________________________________________________________________ Программа для Arduino nano. __________________________________________________________________ int ledPin = 13; boolean ledOn = false; void setup(){ Serial.begin(9600); } // Инициализация Serial (9600 bps) void loop(){ int val = analogRead(A0); // Чтение данных с датчика LM35 float temp = (val*5.0/1024)*100; Serial.println(temp); delay(1000); } __________________________________________________________________ 330
Примечание. Для проверки передачи данных необходимо в браузере перейти по адресу http://elteha.ru/temp/temp.php и убедиться, что значение температуры отображается корректно. Практическая работа № 16. Создание Telegram-бота При выполнении данной практической работы можно использовать программы и схемы из практической работы № 15. Можно использовать собственные решения. Для создания нового Telegram-бота его необходим зарегистрировать в Telegram (для приложения на ПК с ОС Windows 11). Перейдите в программу и найдите его по нику @BotFather. На рисунке 7.24 показано главное окно программы. Рис. 7.24 Создание нового бота в Telegram Для создания нового бота используем команды, которые предлагают в справке. Используем команду /newbot. Далее указываем имя бота (в нашем случае bot_weather) и его название в системе (в нашем случае weather_64_bot). Если название оригинальное, то система сообщит об успешном создании нового бота. Важно сохранить токен, благодаря которому будет происходить общение с ботом. 1. Задание По п. 2 создайте новый скрипт на Python. Запустите скрипт. Убедитесь, что программа работает без ошибок. Проверьте работоспособность программы, используя специальные команды. В нашем случае для запроса используется команда /info. В программе выполняется запрос на сайт openweathermap.org и получение информации о погоде в г. Саратове. Далее выполняется парсинг 331
полученного ответа от сервера, извлечение информации о температуре и влажности, которая будет отображена в окне Telegram соответствующего бота. На рисунке 7.25 показан пример работы бота. Рис. 7.25 Создание нового бота в Telegram 2. Пример программного кода Программа для Raspberry Pi. __________________________________________________________________ #!/usr/bin/env python import requests import json import telebot TOKEN = "5092503565:AAEq7k_RuWOK8OZsphj91UnlDpq8ZjE6XFM" bot = telebot.TeleBot(TOKEN) BASE_URL = 'http://api.openweathermap.org/data/2.5/weather' s_city = 'Saratov, RU' appid = 'e9e0185f6cdf9bcb75dd543cb70738d7' params = {'q': s_city, 'units': 'metric', 'APPID': appid} response = requests.get(BASE_URL, params = params) response_parsed = json.loads(response.text) 332
temp = response_parsed['main']['temp'] humidity = response_parsed['main']['humidity'] @bot.message_handler(commands=['info']) def send_message(message): bot.send_message(message.chat.id, f"Привет, {message.chat.username}.") bot.send_message(message.chat.id, f"Информация о погоде в г.Саратове") bot.send_message(message.chat.id, f"Погода в Саратове: температура t = {temp} градусов, влажность H = {humidity}%") # Запуск бота print("Бот запущен...") bot.polling(none_stop=True) __________________________________________________________________ 3. Дополнительное задание Используя схемы и программы из практической работы № 15, реализуйте систему температурного анализа. Телеграм-бот должен по запросу (команду выбираем произвольно, например, /info) показывать значение температуры, которое Raspberry получает от Arduino. Дополнительно можно реализовать схему управления светодиодами через данного бота. Достаточно использовать 3 светодиода. Управление светодиодами выполняется командами /led_n_on и /led_n_off, где n — номер светодиода. __________________________________________________________________ #!/usr/bin/env python import telebot import RPi.GPIO as GPIO # Настройка GPIO LED_PIN = 17 # GPIO 17 GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN, GPIO.OUT) # Токен вашего бота TOKEN = "5092503565:AAEq7k_RuWOK8OZsphj91UnlDpq8ZjE6XFM" # Создание объекта бота bot = telebot.TeleBot(TOKEN) # Команда /start @bot.message_handler(commands=['start']) def send_welcome(message): bot.reply_to(message, "Команды:\n/on — включить\n/off — выключить") # Команда /on — включить светодиод 333
@bot.message_handler(commands=['on']) def turn_on(message): GPIO.output(LED_PIN, GPIO.HIGH) bot.reply_to(message, "Светодиод включен! 🔴") # Команда /off — выключить светодиод @bot.message_handler(commands=['off']) def turn_off(message): GPIO.output(LED_PIN, GPIO.LOW) bot.reply_to(message, "Светодиод выключен! ⚪") # Запуск бота print("Бот запущен...") bot.polling() __________________________________________________________________ Для включения/выключения светодиодов можно использовать кнопки. При использовании кнопок нужно будет добавить следующую часть программы. __________________________________________________________________ #!/usr/bin/env python from telebot import types # Добавьте этот код после создания бота @bot.message_handler(commands=['menu']) def show_menu(message): markup = types.ReplyKeyboardMarkup(row_width=2) btn_on = types.KeyboardButton('/on') btn_off = types.KeyboardButton('/off') markup.add(btn_on, btn_off) bot.send_message(message.chat.id, "Действие: ", reply_markup=markup) __________________________________________________________________ 334
ЗАКЛЮЧЕНИЕ Данное пособие позволяет получить фундаментальные знания в области цифровой электроники и микропроцессорных систем. Оно позволяет последовательно изучить основные понятия и определения электроники, цифровой и аналоговой схемотехники. Изучение архитектуры процессоров и микропроцессорных систем позволяет понять базовые принципы функционирования подобных систем. Важным аспектом курса является возможность освоения новых перспективных технологий. На данный момент можно уже выделить несколько областей, которые будут активно развиваться. Например, использование нейроморфных процессоров (Intel Loihi, IBM TrueNorth), которые способны имитировать работу головного мозга. Системы будут полезны для реализации высоконагруженных машинных алгоритмов. Перспективным является изучение специальных AI-чипов (TPU от Google, NVIDIA Jetson, AMD XDNA), способных выполнять аналогичные работы. В области квантовой электроники будут созданы процессоры, которые принципиально отличаются от современных вычислительных архитектур. Уже сейчас известны чипы IBM Quantum, Google Sycamore, которые способны выполнять широкий круг задач, в том числе задачу оптимизации и криптографию. Особое внимание заслуживают разработки в области оптической электроники, например, Lightmatter, Ayar Labs, где специалистам удалось разработать фотонный чип, повышающий скорость передачи информации и снижающий энергопотребление. Параллельно с развитием крупных коммерческих компаний существуют команды, которые способны реализовать открытые проекты. Речь прежде всего о микропроцессорах RISC-V с открытой архитектурой. Подобные системы все больше становятся популярными среди специалистов данной области. Если говорить про развитие микроконтроллеров, то здесь необходимо отметить ESP32, Nordic nRF, STM32 ULP устройства. Данные устройства имеют расширенный функционал, но, по сравнению с существующими аналогами, обладают ультранизким энергопотреблением. Важным считается развитие новых технологий проектирования процессоров. Среди подобных можно выделить 3D-интеграцию и чиплеты. Технология 3D-стекинга чипов (TSMC SoIC, Intel Foveros) позволяет увеличить плотность транзисторов и снизить задержки, а чиплет-технология (AMD 3D VCache, NVIDIA Grace) позволяет создавать модульные вычислительные блоки. Напоследок отметим использование так называемых систем биоэлектроники и нейроинтерфейсов. Уже сегодня (Neuralink, Synchron) существуют устройства, которые позволяют силой мысли управлять другими системами. Если подводить небольшой итог, то можно сказать, что будущее электроники за энергоэффективными, интеллектуальными и гибкими решениями, объединяющими AI, квантовые технологии и новые материалы. 335
ДОПОЛНИТЕЛЬНАЯ ЛИТЕРАТУРА Основы электроники 1. Хоровиц, П. Искусство схемотехники: в 3 т. / П. Хоровиц, У. Хилл; пер. с англ. — 7-е изд. — М. : ДМК Пресс, 2022. — Т. 1. — 704 с. 2. Платт, Ч. Электроника для начинающих / Ч. Платт; пер. с англ. — М. : БХВ-Петербург, 2017. — 352 с. 3. Уэйкерли, Дж. Ф. Основы цифровой электроники / Дж. Ф. Уэйкерли; пер. с англ. — М. : Техносфера, 2006. — 480 с. 4. Панфилов, О. А. Электроника. Полный курс: учеб. / О. А. Панфилов. — М. : Лань, 2019. — 512 с. 5. Гаврилов, С. А. Современная электроника: от азов до практического применения. — М. : ДМК Пресс, 2022. — 412 с. 6. Бессонов, В. В. Основы электроники и микропроцессорной техники: учеб. — СПб. : БХВ-Петербург, 2023. — 480 с. 7. Монк, С. Практическая электроника: иллюстрированное руководство / С. Монк; пер. с англ. — М. : Эксмо, 2021. — 336 с. 8. Тюрин, Н. И. Основы аналоговой и цифровой электроники. — М. : Техносфера, 2023. — 298 с. 9. Кузьминов, А. Ю. Электроника и схемотехника: учеб. пособие для вузов. — М. : Юрайт, 2022. — 543 с. 10. Марченко, А. Л. Основы электроники: учеб. пособие для вузов. — Litres, 2022. — 215 с. Аналоговая схемотехника 11. Титце, У. Полупроводниковая схемотехника: справочное руководство / У. Титце, К. Шенк; пер. с нем. — 12-е изд. — М. : ДМК Пресс, 2014. — 942 с. 12. Грей, П. Р. Анализ и проектирование аналоговых интегральных схем / П. Р. Грей, П. Дж. Херст, С. Г. Льюис, Р. Г. Мейер; пер. с англ. — 5-е изд. — М. : Бином, 2017. — 944 с. 13. Седра, А. Микроэлектроника: в 2 т. / А. Седра, К. Смит; пер. с англ. — М. : Техносфера, 2007. — Т. 1. Аналоговая схемотехника. — 656 с. 14. Джонс, М. Х. Аналоговая электроника от основ до проектирования / М. Х. Джонс; пер. с англ. — М. : Техносфера, 2012. — 480 с. 15. Миллер, Г. Аналоговые интегральные схемы — проектирование и применение / Г. Миллер; пер. с англ. — М. : Мир, 1991. — 288 с. 16. Франк, Д. Аналоговые фильтры: проектирование и реализация / Д. Франк, Р. Шимански; пер. с англ. — М. : Техносфера, 2015. — 368 с. 17. Лансбург, Р. Аналоговая электроника: принципы и практика / Р. Лансбург; пер. с англ. — М. : ДМК Пресс, 2019. — 416 с. 18. Кауфман, А. Н. Аналоговая схемотехника: учеб. пособие / А. Н. Кауфман. — М. : Высшая школа, 2016. — 304 с. 336
19. Ромаш, Э. М. Аналоговые устройства на операционных усилителях / Э. М. Ромаш. — М. : Радио и связь, 2003. — 256 с. 20. Уильямс, А. Аналоговая схемотехника — проектирование и моделирование / А. Уильямс; пер. с англ. — М. : Техносфера, 2018. — 400 с. Цифровая схемотехника 21. Уэйкерли, Дж. Ф. Проектирование цифровых устройств в 2 т. / Дж. Ф. Уэйкерли; пер. с англ. — М. : Техносфера, 2012. — Т. 1. Основы цифровой схемотехники. — 480 с. 22. Новиков, Ю. В. Основы цифровой схемотехники: учеб. пособие / Ю. В. Новиков. — М. : Интернет-Ун-т Информационных Технологий, 2015. — 352 с. 23. Антонов, А. П. Цифровая схемотехника: учеб. пособие / А. П. Антонов. — М. : Лань, 2019. — 288 с. 24. Баранов, С. И. Основы цифровой схемотехники: учеб. / С. И. Баранов. — М. : Бином, 2015. — 416 с. 25. Кейт, Дж. Современная цифровая схемотехника / Дж. Кейт; пер. с англ. — М. : Техносфера, 2017. — 448 с. 26. Преснухин, Л. Н. Цифровая схемотехника: учеб. для вузов / Л. Н. Преснухин. — М. : Академия, 2014. — 384 с. 27. Гуров, В. В. Основы цифровой электроники: учеб. пособие / В. В. Гуров. — М. : Физматлит, 2013. — 320 с. 28. Стешенко, В. Б. ПЛИС фирмы Xilinx: основы цифровой схемотехники / В. Б. Стешенко. — М. : ДМК Пресс, 2012. — 256 с. 29. Петров, И. В. Цифровая схемотехника: практическое руководство / И. В. Петров. — М. : ДМК Пресс, 2018. — 272 с. 30. Романов, А. Ю. Цифровая электроника от основ до создания устройств / А. Ю. Романов. — М. : Техносфера, 2016. — 304 с. Основы микропроцессорных систем 31. Бродин, В. Б. Микропроцессорные системы: учеб. пособие / В. Б. Бродин. — М. : Форум, 2015. — 320 с. 32. Гук, М. А. Микропроцессоры и микроконтроллеры: учеб. / М. А. Гук. — СПб. : Питер, 2016. — 512 с. 33. Сташин, В. В. Основы микропроцессорной техники: учеб. пособие / В. В. Сташин. — М. : ДМК Пресс, 2017. — 288 с. 34. Новиков, Ю. В. Архитектура микропроцессорных систем: учеб. пособие / Ю. В. Новиков. — М. : Интернет-Ун-т Информационных Технологий, 2014. — 352 с. 35. Балашов, Е. П. Микропроцессоры и микроконтроллеры: учеб. / Е. П. Балашов, Д. В. Пузанков. — М. : Лань, 2018. — 416 с. 36. Авдеев, В. А. Микропроцессорные системы: основы проектирования / В. А. Авдеев. — М. : Техносфера, 2019. — 304 с. 37. Келим, Ю. М. Микропроцессорные системы: учеб. пособие / Ю. М. Келим. — М. : Академия, 2013. — 256 с. 337
38. Романов, А. Ю. Микропроцессорные системы от основ до программирования / А. Ю. Романов. — М. : ДМК Пресс, 2017. — 368 с. 39. Стешенко, В. Б. Микропроцессорные системы: проектирование и разработка / В. Б. Стешенко. — М. : Техносфера, 2015. — 320 с. 40. Шитиков, В. П. Микропроцессорные системы: учеб. пособие / В. П. Шитиков. — М. : Высшая школа, 2016. — 288 с. Программирование микроконтроллеров 41. Прокопенко, В. С. Программирование микроконтроллеров PIC на языке С / В. С. Прокопенко. — М. : ДМК Пресс, 2018. — 304 с. 42. Смит, Д. Программирование микроконтроллеров PIC на языке ассемблера / Д. Смит; пер. с англ. — М. : ДМК Пресс, 2019. — 272 с. 43. Паркер, М. Программирование микроконтроллеров PIC на языке С / М. Паркер; пер. с англ. — М. : Техносфера, 2017. — 384 с. 44. Бейли, Д. Микроконтроллеры PIC: основы программирования / Д. Бейли; пер. с англ. — М. : ДМК Пресс, 2016. — 320 с. 45. Иванов, А. В. Программирование микроконтроллеров PIC: практическое руководство / А. В. Иванов. — М. : Солон-Пресс, 2015. — 256 с. 46. Хартов, В. Я. Микроконтроллеры PIC: от азов до создания устройств / В. Я. Хартов. — М. : ДМК Пресс, 2014. — 288 с. 47. Редькин, П. П. Программирование микроконтроллеров PIC на языке С / П. П. Редькин. — М. : Техносфера, 2018. — 352 с. 48. Мартин, Т. Программирование микроконтроллеров PIC: от основ до сложных проектов / Т. Мартин; пер. с англ. — М. : ДМК Пресс, 2019. — 416 с. 49. Белов, А. В. Микроконтроллеры PIC: практическое программирование / А. В. Белов. — СПб. : Наука и Техника, 2017. — 368 с. 50. Шпак, Ю. А. Программирование микроконтроллеров PIC: от азов до создания устройств / Ю. А. Шпак. — М. : ДМК Пресс, 2018. — 320 с. Программирование контроллеров 51. Блум, Дж. Изучаем Arduino: инструменты и методы технического волшебства / Дж. Блум; пер. с англ. — М. : Эксмо, 2015. — 336 с. 52. Парк, С. Программирование Arduino: создание практических устройств / С. Парк; пер. с англ. — М. : ДМК Пресс, 2018. — 288 с. 53. Петин, В. А. Проекты с использованием контроллера Arduino / В. А. Петин. — СПб. : БХВ-Петербург, 2016. — 448 с. 54. Монк, С. Программирование Arduino: основы и практика / С. Монк; пер. с англ. — М. : Вильямс, 2017. — 320 с. 55. Шилдт, Г. Программирование на Arduino: полное руководство / Г. Шилдт; пер. с англ. — М. : Эксмо, 2019. — 416 с. 56. Белов, А. В. Arduino: от азов программирования до создания практических устройств / А. В. Белов. — СПб. : Наука и Техника, 2017. — 368 с. 57. Магдалин, Ю. В. Программирование Arduino: создание умных устройств / Ю. В. Магдалин. — М. : ДМК Пресс, 2018. — 304 с. 338
58. Бокселл, Дж. Arduino для начинающих: шаг за шагом / Дж. Бокселл; пер. с англ. — М. : Эксмо, 2016. — 256 с. 59. Голубцов, Д. В. Arduino: практическое программирование / Д. В. Голубцов. — М. : Техносфера, 2019. — 352 с. 60. Робертс, Д. Arduino: проекты для начинающих и профессионалов / Д. Робертс; пер. с англ. — М. : ДМК Пресс, 2017. — 288 с. Программирование микрокомпьютеров 61. Уолтерс, Э. Raspberry Pi: руководство по настройке и применению / Э. Уолтерс; пер. с англ. — М. : ДМК Пресс, 2018. — 320 с. 62. Монк, С. Программирование Raspberry Pi: основы и практика / С. Монк; пер. с англ. — М. : Вильямс, 2017. — 352 с. 63. Петин, В. А. Raspberry Pi: проекты и практические примеры / В. А. Петин. — СПб. : БХВ-Петербург, 2019. — 416 с. 64. Робинсон, М. Raspberry Pi: от новичка до профессионала / М. Робинсон; пер. с англ. — М. : Эксмо, 2016. — 288 с. 65. Блум, Дж. Raspberry Pi: создание умных устройств / Дж. Блум; пер. с англ. — М. : ДМК Пресс, 2018. — 304 с. 66. Белов, А. В. Raspberry Pi: от азов программирования до создания проектов / А. В. Белов. — СПб. : Наука и Техника, 2017. — 368 с. 67. Голубцов, Д. В. Raspberry Pi: практическое программирование / Д. В. Голубцов. — М. : Техносфера, 2019. — 352 с. 68. Шилдт, Г. Программирование на Raspberry Pi: полное руководство / Г. Шилдт; пер. с англ. — М. : Эксмо, 2019. — 416 с. 69. Магдалин, Ю. В. Raspberry Pi: создание проектов на Python / Ю. В. Магдалин. — М. : ДМК Пресс, 2018. — 288 с. 70. Робертс, Д. Raspberry Pi: проекты для начинающих и профессионалов / Д. Робертс; пер. с англ. — М. : ДМК Пресс, 2017. — 304 с. 339
Сергей Юрьевич ДОБДИН, Анатолий Владимирович СКРИПАЛЬ ОСНОВЫ ЦИФРОВОЙ ЭЛЕКТРОНИКИ И МИКРОПРОЦЕССОРНЫХ СИСТЕМ: ОТ ТЕОРИИ К ПРАКТИКЕ УЧЕБНОЕ ПОСОБИЕ Зав. редакцией литературы по информационным технологиям и системам связи О. Е. Гайнутдинова Ответственный редактор А. А. Шульга Подготовка макета С. В. Макаров Корректор Е. П. Филатова Выпускающий В. А. Плотникова ЛР № 065466 от 21.10.97 Гигиенический сертификат 78.01.10.953.П.1028 от 14.04.2016 г., выдан ЦГСЭН в СПб Издательство «ЛАНЬ» lan@lanbook.ru; www.lanbook.com 196105, Санкт-Петербург, пр-кт Ю. Гагарина, д. 1, лит. А. Тел./факс: (812) 336-25-09, 412-92-72. Бесплатный звонок по России: 8-800-700-40-71 ГДЕ КУПИТЬ ДЛЯ ОРГАНИЗАЦИЙ: Для того, чтобы заказать необходимые Вам книги, достаточно обратиться в любую из торговых компаний Издательского Дома «ЛАНЬ»: по России и зарубежью «ЛАНЬ-ТРЕЙД». 196105, Санкт-Петербург, пр-кт Ю. Гагарина, д. 1, лит. А. Тел.: (812) 412-85-78, 412-14-45, 412-85-82; тел./факс: (812) 412-54-93 e-mail: trade@lanbook.ru www.lanbook.com пункт меню «Где купить» раздел «Прайс-листы, каталоги» в Москве и в Московской области «ЛАНЬ-ПРЕСС». 115432, Москва, пр-кт Андропова, д. 10 (БЦ Технопарк Плаза), этаж 6, оф. 6.006 тел.: (499) 350-62-10, (495) 252-79-20; e-mail: lanpress@lanbook.ru в Краснодаре и в Краснодарском крае «ЛАНЬ-ЮГ». 350010, Краснодар, ул. Зиповская, д. 9, литер Д, пом. 31 тел.: (861) 274-10-35; e-mail: lankrd98@mail.ru ДЛЯ РОЗНИЧНЫХ ПОКУПАТЕЛЕЙ: интернет-магазин Издательство «Лань»: http://www.lanbook.com магазин электронных книг Global F5: http://globalf5.com/ Подписано в печать 24.12.25. Бумага офсетная. Гарнитура Школьная. Формат 70×100 1/16. Печать офсетная/цифровая. Усл. п. л. 27,63. Тираж 30 экз. Заказ № 003-26. Отпечатано в полном соответствии с качеством предоставленного оригинал-макета в АО «Т8 Издательские Технологии». 109316, г. Москва, Волгоградский пр-кт, д. 42, к. 5.