Какой микроконтроллер выбрать

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

Открывает наш парад компания Microchip Technology с серией PIC. Эти МК отличаются между собой разрядностью (8/16/32), набором периферии и корпусом чипа. Восьмибитные варианты же делятся на четыре семейства: baseline, mid-range, enhanced mid-range и PIC18. Более подробная информация приведена в таблице.

Также есть 16-битные «пики» — PIC24F и DsPIC30/33F. Ну и 32-битные — PIC32MX. Эти непонятные сочетания букв и цифр — часть идентификатора чипа. То же, что и марки у машин. Например, широко распространенный камень PIC16F628A расшифровывается так: семейство PIC16F6 (Mid-range), а остальная часть имени — указатель на конкретный камень. У рассмотренных далее МК в имени может содержаться еще больше информации.
Цена и содержимое

Эти микроконтроллеры имеют среднюю стоимость. Например, камень PIC6F628 в Chipdip стоит около 150 рублей, а PIC18F2550 — 620 рублей.
Более дешевые экземпляры имеют в своем составе минимум периферии. У упомянутого ранее PIC6F628 следующие характеристики: встроенный тактовый генератор для работы с частотой 4 или 8 МГц; 18 пинов, из них 16 — ввод/вывод, а 2 — питание; для работы на более высоких частотах можно подключить кварцевый резонатор; Flash-память объемом 2048 слов; 4 аналоговых входа; два 8-битных таймера и один 16-битный; 224 байта ОЗУ (самому смешно); 128 байт EEPROM (это программно перезаписываемая энергонезависимая память, вроде жесткого диска); интерфейс UART.
Программирование и использование PIC
Программируют для микроконтроллеров, как правило, на ассемблере и на Си. Есть множество сред разработки: MPASM и MPLAB, MicroC, JALedit (язык JAL, сам про него впервые слышу). Скачать MPLAB
Как правило, на таких МК собирают простенькие устройства вроде мигалки или таймера. Эти контроллеры долго имели монополию на постсоветском пространстве, и в результате в интернете есть огромное множество русскоязычных сервисов и статей, посвященных этим моделям МК. При сборке устройства часто можно даже не писать прошивку, ведь она легко находится в интернете, даже в нескольких вариантах.
Вторым плюсом можно указать встроенные независимые (от тактового генератора) счетчики. Благодаря этому факту семейство зарекомендовало себя в качестве «мозгов» для частотомеров. Пара таких контроллеров лежит у меня в мастерской на черный день. Из минусов можно выделить только высокую стоимость оригинальных программаторов, которые зовутся PICkit.

В интернете есть множество статей по сборке достойных аналогов таких программаторов. Но вся соль в том, что для сборки программатора тебе нужно что? Правильно, программатор. На этот случай был разработан программатор Громова. Для его сборки почти ничего не нужно, а работает он от COM-порта компьютера. На момент его разработки популярность этой серии МК была высока, да и COM-порты были у всех ПК. Сейчас все это уже редкость, так что придется преодолеть порог вхождения либо раскошелиться.
AVR

Микроконтроллеры AVR производит компания Atmel. Если не знал, это те самые контроллеры, из которых собирают Arduino. Некогда Atmel была независимой компанией, но позже ее купила упомянутая ранее Microchip, которая продолжает выпускать эти МК. Они делятся на три семейства: tinyAVR (ATtinyxxx), megaAVR (ATmegaxxx), XMEGA AVR (ATxmegaxxx).
TinyAVR имеет следующие характеристики:
- Flash-память до 16 Кбайт;
- RAM до 512 байт;
- ROM до 512 байт;
- число пинов (ножек) ввода-вывода 4–18;
- небольшой набор периферии.
- FLASH до 256 Кбайт;
- RAM до 16 Кбайт;
- ROM до 4 Кбайт;
- число пинов ввода-вывода 23–86;
- расширенная система команд (ассемблер) и периферии.
- FLASH до 384 Кбайт;
- RAM до 32 Кбайт;
- ROM до 4 Кбайт;
- четырехканальный контроллер DMA (для быстрой работы с памятью и вводом/выводом);
- «инновационная» система обработки событий.
Как и в случае PIC, у моделей AVR в названии содержится ценная информация. Например: ATMega328PU — семейство megaAVR, 32 Кбайта Flash, 8-битный, P — говорит о модификации (примерно как у пистолета Макарова модернизированного — ПММ).

Цена и начинка
Эти микроконтроллеры имеют, как и PIC, среднюю стоимость. Например, упомянутый ранее камень ATmega328P в Chipdip стоит 160 рублей, а ATxmega128A1 — 590 рублей.
TinyAVR дешевле и проще своих старших братьев. Немного характеристик ATmega328P: предельная частота работы 20 МГц (слышал, правда, что под охлаждением и посильнее разгоняли); 23 пина ввода-вывода; Flash-память на 32 Кбайта; 8 аналоговых входов; два 8-битных таймера и один 16-битный; 6 ШИМ-каналов; 2 Кбайта RAM; 1 Кбайт EEPROM; интерфейсы UART, SPI, I2C.
Программирование и использование AVR
Благодаря распространению плат прототипирования Arduino, как у нас, так и за рубежом, эти МК имеют низкий порог вхождения. Программируются на ассемблере, Си, C++; можно воспользоваться графическими генераторами кода типа Scratch (см. Scratchduino). Для работы есть Atmel Studio, IAR AVR, WinAVR. Ну и Arduino IDE, куда уж без нее. Лично я использую связку из Geany и avrdude. Для прошивки есть большое разнообразие программаторов: как дешевые, так и подороже. Я для этих целей прикупил недорогой экземпляр USBasp где-то за 1,5 доллара (на Aliexpress есть масса вариантов). А можно в качестве программатора использовать и Arduino UNO.
Информации об этих контроллерах в интернете много: чего только стоит канал AlexGyver! И благодаря Arduino существует масса обучающих наборов на любой вкус. В общем, низкий порог вхождения — весомый плюс этих контроллеров.
Кстати, если заказываешь из Китая, то взять плату с чипом будет дешевле, чем чип отдельно.
ARM
О компании ARM и ее продукции ты наверняка слышал. Однако производит эта компания не сами микроконтроллеры, а лишь архитектуру. Лицензию на нее покупают конечные производители и используют так, как им захочется. Кто только их не выпускал! Но как микроконтроллеры наибольшее распространение получили чипы компании STMicroelectronics.

Они делятся на два семейства: STM32 и STM8. Как понятно из названий, такие чипы бывают 8- и 32-битные. А каждое семейство делится на серии, которых достаточно много.
STM8
Что можно о них сказать? Это функциональный аналог AVR, только дешевле. Здесь есть три серии: STM8L c ультранизким энергопотреблением, STM8S для индустриальной аппаратуры и STM8A, именуемые «высоконадежными». Периферия у всех такая же, как у AVR, но есть встроенный тактовый генератор. Из плюсов могу выделить только низкое энергопотребление и маленькую цену. Замечу, у STM8 архитектура не ARM, а собственная. Она очень схожа с ARM и использует идентичный STM32 интерфейс прошивки. Компилятор для них используется тоже один, и при его работе ты просто указываешь, под какую архитектуру собирать код.
STM32
Проще говоря, это старший брат STM8. Его характеристики куда выше и колеблются в больших пределах в зависимости от серии. Программируются практически на чем угодно, даже JavaScript, хотя я бы не рекомендовал.
Прошивка и программирование
Прошиваются STM32 с помощью разработанного компанией ST интерфейса Single Wire Interface Module (SWIM). Еще у МК этой серии есть интерфейс отладки Serial Wire Debugging (SWD). Им я не пользовался, но в большинстве гайдов по STM есть описание его настройки.
А еще на STM можно записывать прошивки по USB. Дело в том, что у многих контроллеров этой серии есть аппаратная поддержка USB. STM благодаря этому может эмулировать разные устройства — например, флешку. Если залить специальную прошивку, можно будет обновлять встроенную программу просто по USB.
Для STM32 есть самые разные программаторы — от весьма крутых до простеньких USB-свистков. Я, например, взял ST-LINK, на «Алиэкспрессе» он стоил около 1,6 долларов. Его достоинство в том, что он может прошить любой контроллер STM.

Стоит также упомянуть платы STM Nucleo. Вот одна из них.

Это что-то вроде Arduino из мира STM. Стоит дороговато, как и оригинальные Arduino, но вещь для новичка отличная. Если деньги есть, стоит взять. Здесь же стоит упомянуть «Амперку» с их «Искрой» и набором для начинающих. Тоже вполне достойный выбор для первого раза.

Для программирования можно воспользоваться средами Embedded Workbench, uVision и TrueStudio. Благодаря работе умельцев для этих же целей можно использовать и родной для многих Arduino IDE. Есть также онлайновый IDE — mbed studio.
Цена
Партия из пяти плат с обвязкой и STM8 будет стоить около 4,5 долларов. Плата BluePill с STM32F103 сейчас стоит 1,6 доллара. Плата NUCLEO-F072RB — 16,4 доллара. Ссылок давать не буду — на «Алиэкспрессе» все это легко ищется по запросу «stm32».
ESP

И, наконец, пара слов про ESP. С этими МК я не работал и знаю о них немного. Это 32-битные камни с модулем Wi-Fi на борту. Они используют архитектуру xtensa. На них собирают умные дома и прочие интересные штуки (смотри врезку ниже). Программировать можно опять же в Arduino IDE. Знаменитая ESP8266, неоднократно упомянутая на страницах нашего сайта, как раз и относится к этому семейству. К нему же относится ESP32, старший брат ESP8266.
Выводы
Кроме упомянутых выше производителей есть много других: Intel, Renesas Electronics, Texas Instruments и прочие. Но в сообществе электронщиков-любителей они не прижились, хоть и активно используются в промышленности.
Новичкам я рекомендую AVR в виде Arduino: по нему много информации на русском, а порог вхождения невелик. Но засиживаться на них не стоит, а то так и будешь до конца дней собирать и пересобирать этот конструктор.
После Arduino стоит перейти на STM. Для простеньких проектов бери восьмибитные чипы, для более сложных — 32-битные, и будет тебе счастье. И помни, что микроконтроллер — это уже не процессор, но еще не компьютер.
Статьи на сайте о ESP32
- Программирование на ESP32
- Создание сниффера на ESP32
Статьи на сайте об STM32 и проектах на его основе
- Как реализовать шифрование для самодельного гаджета
- Заводим и разгоняем оперативную память на STM32 и Arduino
- Как собрать свой мобильник и почему это проще, чем кажется
- Собираем программно определяемый радиоприемник своими руками
Карпутер 3. Выбираем микроконтроллер

Итак, со схемами в proteus наигрались, теперь голова полна идеями, хотелками и желалками. Но ни одна идея не реализуется сама собой, поэтому надо выбрать «движок» для нее.
Как выбирают контроллер?
Во-первых, по личным предпочтениям. Кому-то нравится одна архитектура, кому-то другая. У кого-то уже есть опыт с одними микроконтроллерами и ему лень изучать другие … Но я считаю, что раз опыта и предпочтений нет, поэтому — stm32. Вам на данном этапе все равно, а мне потом спасибо скажете.
Во-вторых, по скорости. Если задача сложная, то думаю понятно, что работающий на 72МГц контроллер обгонит работающего на 16МГц (грубо — у кого больше литраж у двигателя, тот быстрее разгонится или больше увезет). А если устройство работает от батареек, то наоборот, устройство работающее на 16МГц легко даст фору работающему на 72х (опять же, чем больше литров, тем чаще на заправку надо будет ездить). Но на данном этапе нам совершенно все равно, какая скорость у контроллера — для нас подойдет любая.
И наконец, по числу портов и их возможностями. Все порты делятся на два типа: цифровые и аналоговые. Цифровые оперируют уровнями типа «есть сигнал» и «нету сигнала», а аналоговые — «какой уровень у сигнала?». Говоря другими словами — кнопки, выключатели и прочие переключатели — это цифровые, а всякие регуляторы, измерители и прочее — аналоговые. На каждую кнопку, релюшку или измеритель надо по одному порту (конечно, есть куча возможностей, как от этого уйти, но пока нам этого не надо). И крайне рекомендую при выборе зарезервировать пару портов под всякие доделки и внезапно всплывшие идеи.
Ладно, хватит разговоров, пора выбирать то, на чем делать будем, а то очень охота в магазине денег потратить, пока еще есть возможность.
Что будем делать-то? В смысле для чего мы все это затеяли? Давайте начнем с простого. Пусть будет система автоматического включения света в машине. Как пример использования: садимся в машину, включаем зажигание, заводим машину и через некоторое время наш контроллер включает фары. Выключили зажигание — все выключилось. Сплошные бонусы: стартеру легче крутить двигатель — фары не отбирают лишних ампер и вам не надо будет помнить о включении фар.
Какой будет алгоритм работы?
1. Измеряем напряжение бортовой сети
2. Напряжение меньше 13В? если да, иди на п.1
3. Подождать 5 секунд.
4. Включить фары.
Все, никаких заморочек. Просто и совсем не страшно. Как видно, нам потребуется всего 2 порта: один аналоговый для измерения напряжения в сети и один цифровой, для управления релюшкой фар.
(отступление) Не хотите фары включать? Ну тогда например можно автоматически включать и выключать компрессор в пневмосистеме. Или в зависимости от температуры включать нагреватель или вентилятор. В общем, подойдет любой вариант «измерил что-то и как это что-то достило такого-то уровня — включил или выключил нечто».
Вернемся к нашим баранам. Нам нужен микроконтроллер, у которого есть как минимум 1 аналоговый порт на вход и 1 цифровой порт на выход. Сейчас смешно, да. Но потом всего будет не хватать и начнутся мучения.
Теперь готовимся скачать много из сети. Для начала нам нужна программа STM32CubeMx. (Все поисковики ее легко находят, но вот прямая ссылка www.st.com/web/catalog/to…533/PF259242?sc=stm32cube там мотайте страницу в самый низ и справа будет маленькая красная кнопочка Download).
Зачем нужна эта программа? Как я писал в первом посте, STM32 имеют один, но очень большой и неприятный минус — очень сложно начать с ними работать. В этих микроконтроллерах очень много возможностей и вариаций, поэтому даже просто запустить его составляет очень большую проблему. Команды инициализации, предназначенные для одной серии, не подходят для другой. Один и тот же порт может выполнять разные функции на разной частоте, причем все это настраивается в четырех или пяти местах. В общем, реальный кошмар после атмеловских контроллеров и 99% причин неработащих программ.
Вот и придумали этакий «генератор кода инициализации», когда можно мышкой не торопясь повыбирать порты и их функции. При этом идет одновременный контроль правильности использования порта и непересечение его с другими функциями. В общем, скачивайте, распаковывайте и запускайте программу (может потребовать java, так что тоже ставьте). Как ставить программы, нажимая next, я рассказывать не буду 🙂

Перед вами откроется очень информативное окно. New Project — это создать новый проект, Load Project — загрузить старый, который редактировали раньше. Нам естесственно надо выбрать создать новый. И тут …

И тут перед вами откроется окно, в котором собрана вся (почти) линейка микроконтроллеров. Первая вкладка — MCU Selector позволяет выбрать подходящие контроллеры в их голом виде. Слева в табличке функционал, справа — подходящие контроллеры. Скажем, нужно нам в нашем проекте использовать одновременно ethernet и часы реального времени, так значит ставим галочки и получаем, что нам подходят 88 микроконтроллеров из 590 (на момент написания). Но эта вкладка для продвинутых пацанов.
Нам нужна следующая вкладка, которая называется Board Selector. Тут уже можно выбрать готовые платы, со всем распаянным. Сразу рекомендую нажать кнопку «>>», которая будет показывать изображение платы.

Механизм тот же самый — слева выбираем что хочется, а справа получаем список того, где это есть. Потом открываем веб-сайт ближайшего магазина электроники и смотрим на наличие и цену. Лично у меня есть платы STM32L100 и STM32F3 (именно она изображения на скриншоте). Так как F3 мне нравится больше, то и в дальнейшем я буду использовать именно эту плату. Но повторюсь, вы можете использовать любую плату или процессор — главное, что бы он вам подошел по характеристикам.
Выбрав плату или процессор, жамкаем на кнопоку ОК в самом низу. Компьютер немного подумает и потом выдаст примерно вот такую картинку.

Слева будут всякие возможности, которые умеет процессор, а справа — как и на что распределены ножки и процессора. Если вы вышли сюда из выбора плат, то программа сама показала, что на плате куда подключено. Как видите, все ножки помечены разными цветами.
Желтенькие и светлозеленые — ножки, назначение которых изменить нельзя. Питание, земля и прочие подобные ножки.
Оранживенькие — ножки, на которые повешено то, что есть на плате и что можно либо отключить, либо заиспользовать. У меня это кварцевые резонаторы, гироскоп с компасом, USB порт и так далее.
Зелененькие — это ножки, на которые тоже повешено то, что есть на плате, но это ТО — кнопки, светодиодики и прочее. Грубо говоря, отличие только в сложности с точки зрения контроллера. Таким же цветом будут обозначаться и ножки, которые вы выделили для вашего проекта.
Серенькие — свободные ножки, которые можно использовать.
«Пришпилленость» ножки означает, что программа не может менять ее назначение, как бы этого ей не хотелось. Дело в том, что если у вас нету предпочтения, какой именно порт для чего использовать, то программа постарается «раскидать» их так, что бы микроконтроллер был наиболее функциональным.
Как менять назначение ножек? Есть два способа. Первый — это просто мышкой ткните на ножке. Вот для примера я ткнул на ножке, которая у меня подключена к голубой кнопке.

Как видите, эта ножка может выполнять аж 17 функций, но сейчас она работает как GPIO_Input (я ниже объясню, что это значит).
А второй способ — воспользоваться левой вкладкой и включить нужную функцию.

Как видим, у функции вообще горит желтый предупреждающий знак, который показывает, что что-то с ней не то. Открыв ее, можно увидеть подсвеченным красным подфункцию. В данном случае это IN1. Подведя мышку к красному, можно узнать, что с чем конфликтует. В данном конкретном случае можно увидеть, что 1й канал 1го аналого-цифрового преобразователя конфликтует на ножке процессора PA0, которая уже стоит в режиме GPIO_Input. Белиберда, да? Но ничего. Для примера можно обидеться и раз нам не дают использовать IN1, выбрать IN3, что бы это не значило. И обратите внимание, на рисунке процессора справа одновременно начнет показываться как «занятая» соответствующая ножка процессора. В нашем случае это PA3, в левом нижнем углу.
Дальше можно начинать включать те или иные функции, сообразуясь со своим мнением о прекрасном и расположением выводов на данной конкретной плате.
Итак, как же понять, какие функции можно повесить на ножку? Что бы не забивать голову, я опишу только наиболее нужные и часто используемые функции. Назначение других можете узнать сами, когда прижмет (но 90% это никогда не понадобится).
Итак, что можно выбрать?
ADC — Или АЦП, аналогово-цифровой преобразователь. Показывает значение напряжения. У большинства АЦП есть каналы, к которым он может подключаться. А каналы напрямую подключены к ножкам. То есть когда вам надо измерить напряжение на 1,2 и 3й ножке, то микроконтроллер на самом деле будет выполнять примерно следующее «подключить ацп к ножке 1, измерить, подключить ацп к ножке 2, измерить, подключить ацп к ножке 3, измерить». В принципе, для большинства задач этого достаточно, ведь измерение одного канала занимает от 1 до 10 мс. Но есть задачи, когда необходимо реально одновременно измерить напряжение на несколких ножках. В таком случае используют два или больше АЦП. Например, в F3 серии аж 4 АЦП, поэтому мы можем измерять 4 уровня одновременно. Если мы заиспользуем все доступные ресурсы, то сможем за 0,1с измерить 59 аналоговых выводов (ардуинщики, вы рыдаете? :).
DAC — или ЦАП. Цифро-аналоговый преобразователь. Преобразует некоторое значение в уровень сигнала на выходе. Обычно один DAC имеет от 1 до 10 выходов, каждый из которых можно регулировать отдельно.
TIM — таймеры. Срабатывающие «раз в нное время» сигналы. На таймерах в stm делается очень многое — от PWM (управление сервомоторами и яркостью) до подсчета частоты смены сигнала на входе. Немножко к ним имеют отношение RTC — часы реального времени (которые считают минуты и секунды, а не тики и такты) и WDG — системы, которые автоматически перезагружают контроллер, если он завис, но я их касаться не буду
USART/UART — контроллеры для связи с «внешним миром»: с компьютерами, с другими контроллерами и так далее.
И наконец GPIO. Это порты общего назначения. То есть на них можно вешать все, что душе угодно. Они могут быть GPIO_Input — порт, работающий на вход (который принимает сигнал «есть» и «нет») и GPIO_Output — порт, работающий на выход (который выдает сигнал «есть» и «нет»). Вы можете увидеть GPIO_Reset — это означает, что порт находится в хз каком стоянии и GPIO_EXTI — это выход прерывания. В общем лишнее на данном этапе.
Все ножки маркируются следующим способом: [подсистема]_[функция]. Пример:
ADC1_IN6 — 6й вход 1го АЦП контроллера
DAC1_OUT1 — 1й выход 1го ЦАП контроллера
USART1_TX — порт передачи 1 контроллера связи.
Но вернемся назад. Из всего выше перечисленного нам нужен один ADC ввод и один GPIO_Output вывод. Для ввода я заиспользую ADC1_IN2 (ножка PA1), а для вывода GPIO_Output — PC5. Они расположены на одной стороне реальной платы, поэтому мне будет удобно с ними работать. И что самое главное, они не конфликтуют ни с чем, что уже есть на плате.

Щелкаем и меняем назначение нужных нам ножек. Обратите внимание на то, что у PA1 нет булавки, а у PC5 — есть. Это та самая функция переназначения портов, когда вдруг функционал будет конфликтовать, а нам нет разницы, откуда его брать. Что бы «прикрепить» функционал к ножке, надо просто правой кнопкой мышки по ней щелкнуть и выбрать Signal Pinning. Теперь ни одна сволочь не отберет у нас ее :). Кстати, там же можно и дать название ножке, что бы не запутаться.

Согласитесь, так немного красивее? И так по всем ножкам-функциям, которые нам потребуются в нашем будующем устройстве. Не подходит что-то — возвращяемся назад и выбираем другую плату/микроконтроллер. Но я буду считать, что мы этот этап успешно преодолели и с большим трудом выбрали и назначили так нужные нам аналоговый порт на вход и цифровой порт на выход.
Можно сохранить проект на всякий случай, ибо это только начало.
Теперь щелкаем следующую вкладку — Clock Configuration. И у некоторых сейчас порвет мониторы 🙂

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

Тут отображаются те системы, которые будут использоваться в нашем контроллере. Не бойтесь лишних. Просто программа умная и сама добавлят то, что необходимо для жизни микроконтроллера.
На картинке мы видим включенный контроллер ADC1 (для него нужны контроллер DMA, NVIC и RCC) и контроллер GPIO (Для него нужен RCC). В общем, давайте поверим, что нам это надо.
На этом экране у нас есть возможность тонкой настройки. Жмем на ADC1

Тут собраны все тонкие настройки для данного контроллера. Особо менять нечего, за исключением подсвеченного — Continuous Conversion Mode. Поставьте его в Enabled. Данная галочка говорит, что мы желаем запрограммировать контроллер так, что бы он постоянно мерял свои входы. И более того, измерянные значения сразу присваивал переменным. Ну ленивый я, пусть железка сама все делает 🙂
Аналогичную картинку можно получить и по GPIO портам.

Тут можно тоже поизменять разные параметры, но нам тут менять тоже ничего не надо.
В общем, полезная вкладка, особенно когда начинаешь использовать более сложные вещи, как USART или USB — здесь можно настроить все.
И наконец, последняя вкладка — Power Consumption Calculator. Тут можно прикинуть, сколько электричества будет потреблять микроконтроллер.

Но подчеркиваю, именно прикинуть. Ибо система не знает, сколько потребляет то, что еще подключено к этому контроллеру. На приведенном выше скриншоте я уже понажимал все кнопки. Согласно картинке, если мы ничего не будем подключать к этому микроконтроллеру, то на полной мощности он будет потреблять 30 миллиампер. Или говоря другими словами, от одной батарейки АА он проработает 3 с лишним суток. И это я не тыкал в различные режимы энергосбережения …
Итак, остался один последний шаг. Сгенерировать исходный код, котрый будет компилироваться и прошиваться в контроллер. На панели сверху есть кнопка «шестеренка с палкой». Нажимаем ее и …

Заполняем, где будут располагаться файлики и как мы обзовем проект. Так же выберем, для какой среды разработки будет генерироваться исходный текст. Выбор небольшой и все предлагаемые системы — полный шлак (тут конечно у каждого свои фломастеры, но тот же бесплатный CoCox уделывает Keil как бог черепаху), поэтому выберите MDK-ARM, как наиболее описанную в русском интернете.
Если вы запускаете генерацию в первый раз, система предложит скачать Firmware Package именно для вашего процессора. Ждем пока скачает и нагенерирует.

Увидели это окошко? Поздравляю! Вы прошли большую часть пути. Остался еще один шаг. Всего один …
Открываем браузер на www.keil.com/download/product/ и выбираем MDK-ARM v5. Вам дадут анкету, в которой реально проверяется только email. Проверяется — в смысле их сервер подключается к вашему серверу и проверяет валидность ящика, поэтому емайлы типа 2@1.co не проходят. Остальное нужно только для того, что бы выбрать, на каком языке потом вам напишет продавец со словами «купите у нас». Как обычно, у данной версии есть ограничения и самым главным из которых является ограничение в объеме кода в 32 килобайта. Поверьте, это довольно приличный объем для микроконтроллеров и вам его хватит надолго. Но если вас это напрягает, то сами знаете где можно найти вылеченную версию совершенно бесплатно.
На данном этапе можете спокойно идти пить чай. Версия, которую вам предлагают, занимает 500 мегабайт и скачаться мгновенно не может. А самизнаетекакая версия занимает еще больше, потому что в нее напихали всякого нужного и ненужного.
Как обычно, рассказывать как ставить программы с помощью нажатия кнопки next, я не буду. Единственное, что при первом запуске вылезет Packs Installer — дождитесь, пока он отработает и закрывайте его. Так что ставьте Keil и в той папочке, куда сохранили проект, найдите каталог Projects, в нем MDK-ARM и там ваш файл с типом mVision4 Project. Нажимаем на него …

Я тут его немного сплющил, но вы увидите именно это. Теперь нажимаем на кнопочку, которая во втором ряду, под «открыть». Похожа на папку для бумаг, в которую входит стрелочка. Ну или на клавиатуре F7. Этим мы запускаем компиляцию всего того, чего мы нагородили выше.

И только после того, как вы увидели в окошке снизу строчку 0 Errors(s), 0 Warning(s) вы можете поздравить себя — у вас есть полностью готовая прошивка для микроконтроллера. Ну и что, что она пока ничего не делает, зато 90% нашей первоначальной задачи уже выполнено. Теперь вы можете идти в магазин и покупать реальный микроконтроллер за реальные деньги. И у вас есть уверенность, что он заработает.
А вот как и что подключать к контроллеру — это уже в следующем посте.
Какой микроконтроллер выбрать для начинающего? (и язык программирования к ним)?
Вы не совсем понимаете суть проблемы. Начнем с того что Arduino это не микроконтроллер, а простая система для обучения и прототипирования на базе МК AVR. Т.е. Arduino это совокупность стандартов для облегчения разработки и Arduino = AVR. МК AVR и PIC сейчас уже в промышленности используются редко, в основном МК на ядре Cortex (например STM32) или ПЛК, но все это сложно дорого и для новичка неприемлемо.
Примечание: Arduino грубо говоря по комплекту новичка,бьет по кошельку.
Да, ну! Если для вас набор новичка 30-50$ это дорого то забудьте.
Так же нужно понимать, что Arduino это открытая платформа т.е. их может производить кто угодно. Естественно китайцы этим во всю пользуются. Большинство китайских плат ни чуть не хуже итальянских и американских, но при этом в 2-3 раза дешевле
Короче, не морочьте голову ни себе не людям, хотите изучать МК с нуля купите arduino набор на aliexpress и разбирайтесь. Потом изучайте STM32 это уже вам даст шанс получить работу стажера в серьезной конторе. Уже там вас научат зарабатывать деньги на программировании МК
Ответ написан более трёх лет назад
Нравится 2 2 комментария
Kirs Dev @KIRSss Автор вопроса
Спасибо за краткий ответ. Сделаю как вы сказали
evgeniy_lm @evgeniy_lm
Kirs Dev, Удачи в изучении.
Так же нужно иметь ввиду, что китайцы используют в качестве переходника uart-usb дешевый ch340 вместо МК Atmega16. Это незначительно сокращает возможности, но для новичка это не существенно.
Ответы на вопрос 3
с аурдино стоит поиграться для начала, ибо там и сообщество таких же игрунов и куча готовых шилдов с кучей готовых статей «для чайников» как из буханки хлеба сделать троллейбус.
потом все таки стм32, это более поздняя, а значит более продвинутая платформа (хотя и на порядок сложнее в изчении). весьма стоит изучить ее на аппаратном уровне (на ассемблере как говорят погромисты).
вообще знание с/asm, помноженное на знание аппаратной части процессора, знатно вычищает из головы много ООП мути, неуместной на эмбедед платформе.
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
не буду отвечать из-за модератора
А какая работа — самоделки? Вообще-то автоматика делается на ПЛК (языки Codesys). Дорого (хотя, можно начать с российского Овен), но если ещё освоить SCADA, то работу можно найти.
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Наиболее востребованные микроконтроллеры — STM32. Более конкретно — сейчас лучше изучать новые серии — STM32Н7, STM32G0, STM32F7. Они отличаются от старых серий STM32F1, STM32F2, STM32F3, STM32F4, STM32F0 более продвинутой реализацией периферийных устройств. То есть, у STM32 есть 2 основных набора периферии — старый и новый, периферия в предедах каждого из этих наборов в основном совместима между сериями. Наиболее бюджетный набор для отладки для начала — плата «Blue pill» на STM32F103 + китайская копия STLink. Из более продвинутых — есть относительно недорогие платы STM32H750VBT6-Modul. Другие типы востребованных микроконтроллеров — Freescale i.MX6, dsPIC. AVR и PIC16 считаются устаревшими, и используются редко, в основном в новых версиях старых устройств на них.
Языки программирования — C обязательно, C++ — где как, где-то обязательно, где-то не используется вообще. Это связано с сертификацией по безопасности — для C утверждённые стандарты безопасности, для C++ они только разрабатываются. Python полезен для тестирования устройств с ПК, JavaScript полезен в разработке web-интерфейса устройств.
Ответ написан более трёх лет назад
Kirs Dev @KIRSss Автор вопроса
Хорошо. Небольшой вопросик про Assembler.
Все пишут на C/C++ (Вакансии тоже говорят про них). Но попробовал на Assembler,понравилось.
Есть ли возможность писать на Assembler для STM32?
И так скажем. Попытать счастье и устроиться на работу со знанием Assembler? ( Ну,конечно же еще и C )
Писать на чистом ассемблере — это очень нишевая специализация — это нужно только для разработки высокопроизводительных библиотек, обычно — это библиотеки обработки сигналов. STM32 можно использовать для обработки сигналов, такие задачи — часто составная часть проекта приборов. Но обычно для этого подбирают готовую библиотеку, и только если подобрать не удаётся — пишут модули на ассемблере сами. То есть чтобы писать только на ассемблере нужно работать либо в компании, разрабатывающей библиотеки, на постсоветском пространстве такие мне неизвестны, либо в крупной компании, делающей что-то узкоспециализированное и достаточно необычное. Но вот ассемблерные вставки и отдельные функции — это не такая уж редкость, хотя их тоже стараются избегать, потому что ассемблер ARM достаточно сложный, мало кто знает его достаточно хорошо — а значит программы с ассемлерным кодом трудно сопровождать. С другой стороны — знание ассемблера — весьма полезный навык и в случае, если писать на C/C++ — он позволяет оценивать оптимальность машинного кода, генерируемого компилятором в дизассемблере отладчика, и вручную оптимизировать программу на C/C++, если это нужно и возможно.
Программирование микроконтроллеров. С чего начать?

Достаточно часто в личке ко мне обращаются люди с просьбой дать ссылки на полезные сайты, нужную информацию по программированию микроконтроллеров, необходимые программы и т.п. находясь при этом в самом начале своего познания микроконтроллеров. Сам я проходил через это буквально полтора года назад, имея нулевые знания и знаю, насколько это сложно, дать себе первоначального пинка, разобраться в лавине информации по микроконтроллерам, которую выдают поисковики, когда на тебя обрушивается куча непонятной информации и т. п.
Постараюсь объяснить на простом языке, для людей, умеющих держать паяльник, знающих, что такое цифровая микросхема логики, умеющих читать схемы и пользоваться мультиметром.
Микроконтроллеры бывают разных фирм, которые делают одно и тоже дело, но разными методами. Сравнить это можно с человеческими расами: европейцы, китайцы и африканцы например. Я лично работаю с микроконтроллерами фирмы Атмел, про них и буду говорить. Ну уж пошло сравнение с расами, пускай это будут европейцы.) Программы для микроконтроллеров пишут на языках программирования. Я рекомендую начать с языка Си. Это древний и простой язык. Для написания текста програмы используют программы компиляторы. Они позволяют создавать, редактировать и переваривать написанный программистом текст программы в код (прошивку), который можно загрузить (прошить) в микроконтроллер. Таких программ есть множество. Пример для Атмел: Code VisionAVR, родная от Атмел AVR Studio, Bascom-avr и ещё.
Эти программы делают одно и тоже дело, но своими методами, особенностями достоинствами и недостатками. При это текст Си в тих программах компиляторах немного отличается, но в общем похож. Можно сравнить с различием украинского, русского и белорусского языка. Я использую Code VisionAVR, что и советую начинающим.
Далее я приведу простой текст программы, написанный на языке Си в компиляторе Code VisionAVR для микроконтроллера ATTiny13A. В конце темы есть проект, прошивка и проект для эмулятора протеуса. Микроконтроллер в этой программе умеет делать простую вещь: при помощи кнопки менять логическое состояние на двух выходах, при этом короткое нажатие меняет состояние первого выхода а длинное — второго. В автомобиле например эту схему можно применить для управления одной кнопкой обогревом заднего стекла (которая есть у многих штатно) и добавленным обогревом зеркал. Нажал коротко на кнопку — сработал обогрев стекла, нажал ещё — обогрев стекла выключился. Если нажать и удерживать кнопку, то через какое-то время включиться обогрев зеркал. Если нажать и удерживать кнопку повторно — обогрев зеркал отключится.
Для понятия текста нужно знать грамматику, правила писанины языка Си, этого материала в интернете предостаточно. Так же желательно ознакомиться хотя бы с материалом, по использованию мастера создания проектов в CodeVisionAVR.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
www.hpinfotech.com
Project :
Version :
Date : 28.01.2012
Author :
Company :
Comments:
Chip type : ATtiny13A
AVR Core Clock frequency: 9,600000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 16
*****************************************************/
unsigned char b, trig;
void main(void)
// Declare your local variables here
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTB=0x01;
DDRB=0x06;
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
GIMSK=0x00;
MCUCR=0x00;
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;
А теперь поподробнее.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
www.hpinfotech.com
Project :
Version :
Date : 28.01.2012
Author :
Company :
Comments:
Chip type : ATtiny13A
AVR Core Clock frequency: 9,600000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 16
*****************************************************/
Это шапка, в которой содержится описание проекта, необходимые данные. Текст закомментирован знаками комментария /* в начале и */ в конце. Все, что находится между этими знаками программой не выполняется. Самое полезное здесь это указание типа микроконтроллера и его частота.
Это ссылка на библиотеку. Если какая либо библиотека необходима, то она должна быть здесь указана. У нас есть библиотека самого микроконтроллера tiny13a.h, и библиотека задержек времени.
unsigned char a, b, trig;
Объявление трех переменных. unsigned char . Что это такое можно посмотреть здесь Вообще всё непонятное копируем в буфер и ищем в поисковике.
void main(void)
// Declare your local variables here
void main(void) — это оператор, говорящий что началась основная часть программы на Cи и микроконтроллер будет её с этого места выполнять. Все что начинается с // — это комментарий. Старайтесь чаще ими пользоваться. Вообще конкретный комментарий генерирует сам компилятор, как и во многих других местах. Большинство комментариев я удалил, что уменьшить текст.
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
В комментарии по английски написано, что это такое. Это первая команда микроконтроллеру, одна из команд, которая настраивает нужные функции, порты и необходимые части микроконтроллера, необходимые для его работы и запуска.
Конкретно это настройка частоты делителя тактовой частоты микроконтроллера. Теперь подробнее:
Микроконтроллер имеет тактовый генератор, который задается в мастере и который потом можно изменить в свойствах проекта если что. У нас эта частота 9.6 мегагерца, как видно в шапке.
При прошивке микроконтроллера эту же частоту нужно указать во фьюзах.
CLKPR=0x80; и CLKPR=0x00; это команды настройки регистра внутреннего делителя этой частоты. Задается оно в мастере в первом окне «CHIP». Если у нас выбран делитель 1, то тактовая частота делиться на 1, то есть остается без изменений. Если указать например делитель 128, то соответственно тактовая частота делиться на это число. 9.6Мгц / 128 = 75кГц. и значения регистра делителя будет выглядеть:
CLKPR=0x80;
CLKPR=0x07;
Особо внимательные заметили, в регистр делителя CLKPR сначала пишется число 0x80 а затем сразу 0x00. Нафига пишется сначала одно значение а потом сразу другое? Если у вас возникают какие либо вопросы по регистрам и не только, приучайтесь сразу читать даташиты. Там все подробные ответы на чистом английском языке. Открываете даташит, вставляете в поисковик текста название регистра (CLKPR ) и ищете его описание, за что какие биты данного регистра отвечают. Конкретно у этого регистра для изменения делителя необходимо записать единичку в седьмой бит, после чего микроконтроллер даст изменить и выбрать необходимый делитель в первых четырех битах этого регистра. После того, как пройдет четыре такта выполнения команд процессора, изменить регистр будет уже нельзя. Нужно снова сначала изменить седьмой бит CLKPR=0x80 а затем указать делитель CLKPR=нужный делитель
PORTB=0x01;
DDRB=0x06;
Команды управления и настройкой портов микроконтроллеров — ножек чипа. Задается тоже в мастере. В этих регистрах задается работа на вход порта PB0 и подключается к нему внутренний Pull-up резистор. Порты PB1 и PB2 настраиваются «на выход» с логическим нулем на выходе в их состоянии.
В колонке DataDitection мы указывает тип порта: вход или выход (in или out)
В колонке PullUp/Output Value указываем подключение подтягивающего резистора pullup если порт настроен на вход (P — подключен, Т — неподключен) Если порт настроен на выход, то можно указать его логическое состояние 0 или 1. У нас нули. Строчки Bit0 — Bit5 это порты микроконтроллера PORTB0 — PORTB5
Если посмотреть сгенерированный компилятором комментарий, то можно увидеть соответствие пинов и их настройку:
// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=In
// State5=T State4=T State3=T State2=0 State1=0 State0=P
Если перевести из 16-тиричного в двоичный значение регистров, то можно понять даже без даташита назначение битов в регистре:
PORTB=0x01 PORTB=0b00000001
DDRB=0x06 DDRB=0b00000110
Напоминаю, что при разложении в двоичный код младшие значения справа а старшие слева.
Незначащие нули слева можно не писать:
PORTB=0b1;
DDRB=0b110;
А можно вообще написать в десятичной системе:
PORTB=1;
DDRB=6;
Далее по тексту кода идет:
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK0=0x00;
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;
ADCSRA=0x00;
Настройка таймера микроконтроллера, прерываний, АЦП, компаратора и всего такого пока сложного. Пока его не используем — рановато. У всех этих регистров стоят в значениях нули, это значит, что они отключены. А особо внимательные заметили, что какой-то регистр ACSR имеет значение =0x80; Лезем в даташит и читаем:
Analog Comparator Control and Status Register – ACSR
Вообще, как правило название всех регистров это сокращение от первых букв или части их полного названия.
Если стоит значение данного регистра 0x80, значит в двоичной системе это число 10000000, значит стоит единичка в 7 бите этого регистра, значит читаем в даташите, что он означает:
• Bit 7 – ACD: Analog Comparator Disable
When this bit is written logic one, the power to the Analog Comparator is switched off.
This bit can be set at any time to turn off the Analog Comparator. This will reduce power
consumption in Active and Idle mode. When changing the ACD bit, the Analog Comparator
Interrupt must be disabled by clearing the ACIE bit in ACSR. Otherwise an interrupt
can occur when the bit is changed.
По-русски это означает, что установка единицы в этом бите отключает аналоговый компаратор, что его можно выключить в любой момент, что это приводит к снижению потребления электричества, и в конце текста написано про зависимости и что нужно соблюдать, если нужно изменять этот бит.
После того, как микроконтроллер настроен запущен и выполнена инициализация необходимых частей и выполнены необходимые первоначальные команды в void main(void) в дело вступает его величество главный цикл. Все что находиться внутри этого главного цикла while (1) и заключено в скобки начала и конца > будет крутиться, команды выполняться по кругу от начал до конца. А у нас в нашем коде будет крутиться алгоритм опроса кнопки, подключенной к порту PB0, от состояния которой (нажата кнопка или нет) будет меняться состояние выходных портов PB1 и PB2
На картинке видна схема собранную в эмуляторе Протеус схему, которая позволяет видеть работу кода программы.
Теперь про сами основные команды, которые находятся внутри цикла. Все команды используют один оператор if Это условие ЕСЛИ.
Если в регистре PINB в бите, отвечающем за порт PB0 микроконтроллера.0 содержится значение равное нулю ==0, то выполняем кучку кода, которая находится далее в границах скобок и >
Короче, если нажата кнопка то выполняется следующий код в границах последующих скобок и >
Далее после кучки кода в скобках видим оператор else и ещё кучку кода за ним в скобках и >
Оператор else переводится не как ещё а как иначе
Оператор if и else всегда работают в паре, сначала идет if затем else. Оператор else можно не использовать совсем, если он не нужен.
В нашей ситуации алгоритм можно описать так:
если (нажата кнопка подключенная к порту PB0)
то выполняем кучку кода;
>
иначе (кнопка не нажата)
выполняем эту кучку кода;
>
Так как это все находится внутри главного цикла, то этот код будет выполняться по кругу, будет постоянно опрашиваться кнопка и будет выполняться нужная кучка кода
Теперь рассмотрим кучку кода, которая выполняется, если кнопка нажата:
Операторы можно вкладывать друг в друга, как матрешку. то есть выполняется одно условие, потом если условие сработало, то другое внутри первого условия и т.д.
Если переменное значение trig равняется нулю, то выполняем инкремент переменной b Инкремент — операция увеличения значения, хранящегося в переменной, на 1. То есть при проходе выполнения кода, если процессор натыкается на команду инкремента b++, то процессор прибавляет единичку в число, которое находится в переменной b
Так же здесь применяется упрощенная «орфография» написания условия и команды, без скобок и >:
Такое представление используют, если после условия всего одна команда.
Немного отвлеклись, возвращаемся:
if (trig==0) b++; — если значение переменной равно нулю (а оно у нас равно нулю) то выполняем инкремент переменной b — переменная в была равна нулю, теперь стало единице.
Если переменная b больше ста, то выполняем кучку кода внутри скобок.
Переменная b за каждый круг цикла прибавляется на единичку и в итоге через сто «кругов» главного цикла выполниться условие, которая находится далее внутри скобок и >
Теперь рассмотрим что же там делается, если нажата кнопка, если прошло сто кругов цикла:
if (PINB.2==0)PORTB.2=1;
else PORTB.2=0;
trig=1;
b=0;
Здесь мы видим ещё одно условие (жирная такая матрешка получилась))
if (PINB.2==0)PORTB.2=1;
Если регистр состояния выходного порта PB, а точнее PB2 равен нулю, то меняем его состояние на единичку PORTB.2=1.
else PORTB.2=0;
Иначе пишем в регистр нолик. Или если по-другому: если регистр состояния выходного порта PB2 равен единице, то меняем его на ноль.
Короче если происходит выполнение этих условий и команд, то меняется логическое состояние выхода 2 (PB2) на схеме.
Если полностью описать: если нажата кнопка, если прошло сто кругов главного цикла, то меняем логическое состояние выхода 2 — PORTB.2 в коде он же порт PB2 на схеме.
Как уже стало понятно этот кусок кода отрабатывает длительное нажатие кнопки.
Но этого мало, дальше ещё есть две выполняемые команды присвоения:
trig=1; присвоение единице этой переменной необходимо, что бы описанное выше условие работы инкремента b++ перестало работать
b=0; обнуляем переменную b.
В итоге при длительном нажатии кнопки, условие при котором меняется состояние порта PB2 выполняется единожды, до тех пор, пока кнопка не будет отжата кнопка, ибо инкремент не будет работать и условие if (b>100) больше не сработает, если тупо нажать кнопку и не отпускать совсем.
Теперь вторая часть кучки кода, которая следует за первым условием:
else
if (b>4)
if (PINB.1==0)PORTB.1=1;
else PORTB.1=0;
b=0;
>
b=0;
trig=0;
>
Если кнопка отжата:
Опишем её с конца:
trig=0; присваиваем переменной trig значение ноль. Необходимо, что бы после длительного нажатия, когда наступит последующее отжатие кнопки микроконтроллер снова был готов к нажатиям кнопки ( срабатывало условие инкремента if (trig==0) b++;)
b=0; При не нажатой кнопке значение переменной b равняется нулю.
if (b>4)
if (PINB.1==0)PORTB.1=1;
else PORTB.1=0;
b=0;
>
Подробнее:
if (b>4)
Если значение переменной b больше четырех, то выполняем следующий код:
if (PINB.1==0)PORTB.1=1;
else PORTB.1=0;
Если состояние порта BP1 равно нулю, то делаем единицу, если нет, то ноль.
Это условие и команда отрабатывает кроткое нажатие кнопки. Если нажата кнопка, то начинает работать инкремент b++; значение которого начинает увеличиваться. Если отжать кнопку и при этом значение переменной b будет больше четырех ( но меньше ста — а то сработает длинное нажатие) то состояние выходного порта PB1 (он же выход 1 на схеме, он же PORTB.1 в коде) поменяется, сработает алгоритм короткого нажатия кнопки.
Если значение переменной b при отжатии меньше четырех, то условие не срабатывает и ничего не происходит. необходимо для работы «дребезга контактов» и ложных срабатываний.
И последнее это присвоение переменной b нулевого значения, что бы обработка алгоритма короткого нажатия происходило единожды.
В оконцовке главного цикла виднеется команда:
Это задержка в главном цикле. То есть, выполняется пошагово команды, затем процессор натыкается на команду delay_ms(10); и начинает её выполнять. В итоге процессор будет 10 миллисекунд ждать и ничего не делать в этой строчке, затем опять приступит к выполнению команд.
Находясь в одном общем цикле, скорость нарастания значения инкремента b++ зависит от времени задержки, указанной в delay_ms.
Команда delay_ms находится в библиотеке задержек #include , которую мы для этого и включили в начале кода.
Как видно из описания, длинное нажатие срабатывает от фронта сигнала нажатия кнопки ( начинает работать инкремент) а короткое нажатие кнопки — по спаду, то есть срабатывает по отжатию кнопки.
Вообще выполняемая здесь последовательность: условие + инкремент достаточно часто используемая команда и в языке Си присутствует отдельный оператор для этого for
Архив с прошивкой, исходником и моделью Протеуса:
umat.ru/files/Button_13.zip
ВНИМАНИЕ!
Архив перезалил 22 сентября 2014 года, обнаружил косяк в выставленной частоте в проекте. Теперь тактовая частота 1.2 Мегагерца, при этом фьюзы стоят по дефолту и их при прошивке трогать вообще не надо