Добавить в корзинуПозвонить
Найти в Дзене
Разумный мир

Микроконтроллеры для начинающих. Часть 51. Бегущие огни. Запускаем!

Мы разобрались практически со всеми вопросами готовы собрать и запустить наш учебный проект. Сегодня мы увидим его в работе! Как всегда, я буду рассматривать все три семейства микроконтроллеров. PIC18 пока оставим в стороне, для нашего проекта он избыточен, и не привносит ничего нового (для нашего проекта!). В конце статьи я приведу ссылки на полные тексты программ, которые рассматриваются в статье. Вы сможете их скачать и поэкспериментировать внеся любые изменения. AVR будет представлен весьма популярным ATmega328p. Причем я покажу и его использование в составе Arduino Nano. Этот микроконтроллер тоже избыточен для данного учебного проекта, но возможность использования Arduino (а они есть у многих) и определила выбор. STM8 будет представлен одним из самых дешевых STM8S003F3P6. Его можно заменить на STM8S103F3P6, он допускает большее количество перезаписей программы. PIC будет представлен PIC16F630-I/SL, очень простым микроконтроллером, к тому же далеко не самым новым. Зато у него один
Оглавление

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

Как всегда, я буду рассматривать все три семейства микроконтроллеров. PIC18 пока оставим в стороне, для нашего проекта он избыточен, и не привносит ничего нового (для нашего проекта!).

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

Подопытные микроконтроллеры

AVR будет представлен весьма популярным ATmega328p. Причем я покажу и его использование в составе Arduino Nano. Этот микроконтроллер тоже избыточен для данного учебного проекта, но возможность использования Arduino (а они есть у многих) и определила выбор.

STM8 будет представлен одним из самых дешевых STM8S003F3P6. Его можно заменить на STM8S103F3P6, он допускает большее количество перезаписей программы.

PIC будет представлен PIC16F630-I/SL, очень простым микроконтроллером, к тому же далеко не самым новым. Зато у него один из портов ввода-вывода не имеет альтернативных функций выводов, что для полезно, так как мы еще очень многого не изучили.

Почти во всех случаях будет использоваться конфигурация по умолчанию. Что подразумевает и отсутствие необходимости во внешнем кварцевом резонаторе. Никакой лишней возни с настройкой.

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

Настройка конфигурации при использовании микроконтроллера ATmega328P в составе Arduino Nano

Внимание! Перед использованием Arduino Nano вместо ATmega328р, сохраните содержимое ее памяти программ и конфигурацию на компьютере. Это позволит впоследствии восстановить ее состояние в первозданном виде. Для этого нужно воспользоваться внешним программатором подключаемым через разъем ICSP. Встроенный загрузчик Arduino не обладает нужной функциональностью.

Про конфигурацию микроконтроллеров AVR я рассказывал в статье "Микроконтроллеры для начинающих. Часть 41. Конфигурация AVR (Fuses, Lock Bits, и другие)"

Конфигурация микроконтроллеров AVR "по умолчанию" и в составе Arduino Nano. 1- соответствует НЕ запрограммированному состоянию, 0 - соответствует запрограммированному состоянию. Иллюстрация моя
Конфигурация микроконтроллеров AVR "по умолчанию" и в составе Arduino Nano. 1- соответствует НЕ запрограммированному состоянию, 0 - соответствует запрограммированному состоянию. Иллюстрация моя

Конфигурация микроконтроллера установленного в Arduino отличается от конфигурации по умолчанию. И эта конфигурация нам не подходит. Лучше всего просто восстановить конфигурацию по умолчанию. Но если это по какой то причине вам не нравится, то нужно изменить хотя бы критичные для нас биты (fuse). Те биты, которые нужно изменить до состояния по умолчанию я выделил зеленым цветом фона ячеек.

Используемые компиляторы

Для PIC я приведу примеры программ сразу для двух компиляторов. Во первых, для XC8 (используется версия 2.31). Этот компилятор предоставляется самой Microchip и считается стандартным. Причем я воспользуюсь IDE MPLAB X (версия 5.45). XC8 позволит продемонстрировать, что для всех трех семейств микроконтроллером текст программы будет практически одинаковым. Не считая аппаратно-зависимых отличий в описании и начальной инициализации.

Во вторых, я использую CC5X, который я в основном и использовал в других статьях канала. Это довольно специфичный компилятор, о чем я неоднократно говорил. Но он генерирует хороший код, а заодно позволит показать, что там "под капотом".

Для STM8 будет использоваться SDCC (версия 4.0.0). У него есть определенные проблемы, но для STM8 он генерирует довольно приличный код.

Для AVR будет использоваться avr-gcc (версия 10) и avr-libc (версия 2.0.0-1.261). Этот компилятор, или производные от него, считается стандартным. Он входит в состав различных IDE.

У вас может быть и какой-либо иной компилятор. В таком случае вам возможно придется адаптировать тексты программ под его требования. Я просто физически не могу предусмотреть все возможные варианты.

Используемые программаторы

Это не имеет отношения к теме статьи, но я назову программаторы, которые использовались при подготовке статьи.

Для PIC использовался, де факто, стандарт, PicKit 3 (официальный). Но ничто не мешает использовать и PicKit 2, и PicKit 4. Программирование выполнялось или MPLAB X, если использовался XC8, или из MPLAB IPE, если использовался CC5X.

Для STM8 использовался ST-LINK/V2 (официальный). Можно использовать и ST-LINK, и ST-LINK mini. И даже программаторы имеющиеся на отладочных платах Discovery и Nucleo. Программирование выполнялось с помощью stm8flash. Если вы используете Windows, то можете воспользоваться STVP.

Для AVR использовался MiniPro TL866A, он есть у многих. Программирование выполнялось с помощью поставляемой с ним программы. Для AVR есть множество программаторов и вы можете воспользоваться любым. Но пользоваться встроенным программатором Arduino не стоит. Он работает через загрузчик (который нам не нужен и мы его удаляем) и обладает ограниченным функционалом. Например, не позволяет изменять fuse.

Во всех случаях программатор подключался к микроконтроллеру через ICSP - внутрисхемное программирование. Вне зависимости от того, как оно называется официально.

Схемы

Хоть мы и разобрались с схемотехникой, полные схемы мы не рисовали. Давайте восполним этот пробел. Я приведу схемы макетов. Если вы захотите собрать реальное устройство, то светодиоды нужно будет заменить на один из вариантов выходного каскада, которые мы рассматривали ранее.

Схема макета бегущих огней на PIC16F630-I/SL. Иллюстрация моя
Схема макета бегущих огней на PIC16F630-I/SL. Иллюстрация моя
Схема макета бегущих огней на STM8S003F3P6. Иллюстрация моя
Схема макета бегущих огней на STM8S003F3P6. Иллюстрация моя
Схема макета бегущих огней на PATmega328p. Иллюстрация моя
Схема макета бегущих огней на PATmega328p. Иллюстрация моя

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

Программа

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

Тексты наших программ будут состоять из 3 основных частей: описание микроконтроллера и типов переменных, аппаратно-зависимая процедура начальной инициализации микроконтроллера, собственно алгоритм бегущих огней.

Процедуру Delay я очень подробно рассмотрел в предыдущей статье, поэтому сегодня просто будем ее использовать.

Кроме того, я буду отдельно выделять описание варианта для компилятора СС5Х, так это специфический компилятор. Кроме того,здесь используется "ручное управление" с помощью логических операций, без помощи со стороны компилятора.

Описание микроконтроллеров и типов переменных

Если вы еще не прочитали статьи о портах ввода-вывода, самое время сделать это

Микроконтроллеры для начинающих. Часть 45. Порты ввода-вывода

Микроконтроллеры для начинающих. Часть 46. Порты ввода-вывода PIC

Микроконтроллеры для начинающих. Часть 47. Порты ввода-вывода STM8

Микроконтроллеры для начинающих. Часть 48. Порты ввода-вывода AVR

Так как я буду считать, что вы знаете, как устроены и работают порты.

В целом, для всех микроконтроллеров эта часть выглядит практически одинаково. Вот пример для STM8

Я не пользуюсь стандартными определениями для регистров портов ввода-вывода. Я просто описываю порт так, как это удобнее для нашей задачи. Прежде всего, определяются два типа, две структуры, которые содержат нужные нам группы бит. Такой подход к описанию я описывал в статье "Микроконтроллеры для начинающих. Часть 34. Мост к Си. Описываем регистры аппаратуры"

Нам нужны описания подключения светодиодов (run_light_led) и кнопки (btn). Они могут быть подключены как к разным портам, так и к одному. Затем описанные структуры используются для определения собственно регистров портов. Причем мы задаем и адреса регистров, так стандартных файлов с описаниями не используем.

Аналогично выглядит и описание для AVR, только адреса мы задаем по другому, например

__attribute__((io(0x28)))

И для PIC

__at(0x007)

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

В полных текстах программ (ссылки в конце статьи) вы сможете найти описание для конкретного микроконтроллера. Так как они очень похожи, нет смысла размещать их в статье. Она и так очень большая.

Особый случай, CC5X

Этот компилятор не позволяет (я уже говорил об этом раньше) описывать битовые поля с длинной отличной от одного бита. Поэтому и описание будет совсем иным

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

А для упрощения текста программы мы создаем две вспомогательные функции. GetRunLed (макрос), которая возвращает текущее состояние выходных выводов порта. SetRunLed, которая позволяет задать состояние выходных выводов порта. В этих функциях мы используем логические операции для манипуляции битами.

Аппаратно-зависимая инициализация микроконтроллера

Нам повезло, в выбранных микроконтроллерах не требуется управлять альтернативными функциями портов. Это, в общем то не особо типичный случай, но наш первый проект и должен быть простым.

Все, что нам требуется настроить, это направление работы бит порта, к которым подключены светодиоды. Напомню, по умолчанию после сброса все выводы портов настроены как входы. Поэтому и кнопку настраивать не надо.

В полных текстах программ настройку выполняет функция MCU_Init. Здесь же я просто покажу, к чему вся настройка сводится.

Для PIC

TRISC.run_led_bits=0;

как видно, чрезвычайно лаконично. У PIC вывод работает как выход, если соответствующий бить регистра TRIS равен 0. Так же просто для AVR

DDRC.run_led_bits=0b111;

Да, здесь используются "магические числа". Если вам это не нравится, можете использовать define, что дать им имя. Но для нашего простейшего проекта, когда константа используется один раз, в этом нет особого смысла.

А вот для STM8 инициализация немного сложнее. Сначала мы переключаем выводы в режим выхода

PORTC_DDR.run_led_bits=0b111;

а затем нам еще потребуется включить двухтактный режим работы

PORTC_CR1.run_led_bits=0b111;

Основная программа, чтение кнопки и определение направления бега огня

Мы проделали большую подготовительную работу, поэтому основная программа вообще не будет зависеть от используемого микроконтроллера!

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

Это делается в основной программе, но до главного цикла. Нажатая кнопка соответствует низкому уровню на выводе, отпущенная высокому.

Главный цикл, огонь бежит

Да, никакой зависимости от используемого микроконтроллера нет! Все абсолютно одинаково.

В главном цикле мы, в соответствии с выбранным направлением бега огня, сдвигаем битовую группу порта, соответствующую подключенным светодиодам. А если логическая 1 убежала (или еще не прибежала), мы устанавливаем бит в начальное состояние (в соответствии с требуемым направлением.

После чего выполняем задержку примерно на 100 мс. Это дает частоту бега примерно 10 Гц. При более высокой частоте бегущий огонь зрительно сливается, а при меньшей теряется динамизм картинки.

Параметр вызова Delay для каждого микроконтроллера свой. В полных текстах программ я написал, какой задержке в мс соответствует 1000 циклов задержки. Так что вы можете изменить скорость бега на любую. желаемую.

И ведь это все! Программы для разных микроконтроллеров действительно одинаковы! За исключением инициализации и минимальной разницы в описании регистров.

Особый случай, СС5Х

Я вас много пугал этим особым случаем. Но не так уж он и страшен

Все чрезвычайно похоже на то, как это было для других компиляторов. Только теперь у нас нет поддержки компилятора в работе с группами бит в битовых полях. Поэтому мы используем логические операции.

Я специально использовал для PIC два очень разных компилятора, XC8 и CC5X. Это позволило наглядно показать, полезность подхода к работе с битами, который я ранее описывал "Микроконтроллеры для начинающих. Часть 33. Мост к Си. Работа с битами". И пользу описания ресурсов микроконтроллера под условия свое задачи, а не использования стандартных описаний.

Но кроме плюсов, упрощения кода, есть и минусы, повышенные накладные расходы. Не всегда компилятор генерирует идеальный код для таких манипуляций. Иногда хочется подправить его вручную. Но это уже не для начинающих.

Полные тексты программ

Как и обещал, даю ссылки на полные тексты программ, для всех микроконтроллеров, которые описывались в статье

run_light_pic_v1_xc8.c

run_light_pic_v1_cc5x.c

run_light_stm8_v1.c

run_light_avr_v1.c

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

https://github.com/ektsysto/Smart_World_ZEN

Репозиторий использует лицензию MIT. Это, если просто, обозначает "Делайте что хотите, но автора (то есть, меня в данном случае) указывайте".

Заключение

Вот и закончен наш первый , но не последний, учебный проект. Я постарался не только дать готовые решения, но и показать, пусть и упрощенно, весь путь работы над проектом. Большая подготовительная работа позволила нам написать программу, большая часть которой не зависит от микроконтроллера.

И в дальнейшем я буду поступать точно так же. Я буду выделять аппаратно-зависимые части, что бы основные алгоритмы оказывались не зависящими от аппаратной части. Это конечно не HAL, но жизнь упрощает сильно. Это не всегда просто, но позволяет с минимальными затратами переносить программы на другие микроконтроллеры, даже с очень отличающейся архитектурой.

До новых встреч!