Что такое система команд микроконтроллеров AVR. Какие основные группы команд существуют в AVR. Как программировать микроконтроллеры AVR на языке ассемблера. Какие инструменты нужны для разработки программ для AVR.
Содержание
Архитектура и особенности микроконтроллеров AVR
Микроконтроллеры AVR, разработанные компанией Atmel (ныне часть Microchip Technology), являются одним из самых популярных семейств 8-битных микроконтроллеров. Они обладают рядом особенностей, которые делают их привлекательными для разработчиков:
RISC-архитектура с быстрым однотактным выполнением большинства инструкций
Гарвардская архитектура с раздельной памятью для программ и данных
32 регистра общего назначения, напрямую подключенные к АЛУ
Встроенная Flash-память программ и EEPROM для данных
Широкий набор периферийных модулей (таймеры, АЦП, интерфейсы и др.)
Низкое энергопотребление и различные режимы сна
Такая архитектура позволяет эффективно выполнять программы и обрабатывать данные при низком энергопотреблении, что делает AVR отличным выбором для встраиваемых систем и устройств с батарейным питанием.
Основные группы команд системы команд AVR
Система команд микроконтроллеров AVR содержит более 130 различных инструкций. Их можно разделить на несколько основных групп:
1. Арифметические и логические команды
Эта группа включает команды для выполнения математических и логических операций над данными в регистрах. Некоторые примеры:
ADD — сложение двух регистров
SUB — вычитание
AND, OR, EOR — побитовые логические операции
INC, DEC — инкремент и декремент
2. Команды передачи данных
Эти инструкции используются для перемещения данных между регистрами, памятью и портами ввода-вывода:
MOV — копирование данных между регистрами
LDI — загрузка константы в регистр
LD, ST — загрузка и сохранение в память
IN, OUT — чтение и запись портов ввода-вывода
3. Команды передачи управления
Группа команд для организации переходов, вызовов подпрограмм и возвратов:
JMP, RJMP — безусловные переходы
CALL, RCALL — вызов подпрограмм
RET — возврат из подпрограммы
BREQ, BRNE и др. — условные переходы
Программирование микроконтроллеров AVR на ассемблере
Хотя сегодня большинство разработчиков предпочитает использовать языки высокого уровня, такие как C, знание ассемблера AVR может быть полезно для оптимизации критичных участков кода или лучшего понимания работы микроконтроллера.
Для программирования на ассемблере AVR необходимо знать:
Синтаксис команд и директив ассемблера
Структуру регистров и памяти микроконтроллера
Принципы работы стека и организации подпрограмм
Особенности работы с периферийными модулями через регистры
Вот простой пример программы на ассемблере AVR, которая мигает светодиодом, подключенным к порту B:
.include "tn2313def.inc"
.org 0
rjmp start
.org OVF0addr
rjmp timer0_ovf
start:
ldi r16, (1<<PB0)
out DDRB, r16
ldi r16, (1<<TOV0)
out TIFR, r16
ldi r16, (1<<TOIE0)
out TIMSK, r16
ldi r16, (1<<CS02)|(1<<CS00)
out TCCR0, r16
sei
loop:
rjmp loop
timer0_ovf:
in r16, PORTB
ldi r17, (1<<PB0)
eor r16, r17
out PORTB, r16
reti
Эта программа настраивает таймер 0 для генерации прерываний, в обработчике которых происходит переключение состояния светодиода.
Инструменты для разработки программ для AVR
Для разработки программ для микроконтроллеров AVR используются различные инструменты. Вот некоторые из наиболее популярных:
1. Atmel Studio (теперь Microchip Studio)
Это интегрированная среда разработки (IDE) от производителя микроконтроллеров. Она включает в себя:
Редактор кода с подсветкой синтаксиса
Компилятор C/C++ и ассемблер
Отладчик с поддержкой симуляции и отладки на реальном устройстве
Менеджер проектов
2. AVR-GCC и AVRDUDE
Это набор инструментов с открытым исходным кодом, включающий:
Компилятор GCC, адаптированный для AVR
Ассемблер и компоновщик
Утилиту AVRDUDE для прошивки микроконтроллеров
Эти инструменты можно использовать из командной строки или интегрировать в различные IDE.
3. PlatformIO
Это современная кросс-платформенная среда разработки, которая поддерживает множество плат и микроконтроллеров, включая AVR. Особенности PlatformIO:
Интеграция с популярными редакторами (VS Code, Atom и др.)
Автоматическое управление зависимостями и библиотеками
Поддержка различных фреймворков и платформ
Отладка программ для микроконтроллеров AVR
Отладка программ для встраиваемых систем, таких как микроконтроллеры AVR, может быть непростой задачей. Однако существует несколько методов и инструментов, которые облегчают этот процесс:
Симуляция
Многие среды разработки, включая Atmel Studio, предоставляют возможность симуляции работы микроконтроллера. Это позволяет:
Пошагово выполнять код
Просматривать и изменять содержимое регистров и памяти
Симулировать работу некоторых периферийных устройств
Симуляция особенно полезна на начальных этапах разработки, когда нужно проверить логику работы программы.
Аппаратная отладка
Для отладки на реальном устройстве используются специальные отладочные интерфейсы, такие как JTAG или debugWIRE. Они позволяют:
Устанавливать точки остановки в коде
Выполнять программу пошагово
Просматривать содержимое регистров и памяти в реальном времени
Для работы с этими интерфейсами требуются специальные программаторы-отладчики, например, Atmel-ICE или JTAGICE3.
Отладочная печать
В случаях, когда нет возможности использовать аппаратный отладчик, часто прибегают к отладочной печати. Это может быть:
Вывод информации через UART на компьютер
Использование светодиодов для индикации состояния программы
Запись отладочной информации во внутреннюю EEPROM для последующего анализа
Хотя этот метод менее удобен, он часто оказывается полезным при отладке в полевых условиях.
Оптимизация кода для микроконтроллеров AVR
Оптимизация кода для микроконтроллеров AVR может быть критически важной, особенно для устройств с ограниченными ресурсами или работающих от батарей. Вот несколько советов по оптимизации:
1. Использование регистров
AVR имеет 32 регистра общего назначения, которые работают гораздо быстрее, чем память. Старайтесь максимально использовать регистры для хранения часто используемых переменных.
2. Избегайте операций с плавающей точкой
Операции с плавающей точкой требуют значительных вычислительных ресурсов. Где возможно, используйте целочисленную арифметику или арифметику с фиксированной точкой.
3. Используйте встроенные функции и макросы
Многие операции, такие как установка/сброс битов, могут быть выполнены с помощью встроенных функций компилятора, которые часто оптимизируются лучше, чем написанный вручную код.
4. Оптимизируйте циклы
Разворачивайте короткие циклы, используйте инкремент вместо декремента (если это не влияет на логику), выносите неизменяемые вычисления за пределы цикла.
5. Используйте правильные типы данных
Выбирайте наименьший возможный тип данных для переменных. Например, используйте uint8_t вместо int, если значение никогда не превысит 255.
Заключение
Микроконтроллеры AVR предоставляют мощную и гибкую платформу для разработки встраиваемых систем. Понимание их архитектуры, системы команд и методов программирования позволяет создавать эффективные и оптимизированные приложения. Независимо от того, используете ли вы ассемблер или язык высокого уровня, знание особенностей AVR поможет вам максимально использовать возможности этих микроконтроллеров.
Таблицы команд ассемблера AVR — Микроконтроллеры для всех
В этой статье я хочу представить еще один вариант таблиц команд ассемблера для микроконтроллеров AVR.
Из дополнительных материалов у приобретателей курса уже есть pdf документ с набором таблиц команд. Так в чем же основное отличие набора команд, который представлен ниже?
В первую очередь, тем что в колонке «Описание» дается описание команд на английском. И как не трудно заметить, многие мнемоники команд образованы как раз от этих сокращений. Поэтому, тем кто знает английский язык, тем будет проще запомнить написание команд. И так же присутствует колонка «Код операции», где можно посмотреть каким образом та или иная команда выглядит в двоичном виде. Это на тот случай, если вам вдруг захочется по-программировать в машинных кодах.
Сразу стоит отметить, что здесь представлены в основном только команды семейства tiny. Я намерено убрал команды семейства mega, что бы лишний раз не вносить путаницу.
Арифметические и логические команды
Команда
Описание
Действие
Циклы
Код операции
Флаги
add Rd,Rr
Add two Registers
Rd←Rd+Rr
1
0000 11rd dddd rrrr
Z,C,S,N,V,H
adc Rd,Rr
Add with Carry two Registers
Rd←Rd+Rr+C
1
0001 11rd dddd rrrr
Z,C,S,N,V,H
adiw Rdl,K
Add Immediate to Word
Rdh:Rdl←Rdh:Rdl+K
2
1001 0110 KKdd KKKK
Z,C,S,N,V
sub Rd,Rr
Subtract two Registers
Rd←Rd-Rr
1
0001 10rd dddd rrrr
Z,C,S,N,V,H
sbc Rd,Rr
Subtract with Carry two Registers
Rd←Rd-Rr-C
1
0000 10rd dddd rrrr
Z,C,S,N,V,H
subi Rd,K
Subtract Constant from Register
Rd←Rd-K
1
1010 KKKK dddd KKKK
Z,C,S,N,V,H
sbci Rd,K
Subtract with Carry Constant from Register
Rd←Rd-K-C
1
0100 KKKK dddd KKKK
Z,C,S,N,V,H
sbiw Rdl,K
Subtract Immediate from Word
Rdh:Rdl←Rdh:Rdl-K
2
1001 0111 KKdd KKKK
Z,C,S,N,V
and Rd,Rr
Logical AND Registers
Rd←Rd AND Rr
1
0010 00rd dddd rrrr
Z,S,N
andi Rd,K
Logical AND Register and Constant
Rd←Rd AND K
1
0111 KKKK dddd KKKK
Z,S,N
or Rd,Rr
Logical OR Registers
Rd←Rd OR Rr
1
0010 10rd dddd rrrr
Z,S,N
ori Rd,K
Logical OR Register and Constant
Rd←Rd OR K
1
0110 KKKK dddd KKKK
Z,S,N
eor Rd,Rr
Exclusive OR Registers
Rd←Rd EOR Rr
1
0010 01rd dddd rrrr
Z,S,N
com Rd
One’s complement
Rd←0xFF-Rd
1
1001 010d dddd 0000
Z,S,N
neg Rd
Two’s complement
Rd←0x00-Rd
1
1001 010d dddd 0001
Z,C,S,N,V,H
sbr Rd,K
Set Bit (s) in Register
Rd←Rd OR K
1
0110 KKKK dddd KKKK
Z,S,N
cbr Rd,K
Clear Bit (s) in Register
Rd←Rd AND (0xFF- K)
1
0111 KKKK dddd KKKK
Z,S,N
inc Rd
Increment
Rd←Rd+1
1
1001 010d dddd 0011
Z,S,N,V
dec Rd
Decrement
Rd←Rd-1
1
1001 010d dddd 1010
Z,S,N,V
tst Rd
Test for Zero or Minus
Rd←Rd AND Rd
1
0010 00dd dddd dddd
Z,S,N
clr Rd
Clear Register
Rd←Rd EOR Rd
1
0010 01dd dddd dddd
Z,S,N
ser Rd
Set Register
Rd←0xFF
1
1110 1111 dddd 1111
None
Команды пересылки данных
Команда
Описание
Действие
Циклы
Код операции
Флаги
mov Rd,Rr
Move Between Registers
Rd←Rr
1
0010 11rd dddd rrrr
None
movw Rd,Rr
Copy Register Word
Rd+1:Rd←Rr+1:Rr
1
0000 0001 dddd rrrr
None
ldi Rd,K
Load Immediate
Rd←K
1
1110 KKKK dddd KKKK
None
ld Rd,X
Load Indirect
Rd← (X)
2
1001 000d dddd 1100
None
ld Rd,X+
Load Indirect and Post-Inc.
Rd← (X), X←X+1
2
1001 000d dddd 1101
None
ld Rd, -X
Load Indirect and Pre-Dec.
X←X-1, Rd← (X)
2
1001 000d dddd 1110
None
ld Rd,Y
Load Indirect
Rd← (Y)
2
1000 000d dddd 1000
None
ld Rd,Y+
Load Indirect and Post-Inc.
Rd← (Y), Y←Y+1
2
1001 000d dddd 1001
None
ld Rd, -Y
Load Indirect and Pre-Dec.
Y←Y-1, Rd← (Y)
2
1001 000d dddd 1010
None
ldd Rd,Y+q
Load Indirect with Displacement
Rd← (Y+q)
2
10q0 qq0d dddd 1qqq
None
ld Rd,Z
Load Indirect
Rd← (Z)
2
1000 000d dddd 0000
None
ld Rd,Z+
Load Indirect and Post-Inc.
Rd← (Z), Z←Z+1
2
1001 000d dddd 0001
None
ld Rd, -Z
Load Indirect and Pre-Dec.
Z←Z-1, Rd← (Z)
2
1001 000d dddd 0010
None
ldd Rd,Z+q
Load Indirect with Displacement
Rd← (Z+q)
2
10q0 qq0d dddd 0qqq
None
lds Rd,k
Load Direct from SRAM
Rd← (k)
2
1001 000d dddd 0000kkkk kkkk kkkk kkkk
None
st X,Rr
Store Indirect
(X) ←Rr
2
1001 001r rrrr 1100
None
st X+,Rr
Store Indirect and Post-Inc.
(X) ←Rr, X←X+1
2
1001 001r rrrr 1101
None
st -X,Rr
Store Indirect and Pre-Dec.
X←X-1, (X) ←Rr
2
1001 001r rrrr 1110
None
st Y,Rr
Store Indirect
(Y) ←Rr
2
1000 001r rrrr 1000
None
st Y+,Rr
Store Indirect and Post-Inc.
(Y) ←Rr, Y←Y+1
2
1001 001r rrrr 1001
None
st -Y,Rr
Store Indirect and Pre-Dec.
Y←Y-1, (Y) ←Rr
2
1001 001r rrrr 1010
None
std Y+q,Rr
Store Indirect with Displacement
(Y+q) ← Rr
2
10q0 qq1r rrrr 1qqq
None
st Z,Rr
Store Indirect
(Z) ←Rr
2
1000 001r rrrr 0000
None
st Z+,Rr
Store Indirect and Post-Inc.
(Z) ←Rr, Z←Z+1
2
1001 001r rrrr 0001
None
st -Z,Rr
Store Indirect and Pre-Dec.
Z←Z-1, (Z) ←Rr
2
1001 001r rrrr 0010
None
std Z+q,Rr
Store Indirect with Displacement
(Z+q) ← Rr
2
10q0 qq1r rrrr 0qqq
None
sts k,Rr
Store Direct to SRAM
(k) ←Rr
2
1001 001r rrrr 0000kkkk kkkk kkkk kkkk
None
lpm
Load Program Memory
R0← (Z)
3
1001 0101 1100 1000
None
lpm Rd,Z
Load Program Memory
Rd← (Z)
3
1001 000d dddd 0100
None
lpm Rd,Z+
Load Program Memory and Post-Inc.
Rd← (Z), Z←Z+1
3
1001 000d dddd 0101
None
spm
Store Program Memory
(Z) ←R1:R0
—
1001 0101 1110 1000
None
in Rd,P
In Port
Rd←P
1
1011 0PPd dddd PPPP
None
out P,Rr
Out Port
P←Rr
1
1011 1PPr rrrr PPPP
None
push Rr
Push Register in Stack
STACK←Rr, SP←SP-1
2
1001 001r rrrr 1111
None
pop Rd
Pop Register from Stack
SP←SP+1, Rd←STACK
2
1001 000d dddd 1111
None
Команды передачи управления
Команда
Описание
Действие
Циклы
Код операции
Флаги
rjmp k
Relative Jump
PC←PC+k+1
2
1100 kkkk kkkk kkkk
None
ijmp
Indirect Jump to (Z)
PC← (Z)
2
1001 0100 0000 1001
None
*jmp k
Direct Jump
PC←k
3
1001 010k kkkk 110kkkkk kkkk kkkk kkkk
None
rcall k
Relative Subroutine Call
STACK←PC+1,PC←PC+k+1,SP←SP-2 or 3
¾
1101 kkkk kkkk kkkk
None
icall
Indirect Call to (Z)
STACK←PC+1, PC← (Z),SP←SP-2 or 3
¾
1001 0101 0000 1001
None
*call k
Direct Subroutine Call
STACK←PC+1, PC←k,SP←SP-2 or 3
4/5
1001 010k kkkk 111kkkkk kkkk kkkk kkkk
None
ret
Subroutine Return
PC←STACK, SP←SP+2 or 3
4/5
1001 0101 0000 1000
None
reti
Interrupt Return
PC←STACK, SP←SP+2 or 3
4/5
1001 0101 0001 1000
I
cpse Rd,Rr
Compare, Skip if Equal
if (Rd=Rr) PC←PC+2 or 3
½/3
0001 00rd dddd rrrr
None
cp Rd,Rr
Compare
Rd-Rr
1
0001 01rd dddd rrrr
Z,C,S, N,V,H
cpc Rd,Rr
Compare with Carry
Rd-Rr-C
1
0000 01rd dddd rrrr
Z,C,S, N,V,H
cpi Rd,K
Compare Register with Immediate
Rd-Rr-K
1
0011 KKKK dddd KKKK
Z,C,S, N,V,H
sbrc Rr,b
Skip if Bit in Register is Cleared
if (Rr (b)=0) PC←PC+2 or 3
½/3
1111 110r rrrr obbb
None
sbrs Rr,b
Skip if Bit in Register is Set
if (Rr (b)=1) PC←PC+2 or 3
½/3
1111 111r rrrr obbb
None
sbic P,b
Skip if Bit in IO Register is Cleared
if (P (b)=0) PC←PC+2 or 3
½/3
1001 1001 PPPP Pbbb
None
sbis P,b
Skip if Bit in IO Register is Set
if (P (b)=1) PC←PC+2 or 3
½/3
1001 1011 PPPP Pbbb
None
brbc s,k
Branch if Status Flag is Cleared
if (SREG (s)=0) PC←PC+k+1
½
1111 01kk kkkk ksss
None
brbs s,k
Branch if Status Flag is Set
if (SREG (s)=1) PC←PC+k+1
½
1111 00kk kkkk ksss
None
brcc k
Branch if Carry Flag is Clearsd
if (C=0) PC←PC+k+1
½
1111 01kk kkkk k000
None
brcs k
Branch if Carry Flag is Set
if (C=1) PC←PC+k+1
½
1111 00kk kkkk k000
None
brsh k
Branch if Same or Higher
if (C=0) PC←PC+k+1
½
1111 01kk kkkk k000
None
brlo k
Branch if Lower
if (C=1) PC←PC+k+1
½
1111 00kk kkkk k000
None
brne k
Branch if Not Equal
if (Z=0) PC←PC+k+1
½
1111 01kk kkkk k001
None
breq k
Branch if Equal
if (Z=1) PC←PC+k+1
½
1111 00kk kkkk k001
None
brpl k
Branch if Plus
if (N=0) PC←PC+k+1
½
1111 01kk kkkk k010
None
brmi k
Branch if Minus
if (N=1) PC←PC+k+1
½
1111 00kk kkkk k010
None
brvc k
Bruach if Overflow Flag is Cleared
if (V=0) PC←PC+k+1
½
1111 01kk kkkk k011
None
brvs k
Branch if Overflow Flag is Set
if (V=1) PC←PC+k+1
½
1111 00kk kkkk k011
None
brge k
Branch if Greate or Equal, Signed
if (S=0) PC←PC+k+1
½
1111 01kk kkkk k100
None
brlt k
Branch if Less than Zero, Signed
if (S=1) PC←PC+k+1
½
1111 00kk kkkk k100
None
brhc k
Branch if Half Carry Flag is Cleared
if (H=0) PC←PC+k+1
½
1111 01kk kkkk k101
None
brhs k
Branch if Half Carry Flag is Set
if (H=1) PC←PC+k+1
½
1111 00kk kkkk k101
None
brtc k
Branch if Transfer Flag is Cleared
if (T=0) PC←PC+k+1
½
1111 01kk kkkk k110
None
brts k
Branch if Transfer Flag is Set
if (T=1) PC←PC+k+1
½
1111 00kk kkkk k110
None
brid k
Branch if Interrupt Disable
if (T=0) PC←PC+k+1
½
1111 01kk kkkk k111
None
brie k
Branch if Interrupt Enable
if (T=1) PC←PC+k+1
½
1111 00kk kkkk k111
None
*Обратите внимание! Команды jmp и call не поддерживаются микроконтроллерами семейства tiny, но так как они часто используются при программировании семейства mega, то я решил их так же внести в таблицу, что бы вы не забывали о их существовании.
Команды условных переходов по состоянию флагов SREG
Проверкафлага
Команда условногоперехода
АльтернативнаяФорма написания
Условие перехода
C
brbc 0,k
brcc k
Переход если флаг переноса установлен
brsh k
Переход если больше или равно
brbs 0,k
brcs k
Переход если флаг переноса сброшен
brlo k
Переход если меньше
Z
brbc 1,k
breq k
Переход если равно
brbs 1,k
brne k
Переход если не равно
N
brbc 2,k
brpl k
Переход если плюс
brbs 2,k
brmi k
Переход если минус
V
brbc 3,k
brvc k
Переход если флаг дополнительного кода сброшен
brbs 3,k
brvs k
Переход если флаг дополнительного кода установлен
S
brbc 4,k
brge k
Переход если больше или равно нулю (знаковое)
brbs 4,k
brlt k
Переход если меньше нуля (знаковое)
H
brbc 5,k
brhc k
Переход если флаг половинного переноса сброшен
brbs 5,k
brhs k
Переход если флаг половинного переноса установлен
T
brbc 6,k
brtc k
Переход если флаг хранения бита сброшен
brbs 6,k
brts k
Переход если флаг хранения бита установлен
I
brbc 7,k
brid k
Переход если прерывания запрещены
brbs 7,k
brie k
Переход если прерывания разрешены
Команд битовых операций
Команда
Описание
Действие
Циклы
Код операции
Флаги
sbi P,b
Set Bit in I/O Rerister
I/O (P,b) ←1
2
1001 1010 PPPP Pbbb
None
cbi P,b
Clear Bit in I/ORerister
I/O (P,b) ←0
2
1001 1000 PPPP Pbbb
None
lsl Rd
Logical Shift Left
Rd (n+1) ←Rd (n), Rd (0) ←0
1
0000 11dd dddd dddd
Z,C,N,V
lsr Rd
Logical Shift Right
Rd (n) ←Rd (n+1), Rd (7) ←0
1
1001 010d dddd 0110
Z,C,N,V
rol Rd
Rotate Left through Carry
Rd (0) ←C, Rd (n+1) ←Rd (n), C←Rd (7)
1
0001 11dd dddd dddd
Z,C,N,V
ror Rd
Rotate Right through Carry
Rd (7) ←C, Rd (n) ←Rd (n+1), C←Rd (0)
1
1001 010d dddd 0111
Z,C,N,V
asr Rd
Arithmetic Shift Right
Rd (n) ←Rd (n+1), n=0…6
1
1001 010d dddd 0101
Z,C,N,V
swap Rd
Swap Nibbles
Rd (3…0) ←Rd (7…4),Rd (7…4) ←Rd (3…0)
1
1001 010d dddd 0010
None
bst Rr,b
Bit Store from Rerister to T
T←Rr (b)
1
1111 101b bbbb 0bbb
T
bld Rd,b
Bit Load from T to Rerister
Rd (b) ←T
1
1111 100b bbbb 0bbb
None
bset s
Flag Set
SREG (s) ←1
1
1001 0100 0sss 1000
SREG (s)
bclr s
Flag Clear
SREG (s) ←0
1
1001 0100 1sss 1000
SREG (s)
sec
Set Carry
C←1
1
1001 0100 0000 1000
C
clc
Clear Carry
C←0
1
1001 0100 1000 1000
C
sez
Set Zero Flag
Z←1
1
1001 0100 0001 1000
Z
clz
Clear Zero Flag
Z←0
1
1001 0100 1001 1000
Z
sen
Set Negative Flag
N←1
1
1001 0100 0010 1000
N
cln
Clear Negative Flag
N←0
1
1001 0100 1010 1000
N
sev
Set Twos Complement Overflow
V←1
1
1001 0100 0011 1000
V
clv
Clear Twos Complement Overflow
V←0
1
1001 0100 1011 1000
V
ses
Set Signed Test Flag
S←1
1
1001 0100 0100 1000
S
cls
Clear Signed Test Flag
S←0
1
1001 0100 1100 1000
S
seh
Set Half Carry Flag
H←1
1
1001 0100 0101 1000
H
clh
Clear Half Carry Flag
H←0
1
1001 0100 1101 1000
H
set
Set Transfer bit
T←1
1
1001 0100 0110 1000
T
clt
Clear Transfer bit
T←0
1
1001 0100 1110 1000
T
sei
Global Interrupt Enable
I←1
1
1001 0100 0111 1000
I
cli
Global Interrupt Disable
I←0
1
1001 0100 1111 1000
I
Команды управления процессором
Команда
Описание
Действие
Циклы
Код операции
Флаги
nop
No operation
—
1
0000 0000 0000 0000
None
sleep
Sleep
—
1
1001 0101 1000 1000
None
wdr
Watchdog Reset
—
1
1001 0101 1010 1000
None
Сделаем простой AVR микроконтроллер
Меня часто спрашивают: «Чем отличается микроконтроллер от ПЛИС?» Ну что тут можно ответить? Это как бы разные вещи. .. Микропроцессор последовательно выполняет команды, описанные в его программе. Работа ПЛИС в конечном счете определяется принципиальной электрической схемой, реализованной внутри чипа. Архитектура микроконтроллера, то есть тип процессора, количество портов ввода вывода, интерфейсы, определяется производителем. Микросхема микроконтроллера изготовлена на заводе и изменить ее нельзя. Можно только написать программу, которую он будет исполнять. ПЛИС — это свобода для творчества. Архитектура реализуемого устройства может быть почти любая, лишь бы поместилась вся логика в чип. В ПЛИС можно, например, попробовать реализовать даже и микроконтроллер! Попробуем?
Один из самых распространенных микроконтроллеров — это 8-ми разрядные RISС процессоры семейства AVR компании Atmel. В этой статье я расскажу как реализовать «почти» совместимый с AVR микроконтроллер внутри нашей ПЛИС на плате Марсоход.
Прежде, чем начинать делать свою реализацию микроконтроллера, конечно, следует изучить внутренности контроллера AVR. Нужно как минимум знать систему команд микропроцессора AVR. На нашем сайте можно скачать его описание:
Система команд микроконтроллера AVR ( 703303 bytes )
Мы не будем ставить себе целью полностью повторить поведение чипа Atmel, мы хотим сделать наш микропроцессор лишь частично совместимым. Полностью повторить можно, но нужна ПЛИС гораздо большего объема. У нас на плате Марсоход стоит CPLD EPM240T100C5, значит у нас есть всего-навсего 240 триггеров и логических элементов.
Кроме триггеров и логики в нашей ПЛИС имеется последовательная флеш память UFM объемом 512 слов по 16 бит. В этой флеш памяти мы будем хранить программу микроконтроллера. Удобно, что слова, хранимые во флеш, имеют разрядность 16. Все команды процессора AVR также шестнадцатиразрядные. Кое-что про UFM мы уже писали на нашем сайте. У нас был проект для ПЛИС платы Марсоход, который выполнял чтение из UFM памяти.
«Оперативной памяти» в нашей ПЛИС нет. Ну значит не будет памяти у нашего микроконтроллера, жаль но это нас не остановит.
У микроконтроллера AVR имеется 32 восьмиразрядных регистра общего назначения. Нижняя группа регистров r0-r15 может быть использована только в командах с операндами-регистрами. Верхняя группа регистров r16-r31 может использоваться в командах и с непосредственными операндами. Поскольку места внутри нашего чипа на плате Марсоход действительно не много, нам придется реализовать только некоторые регистры. Это довольно существенное ограничение, и его нужно будет учитывать при написании программ для нашего микроконтроллера.
Мы реализуем только 7 регистров: r16-r22:
Первые 4 регистра r16…r19 — это просто регистры.
Регистр r20 — это тоже обычный регистр, только его биты мы подключим к 8-ми светодиодам платы Марсоход.
Регистр r21 — это тоже обычный регистр, но его биты мы подключим к выводам управления шаговых двигателей на плате Марсоход.
Регистр r22 — только для чтения. К нему подключены входы от 4-х кнопочек платы Марсоход.
Схема нашего микроконтроллера создана в среде Altera QuartusII и выглядит вот так (нажмите на картинку, чтобы увеличить):
Наш микроконтроллер работает по простому алгоритму:
Считывает из флеш памяти UFM очередную команду.
Декодирует команду и выбирает для нее нужные операнды из регистров или непосредственно из кода команды.
Выполняет команду в арифметико-логическом устройстве.
Запоминает результат исполнения команды в регистре приемнике, определяемом командой.
Переходит к исполнению следующей команды.
У нас сейчас нет цели сделать высокопроизводительный микроконтроллер, мы не будем делать конвейерную обработку данных. Это объясняется тем, что команды из флеш памяти чипа мы можем считывать только в последовательном формате, то есть на чтение одной команды нужно как минимум 16 тактов. Быстрее здесь сделать нельзя (да нам и не нужно сейчас).
Ход выполнения программы может изменяться в зависимости от результата исполнения команд. Специальные команды переходов позволяют переходить к нужной операции в нужных условиях.
Перечислим команды микроконтроллера AVR, которые мы собираемся реализовать:
ADD 0000 11rd dddd rrrr SUB 0001 10rd dddd rrrr
AND 0010 00rd dddd rrrr EOR 0010 01rd dddd rrrr OR 0010 10rd dddd rrrr MOV 0010 11rd dddd rrrr
Слева написаны названия команд, а справа — их бинарное представление (кодирование). Так буква «r» обозначает регистр источник, буква «d» — регистр приемник, «K» — это непосредственно операнд.
Конечно — это только малая часть от «настоящей системы команд», но уже и эти команды позволять писать вполне работающие программы. У нас будет упрощенное АЛУ (Арифметико-Логическое Устройство). Оно реализует только некоторые, наиболее употребительные команды, а так же всего 2 флага для условных переходов: «Z» и «C».
Флаг «Z» устанавливается, если результат АЛУ это ноль. Если результат из АЛУ не нулевой, то флаг «Z» сбрасывается. Флаг «C» устанавливается при возникновении переноса в арифметических операциях ADD и SUB/SUBI или сравнения CP/CPI. Флаги влияют на исполнение команд условных переходов: флаг «Z» влияет на BREQ, BRNE, а флаг «C» влияет на BRCS, BRCC.
Вообще всеь проект мы уже реализовали и его можно взять здесь:
Ядро микропроцессора Atmel AVR ( 109584 bytes )
. Исходный текст нашего ядра AVR написан на языке Verilog и его можно посмотреть здесь.
Теперь посмотрим, как мы сможем написать программу для нашего микроконтроллера? Для написания программы на языке ассемблер воспользуемся средой разработки компании Atmel AVRStudio4. Эту среду разработки можно скачать прямо с сайта компании Атмел (после регистрации), вот здесь. Или поищите в яндексе — наверняка найдете в свободном доступе.
Создаем проект в AVRStudio4 и пишем простую программу. Программа будет моргать светодиодом на плате Марсоход и опрашивать состояние нажатых кнопочек. Если нажать одну кнопочку, то моргающий светодиод «побежит» в одну сторону, а если нажать другую кнопочку, то светодиод «побежит» в другую сторону. Вот исходный текст на ассемблере для нашего примера:
.include «1200def.inc» .device AT90S1200
.cseg .org 0
start:
;initial one bit in register ldi r16,$80
rd_port:
;read port (key status) mov r17,r22 cpi r17,$0f ;go and blink one LED if no key pressed breq do_xor
cpi r17,$0e ;go and right shift LEDs if key[0] pressed breq do_rshift
cpi r17,$0d ;go and left shift LEDs if key[1] pressed breq do_lshift
pause: ldi r18,$10 cycle2: ldi r19,$FF cycle1: or r19,r19 or r19,r19 subi r19,1 brne cycle1 subi r18,1 brne cycle2
or r16,r16 brne rd_port
Видите? Чтение состояния кнопочек — это чтение из регистра r22. Изменение состояния светодиодов — это запись в регистр r20. Настройте AVRStudio так, что бы выходной формат был «Generic». Это в свойствах проекта, «Assembler Options», настройка «Hex Output Format». После компиляции программы получается вот такой текстовый файл с кодами программы:
Этот файл нам почти подходит для QuartusII. В нашем проекте для ПЛИС есть файл avr_prog. mif (Memory Initialization File), куда мы и вставляем полученный из AVRStudio код (только нужно добавить точку с запятой в конце каждой строки). Таким образом, после компиляции QuartusII эти коды попадут во флеш UFM нашей ПЛИС.
Теперь можно компилировать и пробовать наш проект в плате Марсоход. Вот видеоролик, демонстрирующий работоспособность нашего процессора:
Все работает так как и задумывалось! Обратите внимание, что после компиляции, весь проект занимает только 205 логических элемента из 240 имеющихся в нашей ПЛИС. Это значит, что наш микроконтроллер можно и дальше усложнять или добавить какую-то новую логику. Так что проект может быть полезен для создания Ваших устройств.
Список инструкций на ассемблере AVR
Список инструкций
Мнем.
P1
P2
Описание
Действие
Задействованные флаги
Clk
Ограничения
Слова
9000 6
Арифметические и логические операции
ADD
Rx
Ry
Добавить регистр
Rx ← Rx + Ry
Z,C,N,V,S,H
1
1
АЦП
Rx
Ry
Добавить регистр и перенос
Rx ← Rx + Ry + C
,0,0,C,C 32 1
1
ADIW
RdL
K
Добавить константу в пару регистров
RdH:RdL ← RdH:RdL + K
Z,C,N,V,S
0032 ЛдЛ=24/26 /28/30, K: от 0 до 63
1
SUB
Rx
Ry
Регистр вычитания
Rx ← Rx — Ry
Z,C,N,V,S,H
1
1
9003 2 SUBI
Rh
K
Вычесть постоянную
Rh ← Rh — K
Z,C,N,V,S,H
1
R: от 16 до 31
1
SBC
Rx 90 033
Ry
Вычитание и перенос
Rx ← Rx — Ry — C
Z 1 ,C,N,V,S,H
1
1
SBCI
Rh
K
Вычесть константу и перенести 1 ,С,Н,В,С,Ч
1
R: с 16 по 31
1
CP
Ry1
Ry2
Регистр сравнения 3
Z0 -239 R0
С, Н, В, С, Н
1
1
КТК
Рай1
Рай2
Сравнение регистрации и переноса
Ry1 — Ry2 — C
Z 1 ,C,N,V,S,H
1
1
9 0003
CPI
Rh
K
Сравнить с константой
Rx — K
Z,C,N,V,S,H
1
R: от 16 до 31, K: от 0 до 255
1
900 32 SBIW
RdL
К
Вычесть константу из пары регистров
RdH:RdL ← RdH:RdL — K
Z,C,N,V,S
2
RdL=24/26/28/30, K: от 0 до 63
1
И
И
3
3 Rx
3
Двоичный регистр И
Rx ← Rx AND Ry
Z,N,V,S
1
1
ANDI
Rh
K Двоичная константа 9 ANDI
Правая ← Правая UND K
Z ,N,V,S
1
R: от 16 до 31, K: от 0 до 255
1
ИЛИ
Rx
Ry
Двоичный ИЛИ
Rx ← Rx ИЛИ Ry
Z,N,V,S
1
3 1
3 100046
ORI
Rh
K
Бинарный OR с константой
Rh ← Rh OR K
Z,N,V,S
1
R: от 16 до 31, K: от 0 до 255
1
EOR 0033
Рай
Исключающее ИЛИ
Rx ← Rx XOR Ry
Z,N,V,S
1
1
COM
Rx
Дополнение до единицы
Rx ← 255 — Rx
Z,C,N,V,S
1
1
НЕТ
Rx
Дополнение до двух
Rx ← 256 — Rx
Z,C,N,V,S,H
1
1
SBR
Rh
K
Набор бит в константе K
Rh ← Rh OR K
Z,N,V,S
1
R: от 16 до 31, K: от 0 до 255
1
CBR
Rh
бит s в константе K
Rh ← Rh AND (NEG K)
Z,N,V,S
1
R: от 16 до 31, K: от 0 до 255
1
INC
Rx Увеличить на единицу
Rx ← Rx + 1
Z,N,V,S
1
1
ДЕК
Rx
Уменьшение на единицу
Rx ← Rx — 1
Z,N,V,S
1
ST 1
3 T 032 Ry
Сравнить с нулем
Rx ИЛИ Rx
Z,N,V,S
1
1
CLR
Rx
Очистить все биты 9033 3 Rx
900 32 З,Н,В,С
1
1
СЕР
Правая
Установить все биты
Rh ← 255
—
1
R: с 16 по 31
1
1 MUL
Ry2
Умножить 8 бит
R1:R0 ← Ry1 * Ry2
Z,C
2
1
MULS
Ry1
Ry2
Ry1 * Ry2
Z,C
2
Ry1, Ry2: с 16 по 31
1
MULSU
Rx
Ry
Умножение без знака и со знаком
R1:R0 ← Ry1 * Ry2
Z,C
9 0032 2
Ry1, Ry2: от 16 до 31
1
FMUL
Ry1
Ry2
Умножение с плавающей запятой
R1:R0 ← Ry1 * Ry2
Z,C
2
Ry1,R y2: с 16 по 23
1
FMULS
Ry1
Рай2
Умножение с плавающей запятой со знаком
R1:R0 ← Ry1 * Ry2
Z,C
2
Ry1,Ry2: от 16 до 23
1
90SU
2 033
Ry1
Ry2
С плавающей запятой умножение со знаком и без знака
R1:R0 ← Ry1 * Ry2
Z,C
2
Ry1,Ry2: от 16 до 23
1
DES 033
Кодирование и декодирование данных
(R7:R0, R15:R8)
—
1/2
(только MEGA/XMEGA), K<16
1
Флаг Z устанавливается в единицу, если эта инструкция дала ноль И если он был установлен предыдущей инструкцией. Это позволяет проводить 16-битные сравнения.
Инструкции перехода
RJMP
K
Относительный переход
(ПК) ← (ПК) +/- K
9003 2 —
2
К: от -2048 до 2047
1
IJMP
Косвенный переход
(ПК) ← Z
—
2
1
4JMP 6
Расширенный непрямой прыжок
(ПК) ← EIND + Z
—
2
(только XMEGA)
1
JMP
K
Прямой (широкий) прыжок
(PC) ← 9
3 K3 3
К: от 0 до 65535
2
RCALL
K
Относительный вызов
(стек) ← (ПК), (ПК) ← (ПК) +/- K
—
2/3/4
K: -20042 K: -20048
1
ICALL
Косвенный вызов
(стек) ← (ПК), (ПК) ← Z
—
6 2 3 9 0
ЭЙКЛ
Расширенный непрямой вызов
(стек) ← (ПК), (ПК) ← EIND+Z
—
3/4
1
ВЫЗОВ
K
Общий вызов
(стек) ← (ПК), 903 — 9 K
3/4/5
2
RET
Возврат после звонка
(ПК) ← (Стопка)
—
4
3
32 RETI
Возврат из процедуры обработки прерывания
(ПК ) ← (стек), I ← 1
—
4
1
CPSE
Ry1
Ry2
Перейти на следующую инструкцию, если равно
Ry1=Ry2: (ПК) ← (ПК + 2)
—
2/ 3
1
SBRC
Ry
B
Переход к следующей инструкции, если бит очищен
(Бит)=0: (ПК) ← (ПК+2) )
—
2/3
1
СБРС
Рай
B
Переход к следующей инструкции, если бит установлен 032 ПЛ
B
Переход через следующую инструкцию, если бит порта очищен номер
B
Переход к следующей инструкции, если бит порта установлен
(Бит)=1: (ПК) ← (ПК+1)
—
2/3
1
BRBS
K
B
Относительный переход, если бит в SREG установлен 9003it3): ПК) ← (ПК) + /- K
—
1/2
K: от -63 до + 64
1
BRBC
K
B 9003 Бит, если очистить EG относительный переход 3 0033
(SREG-бит= 0): (ПК) ← (ПК) +/- K
—
1/2
K: от -63 до + 64
9
(SREG-Z=1): (PC) ← (PC) +/- K
— 900 33
1/2
K: от -63 до + 64
1
BRNE
K
Относительный скачок, если Z в SREG очистить
(SREG-Z=0): (PC) (PC) ( ПК) +/- К
—
1/2
K: от -63 до + 64
1
BRCS
K
Относительный переход, если C в наборе SREG.
BRCC
K
Относительный переход, если C в SREG очистить
(SREG-C=0): (PC) ← (PC) +/- K
—
K 1/2
3 : От -63 до + 64
1
БРШ
K
Относительный скачок, если C в SREG очистить
(SREG-C=0): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
BRLO
K
Относительный переход, если C в SREG установлен
(SREG-C=1): (PC ) ← (ПК) +/- K
—
1/2
K: от -63 до + 64
1
BRMI
K
Относительный переход, если в SREG установлено N
( SREG-N=1): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
BRPL
K
Относительный переход при сбросе Z в SREG
(SREG-N=1): (PC) ← (PC) +/- K
—
3 K 9 9 032 1/2 : от -63 до + 64
1
BRGE
K
Относительный переход, если S в SREG очистить
(SREG-S=0): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
BRLT
K
Относительный переход, если S в наборе SREG
(SREG-S=1): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
3 BRHS
3
Относительный скачок, если H в SREG установлен
BRHC
K
Относительный переход при сбросе H в SREG
(SREG-H=0): (PC) ← (PC) +/- K
—
1/2 1/2(PC) K
—
1/2
K: от -63 до + 64
1
BRTC
K
9003EG
Относительный переход, если T 2 (СРЭГ-Т=0): ( ПК) ← (ПК) +/- К
—
1/2
К: от -63 до + 64
1
БРВС
K
Относительный скачок, если V в SREG установлен
(SREG-V=0): (PC) ← (PC) +/- K
—
2
K: от -63 до + 64
1
BRIE
K
Относительный переход, если I в наборе SREG
(SREG-I=1): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
BRID
3 K
3
Относительный переход, если I в сбросе SREG
(SREG-I=0): (PC) ← (PC) +/- K
—
1/2
K: от -63 до + 64
1
Инструкции по копированию и загрузке данных
MOV
Rx
Ry
Регистр копирования
Rx ← Ry
—
1
1
MOVW
Rx
Ry
Пара регистров копирования
90:Rx Rxy+1
—
1
Rx, Ry: Четный
1
LDI
Правая
K
Постоянная нагрузки
Правая ← K
—
R
3 1 6 31, К: от 0 до 255
1
LDS
Rh
A
Копировать байт SRAM
Rx ← (SRAM-A)
—
2/3/4
R: с 16 по 31
2
3x
LD
2
X
Копировать байт SRAM вкл. адрес X
Rx ← (X)
—
2/3/4
1
LD
Rx
байт адрес 90RAM X+ X и инкрементный адрес
Rx ← ( Х), Х = Х + 1
—
2/3
1
LD
Rx
-X
Уменьшить X и скопировать байт SRAM с адреса X 033
1
LD
Rx
Y
Копировать байт SRAM по адресу Y
Rx ← (Y)
—
3 0 3 0 4 9 0 0/2 0032 1
LD
Rx
Y+
Скопировать байт SRAM по адресу Y и увеличить адрес
Rx ← (Y), Y = Y + 1
—
2/3
1
LD
Rx
900 32 -Y
Уменьшить Y и скопировать байт SRAM по адресу Y
Y = Y — 1, Rx ← (Y)
—
2/3/4
1
LDD
Rx
Y+K 90 033
Копировать байт SRAM из адреса (Y+K)
Rx ← (Y+K)
—
2/3
K: от 0 до 63
1
LD
Rx
Z
Копировать байт SRAM с адреса Z
Rx ← (Z)
—
1 9036 2/3/4
033
LD
Rx
Z+
Скопировать байт SRAM с адреса Z и увеличить адрес
Rx ← (Z), Z = Z + 1
—
2/3
1
R9 0 LD 3
-З
Уменьшить Z и скопировать байт SRAM с адреса Z
Z = Z — 1, Rx ← (Z)
—
2/3/4
1
LDD
Rx 3 Копия 20
Байт ОЗУ по адресу (Z+ K)
Rx ← (Z+K)
—
2/3
K: от 0 до 63
1
STS
3h A
Копировать в SRAM
(SRAM- A) ← Rx
—
2/3/4
R: от 16 до 31
2
91
ST
X+
Rx
Копировать в адрес SRAM в X и увеличить адрес
(X) ← Rx, X = X + 1
—
2/3
1
ST
-X
Rx
Уменьшение X и скопировать на адрес SRAM X
X = X — 1, (X) ← Rx
—
2/3/4
1
ST
Y
Rx
Копировать в адрес SRAM Y 9 0033
(Y) ← Rx
—
2/3/4
1
ST
Rx
Y+
Копировать по адресу Y и увеличить Y
(Y) ← Rx, Y = Y + 1
900 32 —
2/3
1
ST
Rx
-Y
Уменьшить Y и скопировать на адрес SRAM Y
Y = Y — 1, (Y) ← Rx
—
2/3/4
1
STD
Y+K 3 Копировать
3
Адрес SRAM (Y+K )
(Y+K) ← Rx
—
2/3
K: от 0 до 63
1
ST
3x
3 Z
2
Скопировать в SRAM адрес Z
(Z ) ← Rx
—
2/3/4
1
ST
Z+
Rx
Копировать в SRAM адрес Z и увеличить Z
(Z) ← Rx, Z = Z + 1
—
2/3
1
3 ST 32 -Z
Ркс
Уменьшить Z и скопировать в адрес SRAM Z
Z = Z — 1, (Z) ← Rx
—
2/3/4
1
3K 903 ZSTD 90+ 3
Rx
Копировать в адрес SRAM (Z+K)
(Z+K) ← Rx
—
2/3
K: от 0 до 63
1
LPM
Копировать из памяти программ по адресу (Z) в R0
Z09 ← 0032 R09
3
1
LPM
Rx
Z
Копировать из памяти программ адрес (Z) в регистр
Rx ← (Flash Z)
—
3 0032 1
л/мин
Rx
Z+
Копировать адрес памяти программы (Z) в регистр и увеличить Z
Rx ← (Flash Z), Z = Z + 1
—
3
1
3 ELPM
Копировать из адрес расширенной памяти программ (EIND+Z) для регистра R0
R0 ← (Flash Z)
—
3
1
ELPM
3
Rx
032 Копировать из адреса расширенной памяти программ ( EIND+Z) для регистрации
Rx ← (Flash Z)
—
3
1
ELPM
Rx
Z+
Копировать адрес программы Z+ ) для регистрации и увеличения Z
Rx ← (Flash Z), Z = Z + 1
—
3
1
SPM
Копировать слово R1:R0 в адрес программной памяти (Z) 9003 9003 :R0
—
N
1
SPM
Z+
Скопировать слово R1:R0 в адрес памяти программ (Z) и увеличить Z 3
1
IN
Rx
P
Копировать байт порта
Rx ← P
—
3 9: 0 9 0032 3 9 3
1
ВЫХОД
П
Rx
Скопировать байт в порт
P ← Rx
—
1
P: от 0 до 63
1
PUSH
Rx
3
PUSH
Rx
3 900 )
(стек) ← Rx, SP = SP — 1
—
2
1
POP
Rx
Копировать из стека и инкрементировать (SP)
R 90
—
2
1
ХСН
Z
Rx
Регистр обмена с адресом SRAM (Z)
Rx ↔ (Z)
—
1
1
LAS
033
Z
Rx
ИЛИ регистр и SRAM (Z) и замена
Rx ← Rx ODER (Z), (Z) ↔ Rx
—
1
1
LAC
3 Rx
3 Z
2
И дополнительный регистр с SRAM (Z ) и скопировать в SRAM (Z)
Rx ← (255-Rx) UND (Z), (Z) ↔ Rx
—
1
1
LAT
Z,
регистр ИЛИ и SRAM (Z) и обмен
Rx EXOR (Z), Rx ↔ (Z)
—
1
1
Битовые операции
SLx3
2 0033
Логический сдвиг влево
Rx ← Rx * 2
Z,C,N,V,H
1
1
LSR
Rx
Логический сдвиг вправо
Rx ← Rx / 2
Z,C,N,V
1
6 06
ROL
Rx
Бинарный поворот слева с C
Rx ← Rx * 2 с битом 0 = C/C = бит 7
Z,C,N,V,H
1
1
ROR
3
3
0032 Двоичный повернуть вправо с C
Rx ← Rx / 2 с битом 7 = C/C = бит 0
Z,C,N,V
1
1
ASR
Rx
Арифметический сдвиг вправо
6 = 0
Z ,C,N,V
1
1
SWAP
Rx
Обмен старшим и нижним полубайтами
2 Rx 3) (7:4) 0032 —
1
1
BSET
B
Установить бит в SREG
SREG ← SREG OR (1<
—
1
B: от 0 до 7
1
BCLR
B Очистить бит в SREG
SREG ← SREG И ( 255-(1<
—
1
B: от 0 до 7
1
SBI
PL
B 90 33
PL ← PL ИЛИ (1 <
—
2
PL: от 0 до 31, B: от 0 до 7
1
CBI
PL
B
Чистая насадка в порту
PL ← PL AND (255-(1< 3 3
— 90
PL: от 0 до 31, B: от 0 до 7
1
BST
Rx
B
Копировать бит регистра в T
SREG-T ← Rx-Bit B
—
0033
Б: от 0 до 7
1
BLD
Rx
B
Копировать T в регистр, бит
Rx-Bit B ← T
—
1
B: от 0 до 7
1
SEC
C SREG 303
900 Набор 32 SREG-бит C ← 1
—
1
1
CLC
Прозрачный SREG C
SREG-Bit C ← 0
—
3 1 1
SEN
Комплект SREG N
SREG- Бит N ← 1
—
1
1
CLN
Прозрачный SREG N
SREG-Bit N ← 0 9003 3 1 10033 —
—
1
СЭЗ
Комплект СРЭГ Z
SREG-Bit Z ← 1
—
1
1
CLZ
Прозрачный SREG 90 Z
3
3 033
—
1
1
SEI
Набор SREG I
SREG-Bit I ← 1
—
1
1
33
6
6
Очистить SREG I
SREG-Bit I ← 0
—
1
1
SES
Набор SREG S
SREG-Bit S ← 1
— 9 3
1
CLS
Прозрачный SREG S
SREG-Bit S ← 0
—
1
1
SEV
Набор SREG V
SREG-Bit V ← 1
—
1
1
CLV
Clear SREG V
SREG-Bit V ← 0
—
1
1
900 06
НАБОР
Набор SREG T
SREG-Bit T ← 1
—
1
1
CLT
Прозрачный SREG T
SREG-Bit T ← 0
—
1
1
SEH
Комплект SREG H
SREG- Бит H ← 1
—
1
1
CLH
Очистить SREG H
3 — SREG0-Bit
1
1
Инструкции по контроллеру
BREAK
Останов выполнения, управление отладчику
—
1
1
0046
Ничего не делать
—
1
1
СОН
Сон
—
1
1
WDR
9 0 сторожевой таймер
Счетчик WDR ← 0
—
1
1
AVR Tutorial — AVRDUDE
Хорошо, теперь у вас есть целевая плата и программатор, затем вы будете использовать программное обеспечение, которое вы установили на шаге 2, чтобы поговорить с чипом. Это программное обеспечение очень мощное, но его сложно использовать в первый раз. Тем не менее, вы должны проявить настойчивость, и через несколько раз им станет (легче) пользоваться.
Комментарии? Предложения? Пишите на форум!
Avrdude — это программа командной строки, поэтому вам придется вводить все команды (позже вы узнаете, как это сделать с помощью Makefile)
Под
Windows, вам нужно открыть командное окно, выбрать Run… в меню «Пуск», ввести cmd и нажать OK .
В MacOS X вы можете использовать программу Terminal для вызова интерфейса командной строки, она находится в папке Utilities
Теперь в новом окне терминала введите avrdude, вы должны получить этот ответ что в основном представляет собой простой список того, что может сделать avrdude…
Есть много вариантов, давайте быстро их рассмотрим. Не пытайтесь запомнить их, просто поймите, что некоторые из них могут делать.
-p : Это просто для того, чтобы указать, какой микроконтроллер запрограммирован. Например, если вы программируете ATtiny2313, используйте attiny2313 как номер детали
.
-b : это для переопределения скорости последовательной передачи для программистов, таких как STK500. Не используйте этот переключатель, значение по умолчанию правильное.
-B <битрейт>: это для изменения битрейта, то есть скорости, с которой программатор общается с чипом. Если ваш чип работает очень медленно, вам нужно говорить с ним медленно, чтобы он не отставал. Об этом позже, а пока не пользуйтесь.
-C <файл-конфигурации>: Файл конфигурации сообщает avrdude обо всех различных способах общения с программистом. Существует файл конфигурации по умолчанию, так что давайте просто использовать его: не используйте этот командный переключатель
-c : здесь мы указываем тип программатора, если вы используете STK500, используйте stk500, если вы используете программатор DT006, используйте dt006 и т. д.
-D: отключает стирание чипа перед программированием. Нам это не нужно, поэтому не используйте этот командный переключатель.
-P <порт>: это коммуникационный порт, используемый для связи с программатором. Это может быть COM1 для последовательного или LPT1 для параллельного или USB для USB.
-F: Это отменяет проверку подписи, чтобы убедиться, что чип, который, как вы думаете, вы программируете. Настоятельно рекомендуется выполнить тест, так как он проверяет соединение, поэтому не используйте этот переключатель.
-e: это стирает чип, обычно мы не используем это, потому что мы автоматически стираем флэш-память перед программированием.
-U :r|w|v:[:format]: ОК, это важная команда. Это тот, который на самом деле занимается программированием. — это либо flash, либо eeprom (или hfuse, lfuse или efuse для предохранителей конфигурации чипа, но мы не будем с ними связываться). r|w|v означает, что вы можете использовать r (чтение), w (запись) или v (проверка) в качестве команды. — это файл, в который вы хотите записать или прочитать. и [:format] означает, что есть необязательный флаг формата. Мы всегда будем использовать формат «Intel Hex», поэтому используйте i Так, например. Если вы хотите записать файл test.hex во флэш-память, вы должны использовать -U flash:w:test.hex:i. Если вы хотите прочитать память eeprom в файл «eedump.hex», вы должны использовать -U eeprom:r:eedump.hex:i
-n: Это означает, что вы на самом деле ничего не пишете, это хорошо, если вы хотите убедиться, что вы не отправляете никаких других команд, которые могут повредить чип, своего рода «предохранитель».
-V: отключает автоматическую проверку при записи. Мы хотим проверять, когда мы записываем во флэш-память, поэтому не используйте это.
-u: Если вы хотите изменить фьюз-биты, используйте этот переключатель, чтобы сказать, что вы действительно это имеете в виду.
-t: это «терминальный» режим, в котором вы можете вводить команды подряд. Не используйте это, это сбивает с толку новичков.
-E: Здесь перечислены некоторые спецификации программатора, не используйте его.
-v: Это дает вам «подробный» вывод… на случай, если вы хотите что-то отладить. Если хотите, можете использовать его, но в целом мы не будем.
-q: Противоположно предыдущему, меньше выходных данных. В общем, мы не будем его использовать, но, возможно, через некоторое время вы захотите.
Те, которые вы будете использовать в 99% случаев, выделены красным. Давайте рассмотрим их более подробно
Чтобы получить список поддерживаемых программистов, введите avrdude -c asdf ( asdf — это просто какая-то ерунда, чтобы заставить его выдать список программистов) Вот мой вывод, ваш может немного различаться. Не утруждайте себя запоминанием, просто пролистайте список.
C:\>avrdude -c asdf
avrdude: не удается найти идентификатор программиста «asdf»
Допустимые программисты: dasa3 = сбой последовательного порта, reset=!dtr sck=rts mosi=txd miso=cts [C:\WinAVR\bin\avrdude.conf:763] dasa = стук последовательного порта, reset=rts sck=dtr mosi=txd miso=cts [C:\WinAVR\bin\avrdude.conf:750] siprog = Lancos SI-Prog [C:\WinAVR\bin\avrdude.conf:737] ponyser = дизайн серийного номера ponyprog, reset=!txd sck=rts mosi=dtr miso=cts [C:\WinAVR\bin\avrdude.conf:724] frank-stk200 = Фрэнк STK200 [C:\WinAVR\bin\avrdude.conf:689] blaster = Altera ByteBlaster [C:\WinAVR\bin\avrdude.conf:676] ere-isp-avr = ERE ISP-AVR [C:\WinAVR\bin\avrdude.conf:666] atisp = кабель для программирования AT-ISP V1. 1 для AVR-SDK1 с [C:\WinAVR\bin\avrdude.conf:656] dapa = Кабель прямого параллельного доступа AVR [C:\WinAVR\bin\avrdude.conf:645] xil = JTAG-кабель Xilinx [C:\WinAVR\bin\avrdude.conf:632] futurlec = кабель для программирования Futurlec.com. [C:\WinAVR\bin\avrdude.conf:615] abcmini = Плата ABCmini, также известная как Dick Smith HOTCHIP [C:\WinAVR\bin\avrdude.conf:605] picoweb = Кабель для программирования Picoweb, http://www.picoweb.net/ [C:\WinAVR\bin\avrdude.conf:595] sp12 = программист Стива Болта [C:\WinAVR\bin\avrdude.conf:584] alf = Nightshade ALF-PgmAVR, http://nightshade.homeip.net/ [C:\WinAVR\bin\avrdude.conf:568] bascom = кабель для программирования Bascom SAMPLE [C:\WinAVR\bin\avrdude.conf:558] dt006 = Dontronics DT006 [C:\WinAVR\bin\avrdude.conf:548] pony-stk200 = Pony Prog STK200 [C:\WinAVR\bin\avrdude. conf:536] stk200 = STK200 [C:\WinAVR\bin\avrdude.conf:520] bsd = программист Брайана Дина, http://www.bsdhome.com/avrdude/ [C:\WinAVR\bin\avrdude.conf:509] pavr = программатор серийного номера pAVR Джейсона Кайла [C:\WinAVR\bin\avrdude.conf:501] dragon_dw = Atmel AVR Dragon в режиме debugWire [C:\WinAVR\bin\avrdude.conf:494] dragon_hvsp = Atmel AVR Dragon в режиме HVSP [C:\WinAVR\bin\avrdude.conf:486] dragon_pp = Atmel AVR Dragon в режиме PP [C:\WinAVR\bin\avrdude.conf:478] dragon_isp = Atmel AVR Dragon в режиме ISP [C:\WinAVR\bin\avrdude.conf:470] dragon_jtag = Atmel AVR Dragon в режиме JTAG [C:\WinAVR\bin\avrdude.conf:462] jtag2dw = Atmel JTAG ICE mkII в режиме debugWire [C:\WinAVR\bin\avrdude.conf:454] jtag2isp = Atmel JTAG ICE mkII в режиме ISP [C:\WinAVR\bin\avrdude.conf:446] jtag2 = Atmel JTAG ICE mkII [C:\WinAVR\bin\avrdude. conf:438] jtag2fast = Atmel JTAG ICE mkII [C:\WinAVR\bin\avrdude.conf:430] jtag2slow = Atmel JTAG ICE mkII [C:\WinAVR\bin\avrdude.conf:422] jtagmkII = Atmel JTAG ICE mkII [C:\WinAVR\bin\avrdude.conf:414] jtag1slow = Atmel JTAG ICE (mkI) [C:\WinAVR\bin\avrdude.conf:407] jtag1 = Atmel JTAG ICE (mkI) [C:\WinAVR\bin\avrdude.conf:399] jtagmkI = Atmel JTAG ICE (mkI) [C:\WinAVR\bin\avrdude.conf:391] avr911 = Atmel AppNote AVR911 AVROSP [C:\WinAVR\bin\avrdude.conf:385] avr109 = загрузчик Atmel AppNote AVR109 [C:\WinAVR\bin\avrdude.conf:379] бабочка = Atmel Butterfly Development Board [C:\WinAVR\bin\avrdude.conf:373] usbtiny = USBtiny простой программатор USB [C:\WinAVR\bin\avrdude.conf:367] usbasp = USBasp, http://www.fischl.de/usbasp/ [C:\WinAVR\bin\avrdude.conf:361] avr910 = недорогой серийный программатор Atmel [C:\WinAVR\bin\avrdude. conf:355] stk500hvsp = Atmel STK500 V2 в режиме высоковольтного последовательного программирования [C:\WinAVR\bin\avrdude.conf:349] stk500pp = Atmel STK500 V2 в режиме параллельного программирования [C:\WinAVR\bin\avrdude.conf:343] stk500v2 = прошивка Atmel STK500 версии 2.x [C:\WinAVR\bin\avrdude.conf:337] stk500v1 = прошивка Atmel STK500 версии 1.x [C:\WinAVR\bin\avrdude.conf:331] stk500 = Atmel STK500 [C:\WinAVR\bin\avrdude.conf:325] avrisp2 = Atmel AVR ISP mkII [C:\WinAVR\bin\avrdude.conf:315] avrispmkII = Atmel AVR ISP mkII [C:\WinAVR\bin\avrdude.conf:309] avrispv2 = Atmel AVR ISP V2 [C:\WinAVR\bin\avrdude.conf:303] avrisp = Atmel AVR ISP [C:\WinAVR\bin\avrdude.conf:297]
Вы заметите, что упомянутые ранее программисты перечислены здесь, в том числе AVRISP , AVRISPV2 , STK500 , Dragon , DASA/DASA3/PONYSER , DASA/DASA3/PONYSER ( DASA/DASA3/PONYSER ( DASA/DASA3/PONYSER , DASA3/PONYSER , DASA3/PONYSER (SERAMIN dt006/stk200 (программисты для параллельного порта)
Найдите имя используемого вами программатора и примите его к сведению!
Чтобы получить список частей, поддерживаемых avrdude, введите avrdude -c avrisp (это не имеет значения, если вы не используете программатор avrisp) без номера детали в командной строке. Не запоминайте этот список, просто просмотрите его, чтобы получить представление о поддерживаемых микросхемах.
C:\>avrdude -c avrisp avrdude: Часть AVR не указана, используйте «-p Part»
Это все фишки, что avrdude знает об этом. Почти все они программируются провайдером.
Осторожно : t2313 и 2313 , m8 и m88 , c128 и m 128 и т. д. внешне очень похожи, но на самом деле это совершенно разные чипы! По этой причине я предлагаю вам ввести название чипа, то есть вместо t2313 использовать attiny2313 или m8 использовать atmega8 . Avrdude достаточно умен, чтобы понять, что вы имеете в виду, если наберете полное имя.
Мы собираемся использовать ATtiny2313 , поэтому используйте номер детали attiny2313 или ( t2313 )
Дважды проверьте, какой чип вы используете, посмотрев на верхнюю часть чипа, там написано ATTINY2313 и ATMEGA соответственно) -20PI и -16PC — это просто рейтинги скорости и описания пакетов, поэтому пока игнорируйте их.
Этот переключатель сообщает avrdude, где искать ваш программатор. Если вы используете устройство, подключенное через USB, вы можете просто использовать -P usb или не указывать. Программатор автоматически определяет, когда программатор является USB-устройством.
Если вы используете программатор с параллельным или последовательным портом, вы должны использовать эту опцию, чтобы указать, к какому порту подключен программатор. В 99% случаев это lpt1 (параллельный) или com1 (последовательный), но вы всегда можете проверить это, заглянув в диспетчер устройств . Откройте панель управления Свойства системы
Нажмите Диспетчер устройств и откройте подменю Порты .
Перечислены все последовательные и параллельные порты. Может быть несколько COM-портов, но обычно есть только один параллельный (принтерный) порт.
Для компьютеров Mac параллельные порты отсутствуют. Однако, если вы используете последовательный USB-адаптер (который позволяет использовать STK500 или AVRISP v1 с Mac), вам необходимо указать последовательный порт. Я еще не знаю надежного способа, но я делаю это в Терминал Я набираю ls -l /dev/cu.* и он выдает кучу всего (я испортил снимок экрана, перед этим изображением есть еще одно окно, но просто игнорируйте его)
/dev/cu.Bluetooth — это встроенный модуль Bluetooth, не используйте его. /dev/cu.modem — это модем (если он есть), его тоже не используйте. То, что вы ищете, это что-то вроде /dev/cu.usbserial или /dev/cu.KeySerial1 или что-то подобное. В данном случае это /dev/cu.usbserial-FTCTYG5U
Хорошо, мы подошли к важной части. Вот тут-то мы и начинаем рассказывать avrdude , как поместить данные в чип. Эта команда довольно сложная, но мы разберем ее.
— может быть flash , eeprom, hfuse (высокий предохранитель), lfuse (низкий предохранитель) или efuse 2|9v2 (удлиненный предохранитель)
20 — можно р (читать), w (запись), v (проверка) — входной (запись или проверка) или выходной файл (чтение) [:format] — необязательный, формат файла. Вы можете оставить это значение отключенным для записи, но для чтения используйте i для Intel Hex (преобладающий стандарт)
Например:
Чтобы записать файл с именем firmware.hex во флэш-память, используйте команду: U flash:w:firmware.hex
: Чтобы проверить файл с именем mydata. eep из eeprom, используйте команду -U eeprom:v:mydata.eep
Чтобы прочитать низкий предохранитель в файл, используйте команду -U lfuse:r:lfusefile.hex:i
Хватит болтать. Пришло время запрограммировать прошивку в чип!
Подготовьте целевую плату AVR к работе, в этом примере мы будем использовать attiny2313 , но, конечно, вы должны заменить чип, который используете (в этом случае код, вероятно, ничего не сделает). Убедитесь, что устройство питается либо от батареек, либо от сетевой розетки, либо от программатора, если программатор может это сделать.
Загрузите файл test_leds.hex и поместите его в C:\ (Windows) или ваш домашний каталог (Mac)
Выясните, какой программатор вы используете и к какому порту он подключен (в этом примере я буду с помощью usbtinyisp, но все в порядке.) Поскольку usbtinyisp — это программатор USB, я могу не использовать переключатель -P .
Если вы используете параллельный программатор DT006 (например, MiniPOV2), вы, вероятно, захотите использовать команду вида avrdude -c dt006 -P lpt1 -p attiny2313 -U flash:w:test_leds.hex
Если вы используете последовательный программатор Bitbang DASA (например, MiniPOV3), вы, вероятно, захотите использовать команду вроде avrdude -c dasa -P com1 -p attiny2313 -U flash:w:test_leds.hex
Если вы используете программатор STK500 devboard, вы, вероятно, захотите использовать такую команду, как avrdude -c stk500 -P com1 -p attiny2313 -U flash:w:test_leds.hex
Если вы используете USB-программатор AVRISP v2, вы, вероятно, захотите использовать такую команду, как avrdude -c avrispv2 -p attiny2313 -U flash:w:test_leds.hex
и т.д…
Avrdude должен пройти следующие шаги:
Инициализация программатора (вы не увидите этого, если он работает)
Инициализация устройства AVR и проверка его готовности к инструкциям
Чтение подписи устройства ( 0x1e910a ), которая подтверждает, что указанный вами в командной строке чип ( attiny2313 ) на самом деле чип к которому подключен программатор
Стирание чипа
Чтение файла и проверка правильности файла
Запись flash
Проверка флэш-памяти
Fuse memory — это отдельный блок флэш-памяти, в который не записывается запись при обновлении микропрограммы. Вместо этого 3 предохранителя, как правило, устанавливаются один раз (хотя их можно устанавливать столько раз, сколько вы хотите). Фьюзы определяют такие параметры, как тактовая частота, тип кристалла, включен ли JTAG, уровень снижения напряжения (минимальное напряжение) и т. д. Для получения дополнительной информации о фьюзах вы можете прочитать о них здесь.
Сначала вам нужно рассчитать предохранители с помощью очень удобного калькулятора предохранителей AVR
Неправильная установка фьюзов может «заблокировать» чип — например, вы можете отключить будущее программирование или сделать так, чтобы чип ожидал внешнего кристалла, когда его нет. По этой причине я предлагаю трижды проверить значения предохранителей. Затем проверьте еще раз, убедитесь, что вы не отключили программирование интернет-провайдера или контакт сброса или не установили тактовую частоту на 32 кГц. Затем снова убедитесь, что у вас есть правильный чип для расчета. Тогда, наконец, вы можете попробовать записать их на чип!
Помните: после того, как вы установили фьюзы, вам не нужно устанавливать их снова
Если программатор неправильно подключен к чипу, вы получите следующее сообщение: попробуйте еще раз или используйте -F, чтобы переопределить эту проверку
Это означает, что программатор не смог поговорить с чипом. Если вы используете «простой» программатор, такой как программатор последовательного или параллельного порта, это может означать, что виноват программатор. В противном случае это обычно означает, что программатор в порядке, но не может найти чип.
Убедитесь, что микросхема запитана, правильно подключена к розетке или программатору, правильно ли подключены кабели программирования, правильно ли подключен разъем и т.