Сниппеты AVR. Настройка портов I/O для реакции на нажатие кнопки

👁 27 просмотров

Допустим, есть банальная задача написания кода для реагирования на нажатие кнопки, которая подключена к ножке микроконтроллера A. После нажатия на кнопку сигнал нажатой появится на ножке B и включится лампочка.

Схема подключения микроконтроллера

Код на ассемблере

; project.asm
;
; Created: 23.11.2017 16:49:01
; Author : WebSofter
;

.list
.def temp = R16			;Определяем переменный регистр
.cseg					;Устанавливаем текущую рабочую память

;Настриваем PORT A
ldi temp, 0x00			;Записываем константу для DDRA
out DDRA, temp			;В порт управления записываем 0. Будет работать на ввод
ldi temp, 0xff			;Записываем константу для PORTA
out PORTA, temp			;A порт вывода записываем 1. Будет полдключен внутренний резистор
;Настриваем PORT B
ldi temp, 0xFF			;Записываем константу для DDRB
out DDRB, temp			;В порт управления записываем 1. Будет работать на вывод

;Организуем бесконечный цикл чтения сигнала нажатия
main:					;Метка цикла
	in temp, PINA		;Читаем сигналы с PIN
	out PORTB, temp		;Записываем в порт на вывод
rjmp main				;Операция перехода к метке

 

Код на C/C++

/*
 * GccProject.c
 *
 * Created: 23.11.2017 21:39:37
 * Author : WebSofter
 */ 

#include <avr/io.h>


int main(void)
{
    //Настрояка порта A
	DDRA = 0x00;//Установка напрвления на ввод
	PORTA = 0xFF;//Подключение внутреннего резистора
	//Настрояка порта B
	DDRB = 0xFF;//Устновка направления на вывод
	PORTB = 0xFF;//Начальная установка
	
    while (1) //Бесконечный цикл
    {
		PORTB = PINA;//Записываем нажатый пин из A в B
    }
}

 

Система команд ассемблера для Atmel AVR

👁 99 просмотров

Предисловие

Подобных страниц, описывающих систему команд данной замечательной архитектуры микропроцессора очень много в сети Интернет. Поэтому не хотелось бы создать очередной обычный «велосипед», но наш «велосипед» будет особенным. Особенностью данной страницы будет то, чтобы вы не утруждались нажимать на ссылки на сторонние ресурсы и не утруждались по крупинкам собирать недостающие части информации по теме. Это очень удобно, если читаете через экран мобильного устройства или планшета.

Регистр статуса (SREG)

SREG: Регистр статуса
C: Флаг переноса
Z: Флаг нулевого значения
N: Флаг отрицательного значения
V: Флаг-указатель переполнения дополнения до двух
S: NЕV, Для проверок со знаком
H: Флаг полупереноса
T: Флаг пересылки, используемый командами BLD и BST
I: Флаг разрешения/запрещения глобального прерывания
Регистры и операнды
Rd: Регистр назначения (и источник) в регистровом файле
Rr: Регистр источник в регистровом файле
R: Результат выполнения команды
K: Литерал или байт данных (8 бит)
k: Данные адреса константы для счетчика программ
b: Бит в регистровом файле или I/O регистр (3 бита)
s: Бит в регистре статуса (3 бита)
X, Y, Z: Регистр косвенной адресации (X=R27:R26, Y=R29:R28, Z=R31:R30)
P: Адрес I/O порта
q: Смещение при прямой адресации (6 бит)

I/O регистры

RAMPX, RAMPY, RAMPZ: Регистры связанные с X, Y и Z регистрами, обеспечивающие косвенную адресацию всей области СОЗУ микроконтроллера с объемом СОЗУ более 64 Кбайт

Стек

STACK: Стек для адреса возврата и опущенных в стек регистров
SP: Указатель стека

Флаги

Флаг, на который воздействует команда
0 Очищенный командой Флаг
1 Установленный командой флаг
Флаг, на который не воздействует команда

Описание команд

ADC - Add with Carry, Сложить с переносом

Описание:
Сложение двух регистров и содержимого флага переноса (С), размещение результата в регистре назначения Rd.

Операнды:

Rd, Rr
Операция:

(i) Rd ← Rd + Rr + C
Синтаксис Операнды Счетчик программы
(i) ADC Rd, Rr 0 ≤ d ≤ 31, 0 ≤ r ≤ 31 PC ← PC + 1

16-разрядный код операции:

0001 11rd dddd rrrr

Булевые выражения регистра статуса (SREG):

I T H S V N Z C
H Rd3•Rr3 + Rr3 + R3 + R3•Rd3
Устанавливается если есть перенос из бита 3, в ином случае очищается
S N⊕V, Для проверок со знаком
V Rd7•Rr7•R7 + Rd7•Rr7•R7
N R7
Устанавливается если в результате установлен MSB, в ином случае очищается
Z Rd7•Rr7•R7•R7•R7•Rd7
Устанавливается если результат $00, в ином случае очищается
C Rd7•Rr7 + Rr7 + R7 + R7•Rd7
Устанавливается если есть перенос из MSB результата, в ином случае очищается
R (Результат) соответствует Rd после выполнения команды

Пример:

           ;СложитьR1 : R0 с R3 : R2
add r2, r0 ;Сложить младший байт
adc r3, r1 ;Сложить старший байт с переносом

w Слов:
1 (2 байта)
Циклов:
1

ADD - Add without Carry, Сложить без переноса

Описание:
Сложение двух регистров без добавления содержимого флага переноса (С), размещение результата в регистре назначения Rd.

Операнды:

Rd, Rr
Операция:

(i) Rd ← Rd + Rr + C
Синтаксис Операнды Счетчик программы
(i) ADC Rd, Rr 0 ≤ d ≤ 31, 0 ≤ r ≤ 31 PC ← PC + 1

16-разрядный код операции:

0001 11rd dddd rrrr

Булевые выражения регистра статуса (SREG):

I T H S V N Z C
H Rd7•Rr7•R7 + Rd7•Rr7•R7
Устанавливается если в результате операции образуется переполнение дополнения до двух, в ином случае очищается
S N⊕V, Для проверок со знаком
V Rd7•Rr7•R7 + Rd7•Rr7•R7
N R7
Устанавливается если в результате установлен MSB, в ином случае очищается
Z R7•R6•R5•R4•R3•R2•R1•R0
Устанавливается если результат $00, в ином случае очищается
C Rd7•Rr7+Rr7•R7+R7•Rd7
Устанавливается если есть перенос из MSB результата, в ином случае очищается
R (Результат) соответствует Rd после выполнения команды

Пример:

add r1,r2   ; Сложить r2 с r1 (r1=r1+r2)
adc r28,r28 ; Сложить r28 с самим собой
              (r28=r28+r28)

w Слов:
1 (2 байта)
Циклов:
1

ADIW - Add Immediate to Word, Сложить непосредственное значение со словом

Описание:
Сложение непосредственного значения (0-63) с парой регистров и размещение результата в паре регистров. Команда работает с четырьмя верхними парами регистров, удобна для работы с регистрами указателями.

Операнды:

Rd, K
Операция:

(i) Rdh:Rdl ← Rdh:Rdl + K
Синтаксис Операнды Счетчик программы
(i) ADIW Rdl, K dl ∈ {24,26,28,30}, 0 ≤ K ≤ 63 PC ← PC + 1

16-разрядный код операции:

1001 0110 KKdd KKKK

Булевые выражения регистра статуса (SREG):

I T H S V N Z C
S N⊕V, Для проверок со знаком
V Rdh7 R15
N R15
Устанавливается если в результате установлен MSB, в ином случае очищается
Z R15•R14•R13•R12•R11•R10•R9•R8•R7•R6•R5•R4•R3•R2
Устанавливается если результат $0000, в ином случае очищается
C R15•Rdh7
Устанавливается если есть перенос из MSB результата, в ином случае очищается
R (Результат) соответствует Rdh:Rdl после выполнения команды (Rdh7 — Rdh0 = R15 — R8, Rdl7 — Rdl0 = R7 — R0)

Пример:

adiw r24, 1  ; Сложить 1 с r25:r24
adiw r30, 63 ; Сложить 63 с Z указателем (r31 : r30)

w Слов:
1 (2 байта)
Циклов:
2

 

Продолжение следует…

ISP — интерфейс микроконтроллеров AVR

👁 36 просмотров

Перед началом вхождения в практику мы должны иметь несколько основополагающих знаний и умений использовать последовательное программирование для семейства AVR. Нет, вам не нужно использовать 3 провода для программирования и чтения FLASH – памяти AVR, вам не нужен другой запрограммированный микропроцессор для программирования AVR, вам не нужны 10 I/O линий, чтобы сказать чипу, что вы с ней хотите сделать и вам не нужно отсоединить каждый раз чип AVR из гнезда экспериментальной платы перед программированием. Это очень легко – в AVR есть специальный интерфейс программирования, который позволяет читать и писать из программной FLASH – памяти, EEPROM – памяти. Данный интерфейс является последовательным, т.е. биты программы читаются и записываются последовательно по двум проводам, а третий является общим проводом:

  • SCK: тактовый сигнал, для сдвига битов, записываемые в память, во внутренний сдвиговый регистр;
  • MOSI: на этом проводе будут сигналы данных, записываемые в AVR;
  • MISO: на этом проводе будут сигналы данных, записываемые из AVR.

Эти три сигнальных пина внутренне соединены к программной машине, если вы изменили RESET (иногда именуется, как RST или restart) – пин на нуль. В противном случае, в процессе нормальной работы AVR, эти пины работают как обычные пины I/O. Пины, в данном случае, – это физические выводы микроконтроллера. Если вы также используете данные пины для других целей в случае нормальной работы и системного программирования вы должны позаботиться о том, чтобы эти ваш две цели между собой не конфликтовали.

Способы тестирования программы для AVR

👁 48 просмотров

Изучение ассемблера требует некоторого простого оборудования для тестирования вашей программы и для просмотра ее работы на практике. Данный шаг покажет 2 простые схемы, которые позволят вам прошить и тестировать вашу программу:

  • на основе реального микроконтроллера AVR;
  • на основе программного симулятора Proteus.

Для продвинутого использования и обучения всей периферии микроконтроллера можно закупить готовую отладочную плату, но я не сторонник их использования и для начинающих будет трудновато им пользоваться. Лучшим вариантом, на мой взгляд, является использование виртуального симулятора Proteus, в котором есть все необходимое для начального обучения. Но ярые материалисты могут использовать и реальный микроконтроллер. В данном шаге будут показаны 2 способа прошмвки реального микроконтроллера:

  • при помощи COM — порта;
  • при помощи USB — интерфейся.

Высокоуровневые языки и ассемблер

👁 61 просмотров

Высокоуровневые языки внедряют дополнительный непрозрачные разделительные уровни между ЦПУ и исходным кодом. Примером такой непрозрачной концепции являются переменные. Эти переменные имеют хранилища, которые могут хранить числа, текстовую строку или простое булевое значение. В исходном коде имя переменной представляет место, где находиться переменное значение, определенное для определенного типа: числа с его форматом, строки с ее длиной и т.д. Для изучения ассемблера надо просто забыть про концепцию переменных в высокоуровневом языке. Ассемблер знает только биты, баты, регистры и байты SRAM. Термин «переменные» не имеет смысла в ассемблере. Кроме того, связанные термины, как «типы» бесполезны и не имеют никакого смысла здесь.
Высокоуровневые языки требуют от тебя определения переменных перед их использованием в исходном коде, например, как типы Byte (8-bit), double word (16-bit), integer (15-bit плюс 1 знак бита). Компиляторы для данного высокоуровневого языка перемещают такие задекларированные (определенные) переменные в любое доступное хранилище, включая и 32 регистра общего назначения, которые есть у AVR. Размещением переменных в регистры занимается компилятор, который сам выбирает место хранения по определенным приоритетным правилам, словно этим занят программист на ассемблере и вся рутинная работа в операциях с данными ложитья на плечи компилятора. Программист может только догадываться, о чем компилятор «думал», когда перемещал переменную в ту или иную ячейку памяти или регистр и право на решение заключено за компилятором. Это снимает с программиста неприятностей, связанных с решениями хранения переменных, но, в некотором смысле, делает и рабом компилятора. Инструкция «A = A + B» теперь типизирована: если «A» определен, как символ, а «B» — как число, то формулировка будет неправильной, так как число нельзя оперировать сложением с символом строки. Программисты на языках высокого уровня предполагают, что ошибка о неправильных формулировках операций позволяет им избегать различных глупостей при написании кода. Защита, которую предоставляет компилятор, данном случае, запрещающая использование разных типов в операторе сложения, довольно бесполезна: добавление 2 к символу «F», конечно, должно привести к «H», как результат, так как на уровне железа это все бинарные цифры и только на уровне компилятора высокого уровня типы делятся на строки, символы, целые числа, числа с плавающей точкой и т.д.
Ассемблер позволяет вам сложить числа, такие как 7 или 48, вычитать байтовые хранилища, не вдаваясь в то какие типы хранятся в этих хранилищах. Что находиться в каждом хранилище определяет не компилятор, а сам программист на ассемблере. Если, например, четыре регистра представляют одно 32 – битное число или четыре символа ASCII, то эти четыре байта могут быть размещены в регистрах как low-to-high, high-to-low или в полностью смешанном виде самим программистом. Программист, в ассемблере, является главным в решении размещения данных и самостоятельно должен контролировать весь процесс отладки. Типы неизвестны, все значения находятся в виде битов и байтов, доступных в любом хранилище данных (регистрах или SRAM). Программист должен не только организовать хранение данных, но и оптимизировать их работу, что не скажешь о программистах языков высокого уровня, которые ограничены в этом.

Интерпретация и ассемблер

👁 50 просмотров

С интерпретацией ЦПУ, в первую очередь, транслирует человеко-читабельный код в бинарные слова, чтобы ЦПУ смог их выполнить. Интерпретатор должен:

  • первым делом читает текстовый поток «A = A + B» (девятый символ у каждого байта);
  • пропустить 4 пробела из текста;
  • находить переменные A и B (находящиеся в регистрах или в SRAM, точность/длина, и т.д.);
  • идентифицировать символ «+», как оператор сложения;
  • подготовить машинно-ориентированную последовательность, которая эквивалентна в текстовой форме на ассемблере.

В последствии, будет вероятный простой машинный код, похожий на «ADD R0, R1» (в ассемблере). Но, скорее всего, конечный машинный код будет несколько длиннее, чем ассемблерный, так как помимо одной операции сложения процессору еще нужно читать, записать переменные из/в SRAM, сложить 8-битные целые числа, сохранить/перезаписать регистры в стек и т.д.
Различие между интерпретацией и ассемблированием кода в том, что после интерпретации ЦПУ получает привилегированную «еду», полностью выполняемые слова. При интерпретации процессор, в течение большей части времени, выполняет задачу трансляции. Трансляция требует, примерно, 20 или 200 шагов ЦПУ, перед три или четыре словами может быть выполнен. Скорость выполнения высокая обычно некритична для общей работы процессора. Если требуется большая скорость выполнения, то не проблема это решить, поставив генератор тактовой частоты большего значения. Низкая скорость неуместна во время критических ситуаций, где требуется быстрая реакция на события. Никто не знает, что процессор точно будет делать и как долго это продолжиться.

Различия с языками высокого уровня

👁 54 просмотров

Вот некоторые подсказки для программистов на языках высокого уровня. В языках высокого уровня конструкции или инструкции языка не зависят от аппаратной части чипа или возможностей ЦПУ. Эти конструкции(инструкции) работают на самых различных процессорах, если имеется компилятор для данного языка и в ней имеется возможность компилировать код для того или иного семейства процессора. Компилятор транслирует конструкции языка высокого уровня в объектный бинарный код для того или иного процессора. Язык высокого уровня призван облегчить процесс написания кода и уменьшить затрачиваемое на это время. Между языками высокого уровня и ассемблером мало схожестей, но могут попасться похожие по действию команды, например, GOTO в языке BASIC схож по функциональности с конструкцией JMP в языке ассемблер, но они разные в плане внутренней организации. Использование одного и того же кода программы для другого процессора будет работать только тогда, если конструкции в этом языке определены для обеих этих процессоров. Если ЦПУ процессора не имеет доступ к 16-битному таймеру, то компилятор языка высокого уровня может симулировать только 8 – битный таймер, который имеется в наличии у данного типа процессора. Если три таймера имеются в наличии у микроконтроллера, а компилятор позволяет использовать только два из них, то оставшийся нельзя будет использовать в дальнейшем и для его использования потребуется использовать либо ассемблерные вставки в код языка высокого уровня либо полностью написать программу на ассемблере.
Таким образом, используя язык высокого уровня вы полностью оказываетесь зависимы от возможностей компилятора для того или иного семейства процессора, но не от возможностей самого процессора. Другой пример к вышеперечисленным – это инструкция «MUL». В ассемблере только целевой процессор определяет можете ли вы использовать данную инструкцию, если вы захотите использовать операцию умножения. А что касается языка высокого уровня, то вам здесь не стоит об этом беспокоиться, он не зависит от возможностей процессора и обычно, вам придется использовать специальную математическую библиотеку, в которой определены все математические операции, если даже такая операция не определена в возможностях самого процессора, но она реализована в самом языке при помощи комбинации операций сложения.

difference-bitween-c-and-asm-langsБиблиотека предлагает умножить также целое(integer), длинное целое (long) даже если у вас микроконтроллер является 8-битной. Но нужно заметить одну существенную вещь – если вы будете использовать такие «грозные» операции языка высокого уровня на микроконтроллерах с меньшим количеством FLASH — памяти семейства ATiny AVR, то вы быстро исчерпаете ее и придется использовать микроконтроллера ATMega или XMega AVR с большей памятью, но опять таки в нем будут не использованы множество встроенных функций, если в вашу задачу не входит их использование. Поэтому, в таких ситуация предпочтительнее использовать язык ассемблер, как компактный и быстрый язык.

 

Инструкции ассемблера AVR

👁 55 просмотров

Так как команды представляют из себя 16-ти битные числа, то имеется необходимость читать эти 16-ти битные числа команд и запоминать, в соответствии с порядком расположения битов в числе – это было бы неразумно, поэтому в ассемблере используются человеко-читабельные абревиатуры для каждой команды и констант, вместо 16-битных чисел. Они еще называются мнемониками и призваны для лучшего запоминания, чем для увеличения производительности процессора. Вся суть процессора заключается в оперировании двоичными числами и лишь через ассемблер мы можем оперировать мнемокодами, константами и числами в десятичной и шестнадцатеричном формате. К примеру, ассемблерная презентация команды в виде числа 9588 будет мнемокод «SLEEP». В противоположность 9588 запись данной команды в виде ассемблерного мнемокода «SLEEP» – гораздо легче запомнить и оперировать им в уме, чем просто число.
Команда суммирования будет просто «ADD». Чтобы указать регистры, значения в которых нужно суммировать надо записать их в виде параметров. Передача параметров в ассемблере – это не одно и тоже, что и передача параметров в С/С++, в ассемблере для этого не используются скобки, как в С/С++, а записывается следующим образом как
ADD R0, R1
Эта запись заставит процессор сложить значения регистров R0 и R1, а результат сложения записать в R0.

avr-assembler-translation-processПосле трансляции данная команда будет переводиться в 16-ти битное слово 0C01(«слово» на сленге программирования означает 16-битное число) и подобным образом транслируется в цифры весь человеко-читабельный код на ассемблере. Для того, чтобы записать полученный код в память микроконтроллера нужно компилировать программу. Компиляция – это процесс генерации объектного файла, в котором будет код из 1 и 0 и ничего больше. Данный файл необходим для записи в память, а чтобы записать нужно использовать программатор, который будет прожигать чип памяти программы в соответствии с объектным кодом на физическом уровне. Об этом мы еще поговорим.
ЦПУ понимает только значение 0C01 в формате 110000000001. После записи данной команды в память программы (FLASH – память) микроконтроллера, ЦПУ читает эту команду с параметрами и выполняет данную команду на физическом уровне записывая и перезаписывая биты в регистрах. Каждая команда, которую понимает ЦПУ имеет свое мнемоническое обозначение в ассемблере и наоборот – каждая мнемоническая команда имеет, понимаемую ЦПУ, инструкцию в виде двоичного кода, которая выполняет строго определенное действие с переданными ей параметрами. Возможности ЦПУ ограничены и определяются инструкциями, которые доступны в конечном ассемблерном языке. Ассемблер – это, своего рода, отражение того языка из 1 и 0, которое понимается процессором на физическом уровне и его можно считать базовым, который доступен для всех программируемых чипов.

 

Как работает ЦПУ (CPU) AVR

👁 42 просмотров

Очень значимо понимание работы ЦПУ (Центральное Процессорное Устройство) для понимания и хорошего освоения языка ассемблера. ЦПУ читает инструкции (берет инструкцию) из программной памяти (FLASH – память), транслирует его во внутренние выполняемые шаги и выполняет ее. В AVR каждая инструкция имеет длину в 16 бит внутри FLASH – памяти и читаются оттуда за один шаг (за один такт тактового генератора). Если проследить весь этап работы ЦПУ, то это будет выглядеть вот так:

  • команда читается(первый шаг);
  • транслируется(второй шаг);
  • читается числа из программной памяти в регистры R0 и R1, подставляя на входы АЛУ(третий шаг);
  • суммирует их(четвертый шаг);
  • записывает результат в регистр R0(пятый шаг).

Регистры представляют из себя простые 8 – битные хранилища, которыми может управлять АЛУ, читая или записывая из них информацию. Пример кодирования инструкции продемонстрирован на нижеуказанном примере

Операции ЦПУ Код (binary) Код (hex)
Отправка ЦПУ в спячку 1001.0101.1000.1000 9588
Суммировать значения в регистрах R1 и R0 0000.1100.0000.0001 0C01
Вычесть значение регистра R1 из значения регистра R0 0001.1000.0000.0001 1801
Записать константу 170 в регистр R16 1110.1010.0000.1010 EA0A
Умножить значение регистра R3 со значением регистра R2 и записать значение в регистр R1 (MSB) и
R0 (LSB)
1001.1100.0011.0010 9C32

Итак, если ЦПУ читает число 9588 из FLASH – памяти, то ЦПУ больше не делает выборку инструкции. После каждой выборки счетчик команд увеличивается а единицу. Счетчик команд – это специальный регистр, который недоступен пользователю для записи, в нем храниться номер текущей команды в памяти программы. Он необходимо для создания условных и безусловных переходов внутри программы в пределах все области программной памяти.
Когда ЦПУ читает 0C01, то R0 и R1 суммируются и результат записывается в регистр R0. Данная операция продемонстрирована на рисунке
avr-hardware-how-toworkavr-cpu1.    Сперва читается инструкция с размером в 16 битное слово из памяти FLASH и транслируется в выполняемый шаг;
2.    Следующий шаг соединяет регистры R0 и R1 со входами АЛУ и АЛУ суммирует их содержимое;
3.    Далее результат записывается обратно в регистр R0.

Когда ЦПУ читает 9C23 из FLASH, то регистры R3 и R2 перемножаются и результат перезаписывается в R1(верхний 8 бит) и R0(нижний 8 бит). Если АЛУ не оборудован на аппаратном уровне устройством перемножения (как в ATtiny13), то с числом 9C23 ничего не делается.
В принципе ЦПУ может выполнить 65.536(16 – битных) различных инструкций из-за двухбайтовой системы команды во FLASH-памяти.
Когда записываем 170, то он должен быть записан в определенный регистр. Записываемое число в регистр может быть в пределах от 0 до 255 и может быть записан в любой регистр между R16 и R31.

 

 

Зачем учить ассемблер для AVR

👁 59 просмотров

Ассемблер или другие языки? Xто выбрать? Почему я должен выучить еще один язык, если уже выучил другие языки? Лучший ответ — это следующий аргумент: когда вы знаете английский и живете во Франции и общаетесь там на английском, то чувство неудобства общения никогда вас не покинет. Это потому что во Франции первоочередным и приоритетным будет является французский язык, на котором вас поймут где угодно в пределах страны.

Замечание! Данный курс по программированию микроконтроллеров не распространяется на процессоры ПК с операционными системами Linux/ Windows/Mac, не распространяется на обучение программирование сложных систем на подобие Ethernet, а отвечает только требованиям, которые необходимы для начинающих программировать на языке ассемблер без каких-либо языков высокого уровня.

Много разработчиков, имеющих большой опыт программирования для AVR и которые используют высокоуровневые языки(C/C++. Basic, Pascal…) в повседневной их работе рекомендует начинающим учить AVR на основе языка ассемблер. Причинами этого, чаще всего, являются следующие случаи:

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

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

Краткий и легкий

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

Быстрый и скоростной

Потому что выполняется только необходимый код шаг за шагом, за счет чего программа выполняется очень быстро. Продолжительность каждого шага известна и, обычно, он равен одному такту тактового резонатора. Критические ко времени программы, такие как измерители сигналов времен без аппаратного таймера, которые должны выполняться превосходно, должны быть написаны на ассемблера. Если у вас программа не прихотлива при выполнении ко времени и чип остается в 99% времени в режиме ожидания, то код можно написать на любом языке, на котором вы хотите.

Легок ли ассемблер в изучении?

Ассемблер очень сложен и не так легок в понимании, как другие, высокоуровневые языки. Изучение языка ассемблер для какой-либо типа процессора начинается с понимания базовых принципов архитектуры чипа и языковых диалектов. Одним словом – принцип и грамматика ассемблера одинаковы везде для любого процессора, но язык может отличаться грамматикой написания и диалектикой команд, отсутствием или присутствием команд той или иной операции. Высокоуровневые языки часто не позволяют использовать специальные функции микроконтроллера, так как они могут быть не реализованы для микроконтроллера и выходом из этой ситуации может быть использование вставка в код в высокоуровневый код ассемблерных вставок, чтобы использовать эту функцию.
Ассемблер очень хорош, если вы создаете программу в пределах 100 линий кода. Некоторые программы требуют до нескольких тысяч линий кода и для его оптимизации требуется много работы. То, что можно сделать нескольким линиями кода на языке высокого уровня на ассемблере идентичный код может быть написан десятками линий, но в то же время высокоуровневый язык более прожорлив к памяти, так как после компиляции программы инструкции языка высокого уровня транслируются в несколько инструкций языка ассемблера и дальше переводиться в машинный код, состоящий из единиц и нулей. Первый шаг в освоении для любого языка сложен, но после нескольких недель упорного самообучения можно уже осознанно программировать. Некоторые инструкции кода ассемблера можно понять через месяцы обучения программированию – это нормально.