Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Вымогатель припоя
Аватара пользователя
Сообщения: 516
Зарегистрирован: Пт янв 18, 2013 15:11:02

Сообщение strengerst »

Книга не дает практики, и многое само сабой тоже не снимается. А форумы для того создали что бы общались и помогали, тем более конкретно вас Demiurg не кто не просит тратить свое время, перейдите на другой раздел форума или вообще помогите другим более опытным участникам.
Реклама
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Вы, последние двое задали те вопросы, ответы на которые получите из этой книги. Плюс примеры программ для практики. Не надо рассматривать форумы как отвечалки на простые элементарные вопросы. А вот когда затруднения, тогда уже другой вопрос.
Контактная информация:
Реклама
Открыл глаза
Сообщения: 55
Зарегистрирован: Вс май 03, 2015 15:05:58

Сообщение Feruz »

Минутка полезностей! :shock: Делюсь кодом на ассемблере для организации точных задержек на AVR. Точность до такта. Надеюсь будет полезно, так как в свое время обыскался!
short_delay я откопал на каком-то форуме (скрин), long_delay писал сам по образу и подобию short_delay.
Представлено в виде макроса. Пример использования в коде: "long_delay 123456" - дает задержку ровно на 123456 тактов.

nop'ы в конце long_delay обязательны!

Код: Выделить всё

	//задержка на 8-65543 тактов
	.macro short_delay					
		ldi r24, low( @0 - 8 )
		ldi r25, high( @0 - 8 )
		sbiw r24, 4
		brcc pc - 1
		cpi r24, 0xFD	
		brcs pc + 4
		breq pc + 3
		cpi r24, 0xFF
		breq pc + 1
	.endmacro

Код: Выделить всё

	//задержка на 13-16777228 тактов
	.macro long_delay
		ldi r16, low( @0 - 13 )
		ldi r17, high( @0 - 13 )
		ldi r18, byte3( @0 - 13 )
		subi r16, 5
		sbci r17, 0
		sbci r18, 0
		brcc pc - 3
		cpi r16, 0xFB
		brcs pc + 8
		breq pc + 7
		cpi r16, 0xFD
		brcs pc + 6
		breq pc + 5
		cpi r16, 0xFF
		brcs pc + 4
		breq pc + 3
		nop
		nop
	.endmacro
Вложения
short_delay.jpg
(41.85 КБ) 259 скачиваний
Встал на лапы
Сообщения: 106
Зарегистрирован: Чт сен 10, 2015 06:59:03
Откуда: Гродно, BY

Сообщение trofim2 »

Мой вариант:

Код: Выделить всё

.macro Delay_mks		;Delay_mks const
.if (@0*F_cpu/1000000-1)/3 < 255
 .if (@0*F_cpu/1000000-1)/3 > 0
	ldi Tmp,(@0*F_cpu/1000000-1)/3
 _delay:
	dec Tmp
	brne _delay
 .endif
 .if @0*F_cpu/1000000-@0*F_cpu/1000000/3*3 >0
	nop
 .endif
 .if @0*F_cpu/1000000-@0*F_cpu/1000000/3*3 >1
	nop
 .endif
.else
	push zl
	push zh
	ldi zl,Low(@0*F_cpu/1000000-7)/4
	ldi zh,High(@0*F_cpu/1000000-7)/4
 _delay:
	sbiw zl,1
	brne _delay
	pop zh
	pop zl
.endif
.endm

Реклама
Эиком - электронные компоненты и радиодетали
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Обббалдеть не встать!
А теперь задержки на единицы, десятки, сотни миллисекунд. Срочно в студию! Ведь это касается организации программ...
Контактная информация:
Реклама
Встал на лапы
Сообщения: 106
Зарегистрирован: Чт сен 10, 2015 06:59:03
Откуда: Гродно, BY

Сообщение trofim2 »

А вот этого не надо
Реклама
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

[uquote="trofim2",url="/forum/viewtopic.php?p=3281431#p3281431"]А вот этого не надо[/uquote]
Чего именно?
Контактная информация:
Встал на лапы
Сообщения: 106
Зарегистрирован: Чт сен 10, 2015 06:59:03
Откуда: Гродно, BY

Сообщение trofim2 »

Миллисекунд
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Имхо, если в программе есть прерывания, то все эти суперточные задержки превращаются в тыкву. А прерывания есть в любой мало-мальски сложной программе.
Контактная информация:
Встал на лапы
Сообщения: 106
Зарегистрирован: Чт сен 10, 2015 06:59:03
Откуда: Гродно, BY

Сообщение trofim2 »

При микросекундных задержках, при необходимости, можно прерывания и запретить.
В каждом конкретном случае решать самому, что важнее, а что нет.
Друг Кота
Аватара пользователя
Сообщения: 15791
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Обычно при особых требованиях задержки генерируются программно.
При подобном подходе естественно запрещаются ВСЕ прерывания на время генерации критичных временных интервалов.
Дополнительная проблема - учет неравноценности времени обработки команд условного перехода в конце счетного цикла. И добавок в виде оценки условий при исполнении нескольких циклов в едином алгоритме.
Как пример особо жесткого подхода к равнозначности серии временных интервалов при дополнительной оценке условий выполнения циклов - программная реализация протокола обмена для светодиодов типа WS2812 (выполнена как элемент - заготовка библиотеки):
Спойлер;
;
; trd2812_m.txt
;
; файл обработчика передачи массива
; из буфера вывода в линейку на основе WS2812B
; базовый МК из линейки АТМЕЛ при тактовой частоте
; от 16 Мегагерц ( 0,000000062 S)
;
; требуемые интервалы по даташиту WS2812B
;
;Data transfer time( TH+TL=1.25µs±600ns)
; T0H 0 code ,high voltage time 0.4us ±150ns
; T1H 1 code ,high voltage time 0.8us ±150ns
; T0L 0 code ,low voltage time 0.85us ±150ns
; T1L 1 code ,low voltage time 0.45us ±150ns
; RES low voltage time Above 50µs
; исходный уровень линии связи = 0
; данные передаются пакетами из трех байт на точку
; старшими битами вперед в последовательности
; соответствующей G - R - B цветам точки
; количество блоков должно соответствовать
; количеству точек в ленте
;
; реальные данные согласно тест - отладки дебаггером (версия1!)
; авр-студио 4.19
;
; Data transfer time( TH+TL=1.38µs -10ns)
; T0H 0 code ,high voltage time 0.44us ±10ns
; T1H 1 code ,high voltage time 0.88us ±10ns
; T0L 0 code ,low voltage time 0.94us ±10ns
; T1L 1 code ,low voltage time 0.50us ±10ns
; RES low voltage time 192,88uS (Above 50µs)
;
; длина прерывания с пакетом загрузки (x60*3) = 2175uS (0.002175)
; интервал между прерываниями (irq t/c0) = 0.004S (4000uS)
;
; define datas
; .equ port_out = PORTB ; порт вывода (по усмотрению)
; .equ out_line = 0 ; линия вывода данных
; .equ bufout = SRAM_START ; начальный адрес буфера вывода
; .equ pixel = 60 ; количество точек в линейке/ленте
; .equ bufout_size = (pixel * 3) ; не может быть более объема ОЗУ - стек!!!


;таблица обьявленных имен - переназначение регистров РОН
;
; .def name = r31 ; ZH регистр (полный)
; .def name = r30 ; ZL регистр (полный)
; .def name = r29 ; YH регистр (полный)
; .def name = r28 ; YL регистр (полный)
; .def name = r27 ; XH регистр (полный) указатель текущей ячейки массива bufout
; .def name = r26 ; XL регистр (полный) указатель текущей ячейки массива bufout
; .def name = r25 ; регистр (полный) BH
; .def name = r24 ; регистр (полный) BL
; .def name = r23 ; регистр (полный)
; .def name = r22 ; регистр (полный)
; .def name = r21 ; регистр (полный)
; .def name = r20 ; регистр (полный)
; .def name = r19 ; регистр (полный)
; .def name = r18 ; регистр (полный)
; .def tmp1 = r17 ; регистр (полный) счетчик байт вывода
; .def tmp0 = r16 ; регистр (полный) буфер выводимого байта
; .def regn = r15 ; регистр (урезан)
; .def regn = r14 ; регистр (урезан)
; .def regn = r11 ; регистр (урезан)
; .def regn = r10 ; регистр (урезан)
; .def regn = r9 ; регистр (урезан)
; .def regn = r8 ; регистр (урезан)
; .def regn = r7 ; регистр (урезан)
; .def regn = r6 ; регистр (урезан)
; .def regn = r5 ; регистр (урезан)
; .def regn = r4 ; регистр (урезан)
; .def regn = r3 ; регистр (урезан)
; .def regn = r2 ; регистр (урезан)
; .def matr = r1 ; регистр (урезан) r1 по возможности не использовать!!!
; .def madr = r0 ; регистр (урезан) r0 по возможности не использовать!!!
;
;-----------------------------------------
; .macro ;; ввод и предобработка данных
;
;
; .endmacro
;
;-----------------------------------------
;
; определение буфера вывода в области данных
; .dseg
; .org bufout
;point0: .byte 3 ; g:r:b
;point1: .byte 3 ; g:r:b
;point2: .byte 3 ; g:r:b
;point3: .byte 3 ; g:r:b
;point4: .byte 3 ; g:r:b
;point5: .byte 3 ; g:r:b
;point6: .byte 3 ; g:r:b
;point7: .byte 3 ; g:r:b
;point8: .byte 3 ; g:r:b
;point9: .byte 3 ; g:r:b
;point10: .byte 3 ; g:r:b
;point11: .byte 3 ; g:r:b
;point12: .byte 3 ; g:r:b
;point13: .byte 3 ; g:r:b
;point14: .byte 3 ; g:r:b
;point15: .byte 3 ; g:r:b
;point16: .byte 3 ; g:r:b
;point17: .byte 3 ; g:r:b
;point18: .byte 3 ; g:r:b
;point19: .byte 3 ; g:r:b
;point20: .byte 3 ; g:r:b
;point21: .byte 3 ; g:r:b
;point22: .byte 3 ; g:r:b
;point23: .byte 3 ; g:r:b
;point24: .byte 3 ; g:r:b
;point25: .byte 3 ; g:r:b
;point26: .byte 3 ; g:r:b
;point27: .byte 3 ; g:r:b
;point28: .byte 3 ; g:r:b
;point29: .byte 3 ; g:r:b
;point30: .byte 3 ; g:r:b
;point31: .byte 3 ; g:r:b
;point32: .byte 3 ; g:r:b
;point33: .byte 3 ; g:r:b
;point34: .byte 3 ; g:r:b
;point35: .byte 3 ; g:r:b
;point36: .byte 3 ; g:r:b
;point37: .byte 3 ; g:r:b
;point38: .byte 3 ; g:r:b
;point39: .byte 3 ; g:r:b
;point40: .byte 3 ; g:r:b
;point41: .byte 3 ; g:r:b
;point42: .byte 3 ; g:r:b
;point43: .byte 3 ; g:r:b
;point44: .byte 3 ; g:r:b
;point45: .byte 3 ; g:r:b
;point46: .byte 3 ; g:r:b
;point47: .byte 3 ; g:r:b
;point48: .byte 3 ; g:r:b
;point49: .byte 3 ; g:r:b
;point50: .byte 3 ; g:r:b
;point51: .byte 3 ; g:r:b
;point52: .byte 3 ; g:r:b
;point53: .byte 3 ; g:r:b
;point54: .byte 3 ; g:r:b
;point55: .byte 3 ; g:r:b
;point56: .byte 3 ; g:r:b
;point57: .byte 3 ; g:r:b
;point58: .byte 3 ; g:r:b
;point59: .byte 3 ; g:r:b
;
;-----------------------------------------

.cseg
.org 0x0020 ; старовая позиция 0х0020 !!!
slot0:
; 6/14 (6-4=2 посему роль остатка выполняет CBI)
cbi port_out,out_line ; 2 цикла
nop
nop
nop
nop
nop
nop
nop
nop
nop
ret ; 4 цикла
.org (slot0+16)
slot1:
nop ; 13/7 (13-4=9)
nop
nop
nop
nop
nop
nop
cbi port_out,out_line ; 2 цикла
nop
nop
ret ; 4 цикла
.org 0x0060
xslot0:
; 6/14 (6-5=1 посему роль остатка выполняет CBI с избытком в 1 nop)
cbi port_out,out_line ; 2 цикла
cbr zl,(1<<6) ; модификация указателя 1 цикл
nop
nop
nop
nop
nop
nop ; -2 цикла на ld tmp0,x+
dec tmp1 ; 1 цикл
brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле)
rjmp trasstt ; 2 цикла
.org (xslot0+16)
xslot1:
nop ; 13/7 (13-5=8)
cbr zl,(1<<6) ; модификация указателя 1 цикл
nop
nop
nop
nop
nop
cbi port_out,out_line ; 2 цикла
; -2 цикла на ld tmp0,x+
dec tmp1 ; 1 цикл
brbs SREG_Z,ends_trd ; 1 цикл при неисполнении (в цикле)
rjmp trasstt ; 2 цикла
;
ends_trd:
pop tmp0
pop tmp1
pop xl
pop xh
pop zl
pop zh ; восстановить рабочую область из стека
ret
;-----------------------------------------
;
; предварительно:
; линия out_line настроена на вывод
; исходный уровень out_line =0
; указатель стека усатновлен на RAMEND
; массив данных (bufout:bufout_size) предварительно загружен
; флаг готовности массива данных установлен
;
mass_trm:
push zh
push zl
push xh
push xl
push tmp1
push tmp0 ; храним рабочую область в стеке
res_line:
ldi tmp0,4
ser tmp1
cbi port_out,out_line
res_time:
dec tmp1
brne res_time
dec tmp0
brne res_time ; =>50uS time out
ldi xh,high (bufout)
ldi xl,low (bufout) ; загрузка начального адреса массива
; в указатель
ldi tmp1,bufout_size
ldwi z,slot0 ; адрес начала таблицы в указателе
;-----------------------------------------
trasstt:
ld tmp0,x+ ; 2 цикла
slot_0:
sbi port_out,out_line ; 2 цикла реально до установки 3 цикла
bst tmp0,7 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла = 4 цикла от out_line=1
;----------------
slot_1:
sbi port_out,out_line
bst tmp0,6 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_2:
sbi port_out,out_line
bst tmp0,5 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_3:
sbi port_out,out_line
bst tmp0,4 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_4:
sbi port_out,out_line
bst tmp0,3 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_5:
sbi port_out,out_line
bst tmp0,2 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_6:
sbi port_out,out_line
bst tmp0,1 ; 1 цикл
bld zl,4 ; 1 цикл
icall ; 3 цикла
;----------------
slot_7:
sbi port_out,out_line
sbr zl,(1<<6) ; модификация указателя под завершающий фрагмент
; 1 цикл
bst tmp0,0 ; 1 цикл
bld zl,4 ; 1 цикл
ijmp ; 3 цикла
;----------------
естественно прерывания на время выполнения загрузки массива должны быть запрещены.
8)
Встал на лапы
Сообщения: 106
Зарегистрирован: Чт сен 10, 2015 06:59:03
Откуда: Гродно, BY

Сообщение trofim2 »

Такие задержки правильнее называть наносекундными.
Вымогатель припоя
Аватара пользователя
Сообщения: 516
Зарегистрирован: Пт янв 18, 2013 15:11:02

Сообщение strengerst »

Подскажите примером как правильно на ассемблере забрать значения с регистров ADCH и ADCL и присвоить полученное значение регистру R16. При условии что выравнивания по левому краю установлено в настройках.
На СИ нашел вроде так делается: v=(ADCL|ADCH<<8); а как на ассемблере.
Друг Кота
Аватара пользователя
Сообщения: 7083
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

так там v 16 битная... а утебя R16 восмибитный, так что выбирай какие биты ADC тебе нужны, если старшие то сначала прочитай в него ADCL, а потом в него же ADCH (старое значение затрется и останутся только старшие 8 бит)

Добавлено after 1 minute 42 seconds:
на С часто делается v=ADC; остальное уже сам компилятор разберёт.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Вымогатель припоя
Сообщения: 615
Зарегистрирован: Вс дек 28, 2014 21:54:05

Сообщение dgrett »

Я читаю сразу ADCH:
in temp,ADCH
И все шуршит. Только сперва устанавливаю ADLAR
Я всё-всё узнAю и стану профессором.
Друг Кота
Аватара пользователя
Сообщения: 7083
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

возможно, просто есть ряд 16битных регистров (у таймеров точно) при чтении (или записи) одного бита второй блокируется, чтобыпрочитано было именно то что было в регистре (а то пока читал один бит - регистр изменился и в результате получим хвост павлиний, рога оленьи - в смысле от совершенно разных значений)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Вымогатель припоя
Аватара пользователя
Сообщения: 516
Зарегистрирован: Пт янв 18, 2013 15:11:02

Сообщение strengerst »

Если я правильно понял то можно прост считать ADCH после установки ADLAR. а ADCL можно вообще не трогать.
Вымогатель припоя
Сообщения: 615
Зарегистрирован: Вс дек 28, 2014 21:54:05

Сообщение dgrett »

Ну с таймерами и т.д. я обращаюсь по ДШ

Добавлено after 1 minute 58 seconds:
[uquote="strengerst",url="/forum/viewtopic.php?p=3284644#p3284644"]Если я правильно понял то можно прост считать ADCH после установки ADLAR. а ADCL можно вообще не трогать.[/uquote]
Я именно так и делаю, говорю же, шуршит
Я всё-всё узнAю и стану профессором.
Друг Кота
Аватара пользователя
Сообщения: 7083
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

[uquote="strengerst",url="/forum/viewtopic.php?p=3284644#p3284644"]Если я правильно понял то можно прост считать ADCH после установки ADLAR. а ADCL можно вообще не трогать.[/uquote]скорее всего да, ну если не взлетит - знаешь куда копать.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Вымогатель припоя
Аватара пользователя
Сообщения: 516
Зарегистрирован: Пт янв 18, 2013 15:11:02

Сообщение strengerst »

Спасибо буду пробовать.
Ответить

Вернуться в «AVR»