1. Директивы начинаются с точки (.INCLUDE, .DB)
2. Определения регистров для ATmega16 можно взять в файле c:\Program Files\Atmel\AVR Tools\AvrAssembler\Appnotes\m16def.inc . Для этого его нужно скопировать в директорию проекта, снять на копии атрибут "только чтение" и включить в начало ассемблерной программы командой
.INCLUDE "m16def.inc"
Кроме того, в этом файле нужно закомментировать строку (иначе ассемблер ругнется на переопределение директивы OR):
;.equ OR =3
После этого можно в программе указывать символьные имена.
3. Инициализация стека в ATmega16:
.ORG 0
JMP RESET
...
RESET:
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
...
4. Назначение имен константам (например, для обозначения ножек процессора):
.EQU _KEY =PB7
.EQU _LED =PB6
.EQU OC0 =PB3
.EQU _BEEPER =PB1
LDI r16, (1<<_KEY)|(1<<_LED)|(1<<OC0)|(1<<_BEEPER) ;0xCA
out PORTB, r16
5. Для назначения имен регистрам применяется команда .DEF или .SET:
.DEF ampl =r0
.DEF time8a =r1
6. Константы напрямую могут загружаться только в регистры r16..r31, и только оттуда - в другие регистры:
ldi r16, 128
mov r0, r16
7. Константы из таблиц памяти программ может считывать только команда LPM, которая загружает данные в регистр R0 через адрес, который загружается в регистровую пару Z. Замечу, то TABLE - это метка в сегменте .CSEG, и поскольку каждая команда занимает 2 байта, адрес метки TABLE надо умножить на 2.
ldi ZL, low(TABLE*2)
ldi ZH, hi(TABLE*2)
lpm
В новых процесорах tiny и mega команда lpm усовершенствовалась в команду ld. Теперь можно загружать любой регистр (r0..r31):
ldi ZH, high(Table_1<<1)
ldi ZL, low(Table_1<<1)
lpm r16, Z
Для 256-байтных таблиц удобно, например, выравнивать положение таблиц в памяти сразу на 256 байт с помощью директивы .ORG:
.ORG 0x0400
SINUS:
;таблица синуса из 256 байт - по адресу 0 лежит sin(0*2pi),
; по адресу 255 лежит sin(2*pi - 2*pi/256)
.DB 128,131,134,137,140,143,146,150
...
.DB 103,106,110,113,116,119,122,125
Эта хитрость позволяет сразу в младший байт грузить индекс таблицы:
ldi r16, 4 ;инкремент фазы fi0 на константу 4
add fi0, r16 ;
ldi ZH,HIGH(SINUS*2) ;загрузка начала таблицы
mov ZL, fi0 ; поскольку младший байт адреса таблицы у нас 0, в ZL
lpm ampl,Z ; можно грузить сразу индекс амплитуды
8. В обработчиках прерывания почти всегда нужно сохранять регистр статуса SREG. Делается это специальным образом - сохраняется SREG в стек через пересылку в обычный регистр r0..r31, поскольку команды PUSH/POP работают только с регистрами r0..r31:
TIMER0_OVF_vect:
push r16
in r16, SREG
...
out SREG, r16
pop r16
reti
|
Комментарии
2013-04-0311:44:23 Highlander-у: да, наверное, только если все равно, что число в r16 потеряешь.
2010-12-0119:07:55 Всё хорошо, только правильно будет так:
TIMER0_OVF_vect :
in r16, SREG
push r16
pop r16
out SREG, r16
reti