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

Обсуждаем контроллеры компании Atmel.
Ответить
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

neoneon писал(а):Если поставить brne, то когда в delay2 установится 0x00, т.е. сбросится полностью (а в delay1 еще будет FF), установится флаг нулевого результата Z=1, программа выйдет из цикла. Так?
Оказывается не так! После обнуления delay2 0x00, когда delay1 0xFF флаг Z не устанавливается. Проверял в студии кодом ниже. В железе поведение аналогично; длительность интервала 1, формируемого brcc составила 3006 мкс,а длительность интервала 0, формируемого brne 3004 мкс.
Спойлер

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

	.INCLUDE "tn2313def.inc"
	.equ	Fo=1000000
	.def	delay1=R16	; младший регистр
	.def	delay2=R17	; старший регистр
	.CSEG
	.ORG	$00
START:
	LDI	R16,LOW(RAMEND)
	OUT	SPL,R16
	SBI	DDRD,2	;
TEST_BRNE:
	LDI	delay1,$EE
	LDI	delay2,$02
LOOP_BRNE:
	SUBI	delay1,1
	SBCI	delay2,0
	BRNE	LOOP_BRNE
	SBI	PORTD,2
TEST_BRCC:
	LDI	delay1,$EE
	LDI	delay2,$02
LOOP_BRCC:
	SUBI	delay1,1
	SBCI	delay2,0
	BRCC	LOOP_BRCC
	CBI	PORTD,2
	RJMP	TEST_BRNE
СпойлерИзображение
СпойлерИзображение
SBCI_BRNE.GIF
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

:shock: это как? Пойду проверять!
---------
Проверил. Действительно так. Век живи - век учись.. :)
Fucking static initialization order fiasco
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 115
Зарегистрирован: Ср окт 22, 2014 07:39:26
Откуда: Омск

Сообщение neoneon »

akl писал(а): Оказывается не так!
Судя по логическому выражению, флаг Z установится, когда в предыдущих (максимум 8 ) операциях в результате будет 0. Не подскажете, где эту картинку взяли? :)
Разница в 2мкс - это из-за того, что brcc доходит до -1, а brne до 0, верно?
Полный чайник.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Там имеются в виду не операции, а биты. Всего 8 бит. Когда они все (биты) результата равны нулю и если флаг Z от предыдущей операции равен 1 (результат был равен 0), то Z установится в 1. Иначе 0.
2 мкс - да, поэтому.
Взята картинка из документа "Instruction set" для AVR. Поищите через гугл.
Fucking static initialization order fiasco
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 115
Зарегистрирован: Ср окт 22, 2014 07:39:26
Откуда: Омск

Сообщение neoneon »

Akl, Pink-Pank выражаю благодарность за терпение и помощь, разобрался :)
Полный чайник.
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 63
Зарегистрирован: Вс май 30, 2010 20:27:33
Откуда: Санкт-Петербург

Сообщение Kill17 »

День добрый!

Столкнулся с проблемой. Есть слово(2байта), нужно побитно сдвинуть его влево-вправо на 2 бита.
С байтам проблем нету, а тут тупик какой-то.
Камень - atmega32
Asm - Avrstudio4
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Kill17 писал(а):Столкнулся с проблемой. Есть слово(2байта), нужно побитно сдвинуть его влево-вправо на 2 бита.
Asm - Avrstudio4
Сдвиг слова r17:r16 вправо на два бита:

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

            clc
            ror     r17
            ror     r16
            clc
            ror     r17
            ror     r16
Сдвиг слова r17:r16 влево на два бита:

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

            clc
            rol     r16
            rol     r17
            clc
            rol     r16
            rol     r17
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Как вариант

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

	LSR	R17
	ROR	R16
	LSR	R17
	ROR	R16

	LSL	R16
	ROL	R17
	LSL	R16
	ROL	R17
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Вроде как lsl, lsr не работают с флагом Carry. У Вас потеряются биты.
Fucking static initialization order fiasco
Контактная информация:
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Это кто вам сказал? lsr сдвигает вправо, на место 7-го бита ставится 0, 0-й бит помещается в C. lsl - наоборот, на место 0-го ставится 0, 7-й уходит в С.
Друг Кота
Аватара пользователя
Сообщения: 6349
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

COKPOWEHEU, вот именно. И бит от первого сдвига потеряется : В С - то он задвинулся, но во втором LSL/LSR не используется, заполняется нулем. Но и вариант zero648 не самый оптимальный.

Лучше всего так, как у aki

Земляк WiseLord меня опередил. Минчане, чего вам не рождествуется, все форумуетесь :)
Последний раз редактировалось Jack_A Ср янв 07, 2015 11:47:13, всего редактировалось 6 раз.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Получается как-то так:

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

        |   R17    |   R16    | C
--------+----------+--------------
        | abcdefgh | ijklmnop | x
--------+----------+----------+---
LSR R17 | 0abcdefg | ijklmnop | h
ROR R16 | 0abcdefg | hijklmno | p
LSR R17 | 00abcdef | hijklmno | g
ROR R16 | 00abcdef | ghijklmn | o

        |   R17    |   R16    | C
--------+----------+--------------
        | abcdefgh | ijklmnop | x
--------+----------+----------+---
LSL R16 | abcdefgh | jklmnop0 | i
ROL R17 | bcdefghi | jklmnop0 | p
LSL R16 | bcdefghi | klmnop00 | j
ROL R17 | cdefghij | klnmop00 | o
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Вопрос:

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

			.equ	DB4		= PORTC7
			.equ	DB5		= PORTВ6
			.equ	DB6		= PORTА0
			.equ	DB7		= PORTD3
Так будет работать? Т.е. я хочу подключить к разным пинам разных портов. Будет ли у меня далее в программе понимать, что DB4 - это PORTC7?
Станислав
Друг Кота
Аватара пользователя
Сообщения: 6349
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Не будет. Директива .equ просто определяет числовой константе символьное имя для более легкого понимания и модификации исходника программы. Ну какое число можно сопоставить в директиве .equ DB4 = PORTC7 идентификатору 'PORTC7' так, чтобы одним числом выражался и адрес порта, и номер бита в нем ? И вообще, директива ассемблера -- не волшебная палочка, которая может делать то, что не может делать машинный код. Ну представьте, что вышеуказанную директиву компилятор принял, и у вас написано выражение, где это DB4 использовано. Какой машинный код будет сгенерирован в этом случае ?
Последний раз редактировалось Jack_A Ср янв 07, 2015 12:16:25, всего редактировалось 1 раз.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Блин.... И я об этом думаю. Поэтому и задал вопрос для того, чтобы подтвердить сомнения...
Тогда другой вопрос.
Хочу назначить выводы индикатора на любые пины ЛЮБЫХ портов МК. Как правильно их объявить (определить)? Хочу дальше в программе не заморачиваться и писать ДБ4, а подобие дефайнов само определяло, куда он там подключен.
Станислав
Друг Кота
Аватара пользователя
Сообщения: 6349
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Я думаю, с помощью макросов. Изменяя параметры в вызове макроса или макроопределении, можно изменять назначение разрядов/адресов. А "само" типа "разбирайтесь по своим местам" ничего не сможет, по любому назначения определяются в программе, и для того, чтобы прогу лучше понимать/корректировать макросы -- хороший инструмент.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А ведь, точно! Мне же по сути не нужны по отдельности линии DB, мне нужен целиком порт и значение в нем.
Спойлер

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

			
			.equ	DB7port = PORTC
			.equ	DB7pin	= 3

			.equ	DB6port = PORTC
			.equ	DB6pin  = 2

			.equ	DB5port = PORTC
			.equ	DB5pin  = 1

			.equ	DB4port = PORTC
			.equ	DB4pin  = 0

			.equ	RSport  = PORTC
			.equ	RSpin   = 5

			.equ	Eport	= PORTC
			.equ	Epin	= 4
		
	
	.MACRO	DATA						; Вызываем просто DATA TETRADA, предварительно положив в ТЕТРАДУ то, что нужно вывести.

				lsr @0				; Сдвигаем вправо, крайний вывалится в С
				brcc Pusto1				; Если С=0, то переходим по метке
				sbi  DB4port, DB4pin	; Иначе, выставляем бит в 1
				rjmp Next1				; Идем проверять следующий
		Pusto1: cbi	 DB4port, DB4pin	; Выставляем бит в 0
			

		Next1:	lsr @0				; Сдвигаем вправо, крайний вывалится в С
				brcc Pusto2				; Если С=0, то переходим по метке
				sbi  DB5port, DB5pin	; Иначе, выставляем бит в 1
				rjmp Next2				; Идем проверять следующий
		Pusto2: cbi	 DB5port, DB5pin	; Выставляем бит в 0
			

		Next2:	lsr @0				; Сдвигаем вправо, крайний вывалится в С
				brcc Pusto3				; Если С=0, то переходим по метке
				sbi  DB6port, DB6pin	; Иначе, выставляем бит в 1
				rjmp Next3				; Идем проверять следующий
		Pusto3: cbi	 DB6port, DB6pin	; Выставляем бит в 0
			

		Next3:	lsr @0				; Сдвигаем вправо, крайний вывалится в С
				brcc Pusto4				; Если С=0, то переходим по метке
				sbi  DB7port, DB7pin	; Иначе, выставляем бит в 1
				rjmp Next1				; Идем проверять следующий
		Pusto4: cbi	 DB7port, DB7pin	; Выставляем бит в 0
			
	
	.ENDM
А так будет работать? Думаю, что будет. Но код не оптимальный... Может кто ткнет носом, как проще вывести то, что находится в флаге переноса прямо на пин нужного порта?
Последний раз редактировалось СКАЗОЧНИК Ср янв 07, 2015 14:15:37, всего редактировалось 1 раз.
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

Вывод на индикатор с произвольным расположением портов делал так:
Спойлер

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

;Write nibble to LCD:
;Input:	temp7..temp4 - data nibble

LCD_WN:	bbrc	temp,7,lwr7_0
	Port_LCD_D7_1		;D7 <- 1
	rjmp	lwr6	
lwr7_0:	Port_LCD_D7_0		;D7 <- 0
lwr6:	bbrc	temp,6,lwr6_0
	Port_LCD_D6_1		;D6 <- 1
	rjmp	lwr5	
lwr6_0:	Port_LCD_D6_0		;D6 <- 0
lwr5:	bbrc	temp,5,lwr5_0
	Port_LCD_D5_1		;D5 <- 1
	rjmp	lwr4	
lwr5_0:	Port_LCD_D5_0		;D5 <- 0
lwr4:	bbrc	temp,4,lwr4_0
	Port_LCD_D4_1		;D4 <- 1
	rjmp	lwrend	
lwr4_0:	Port_LCD_D4_0		;D4 <- 0

lwrend:	Port_LCD_E_1		;E <- 1
	rcall	Delay		;delay 2 uS
	Port_LCD_E_0		;E <- 0
	ret
 
Там используется макрос, вот мои макросы:
Спойлер
;***** Macros

.macro clbr ;clear bit in register
cbr @0,exp2(@1)
.endm

.macro stbr ;set bit in register
sbr @0,exp2(@1)
.endm

.macro bbrc ;branch if bit in register clear
sbrs @0,@1
rjmp @2
.endm

.macro bbrs ;branch if bit in register set
sbrc @0,@1
rjmp @2
.endm

.macro bbic ;branch if bit in I/O clear
sbis @0,@1
rjmp @2
.endm

.macro bbis ;branch if bit in I/O set
sbic @0,@1
rjmp @2
.endm

.macro addi ;add immediate
subi @0,-@1
.endm

.macro ldx ;load XL, XH with word
ldi XL,byte1(@0)
ldi XH,byte2(@0)
.endm

.macro ldy ;load YL, YH with word
ldi YL,byte1(@0)
ldi YH,byte2(@0)
.endm

.macro ldz ;load ZL, ZH with word
ldi ZL,byte1(@0)
ldi ZH,byte2(@0)
.endm

.macro table ;load Z pointer
ldi ZL,low (@0*2)
ldi ZH,high(@0*2)
.endm

.macro stdi ;store immediate indirect with displacement
ldi temp,@1
std @0,temp
.endm

.macro ldsx ;load XL, XH from memory
lds XL,@0+0
lds XH,@0+1
.endm

.macro ldsy ;load YL, YH from memory
lds YL,@0+0
lds YH,@0+1
.endm

.macro ldsz ;load ZL, ZH from memory
lds ZL,@0+0
lds ZH,@0+1
.endm

.macro stsx ;store XL, XH in memory
sts @0+0,XL
sts @0+1,XH
.endm

.macro stsy ;store YL, YH in memory
sts @0+0,YL
sts @0+1,YH
.endm

.macro stsz ;store ZL, ZH in memory
sts @0+0,ZL
sts @0+1,ZH
.endm
Описание пинов портов делал так:
Спойлер

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

;
Port С:

.equ	DIRC	= 0b11111111		;Port C direction
.equ	PUPC	= 0b11111111		;Port C pull-ups

.equ	LCD_D6	= PC1			;LCD D6 data line
.equ	LCD_D7	= PC3			;LCD D7 data line

.macro	Port_LCD_D6_0			;LCD_D6 = 0
	cbi	PORTC,LCD_D6
.endm

.macro	Port_LCD_D6_1			;LCD_D6 = 1
	sbi	PORTC,LCD_D6
.endm

.macro	Port_LCD_D7_0			;LCD_D7 = 0
	cbi	PORTC,LCD_D7
.endm

.macro	Port_LCD_D7_1			;LCD_D7 = 1
	sbi	PORTC,LCD_D7
.endm

Port D:

.equ	DIRD	= 0b11111110		;Port D direction
.equ	PUPD	= 0b11111111		;Port D pull-ups
.equ	LCD_W	= PD2			;LCD W line
.equ	LCD_E	= PD3			;LCD E line
.equ	LCD_D4	= PD4			;LCD D4 data line
.equ	LCD_D5	= PD5			;LCD D5 data line

.macro	Port_LCD_W_0			;LCD_W = 0
	cbi	PORTD,LCD_W
.endm

.macro	Port_LCD_W_1			;LCD_W = 1
	sbi	PORTD,LCD_W
.endm

.macro	Port_LCD_E_0			;LCD_E = 0
	cbi	PORTD,LCD_E
.endm

.macro	Port_LCD_E_1			;LCD_E = 1
	sbi	PORTD,LCD_E
.endm

.macro	Port_LCD_D4_0			;LCD_D4 = 0
	cbi	PORTD,LCD_D4
.endm

.macro	Port_LCD_D4_1			;LCD_D4 = 1
	sbi	PORTD,LCD_D4
.endm

.macro	Port_LCD_D5_0			;LCD_D5 = 0
	cbi	PORTD,LCD_D5
.endm

.macro	Port_LCD_D5_1			;LCD_D5 = 1
	sbi	PORTD,LCD_D5
.endm
На ассемблере, правда, не пишу уже 10 лет.
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

:facepalm: Леонид Иванович, я после каждого вашего поста себя таким тупым чувствую... :oops:
Спасибо, конечно за помощь, даже пробую разобраться. ))) Однако надо вопрос с повестки дня снять. Все равно по своему напишу все...
Станислав
Друг Кота
Аватара пользователя
Сообщения: 6349
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Вот от холода и нечего делать :) накропал универсальный макрос. Запуливает содержимое
бита С в нужный разряд нужного порта.

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

	.MACRO	C_in_PORT
	brcs	_10
	clt
	rjmp	_15
_10:	set
  ;  Перекинули  бит  С  в  бит  Т,  специально для этих  целей придуманный
_15:	in	temp,@0
	andi	r16,~(1<<@1)
  ;  Считали  порт  и  очистили  нужный  разряд
	bld	r16,@1
	out	@0,temp
  ;  заполнили  разряд  тем  чем  надо  и  закинули  обратно  в  порт.
	.ENDMACRO
Пример вызова : C_in_PORT PORTB,3 temp из диапазона R16...R31 определяется ранее директивой .def
Мож пригодится.
Ответить

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