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

Обсуждаем контроллеры компании Atmel.
Ответить
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Сообщение ILYAUL »

Вообще-то это решается двумя короткими командами и akl их написал в своём коде
Реклама
Родился
Сообщения: 10
Зарегистрирован: Вс авг 23, 2015 16:12:23

Сообщение Святовит »

Доброго времени суток, уважаемые форумчане!
Прошу о помощи в таком вопросе - как настроить прерывания??? :shock:

Контроллер - мега 16а
схема - на макетке распаяны через сопротивление светодиоды на порт А, на выводы INT0, INT1, int2 и ресет - кнопки на землю тактовые

дополнительно - светодиод на одной из лап порта С, как индикатор включения - при инициализации вывожу тудой 1, и он горит, или если чего-то не так - переставляю эти строчки в другую часть кода и смотрю, дошел ли процесс до них

задача - продвинуть хелловорд так, чтобы по нажатию клавиши на INT0 значения на светодиодах порта А "замерзали", по нажатию INT1 - выводили значение счетчика нажатий (регистра 21), ну 3 кнопка на INT 2 вырубала камень до лучших времен.

ПРОБЛЕМА: не работают кнопки. Тоесть цикл А выполняется, светики мигают и больше ничего не происходит(((
ПОМОГИТЕ :cry:

(пишу в атмел студио 4 и программатор аврисп мк2 клон)

/код прилагаю/
//си не предлагать//

.include "D:\all\AVR-projects\m16adef.inc"
.cseg
.org 0
jmp RESET
.org INT0addr ; External Interrupt Request 0
;reti
rjmp ext_int0
.org INT1addr ; External Interrupt Request 1
;reti
rjmp ext_int1
.org OC2addr ; Timer/Counter2 Compare Match
reti
.org OVF2addr ; Timer/Counter2 Overflow
reti
.org ICP1addr ; Timer/Counter1 Capture Event
reti
.org OC1Aaddr ; Timer/Counter1 Compare Match A
reti
.org OC1Baddr ; Timer/Counter1 Compare Match B
reti
.org OVF1addr ; Timer/Counter1 Overflow
reti
.org OVF0addr ; Timer/Counter0 Overflow
reti
.org SPIaddr ; Serial Transfer Complete
reti
.org URXCaddr ; USART, Rx Complete
reti
.org UDREaddr ; USART Data Register Empty
reti
.org UTXCaddr ; USART, Tx Complete
reti
.org ADCCaddr ; ADC Conversion Complete
reti
.org ERDYaddr ; EEPROM Ready
reti
.org ACIaddr ; Analog Comparator
reti
.org TWIaddr ; 2-wire Serial Interface
reti
.org INT2addr ; External Interrupt Request 2
reti
rjmp ext_int2
.org OC0addr ; Timer/Counter0 Compare Match
reti
.org SPMRaddr
reti
RESET:
ldi r16, 0x04
out SPL,r16
ldi r16, 0x5f
out SPH,r16
ldi r16,0xff
out DDRC,r16
ldi r16,0x00
out DDRD,r16
ldi r16,0x00
out DDRB,r16
ldi r16,0xff
out PortD,r16
ldi r16,0xff
out DDRa,r16
in r16,MCUCR
sbr r16,(1<<ISC01)|(0<<ISC00)|(0<<ISC10)|(1<<ISC11)
out MCUCR,r16
in r16, gifr
sbr r16, (0<<INTF0)|(0<<INTF1)|(0<<INTF1)
out gifr, r16
ldi r16, 0x33
OUT GICR, r16
in r16,MCUCR
sbr r16,(1<<sm2)|(1<<sm1)|(1<<sm0)
out MCUCR,r16
ldi r16,0xff
out portc,r16
ldi r17, 0x02
ldi r18, 0xff
ldi r21, 0x00
sei

a:
inc r21
inc r18
out porta, r18
ldi r20, 0x00
ldi r21, 0x00
ldi r22, 0x0f
ba:
dec r20
brne ba
dec r21
brne ba
dec r22
brne ba
rjmp a

EXT_INT0:
r: jmp r
reti

EXT_INT1:
out portc, r21
ra: jmp ra
reti

EXT_INT2:
sleep
in r16,MCUCR
sbr r16,(0<<se)
out MCUCR,r16
reti
Реклама
Родился
Сообщения: 10
Зарегистрирован: Вс авг 23, 2015 16:12:23

Сообщение Святовит »

так, один вопрос я решил - первая кнопка на INT0 заработала
просто забыл включить ее

было:

ldi r16, 0x33
OUT GICR, r16

А надо:

"ldi r16, 0xe3
OUT GICR, r16"

но теперь вторая кнопка - INT1, выключает светодиоид на порте С и тоже замораживает состояние светодиодов, но 21 регистр не выводит

и третья по прежнему не работает

Что не так???

И чем культурным можно заменить зацикливание:

EXT_INT0:
r: jmp r
reti

чтобы значение заморозилось тоже, но по нажатию этой или другой кнопки происходил возврат в основной цикл???
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

1. Указатель стека установлен неправильно

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

RESET:
	LDI	R16,HIGH(RAMEND)
	LDI	R17,LOW(RAMEND)
	OUT	SPH,R16
	OUT	SPL,R17

;ldi r16, 0x04 
;out SPL,r16
;ldi r16, 0x5f
;out SPH,r16 
2.Чтобы был переход обслуживание INT2

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

.org INT2addr	; External Interrupt Request 2
;;;;;;;;;;;;;;;;;;reti
rjmp ext_int2
3. Сброс флагов у AVR осуществляется записью 1

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

;	in r16, gifr 
;	sbr r16, (0<<INTF0)|(0<<INTF1)|(0<<INTF1)
;out gifr, r16


	LDI	R22,(1<<INT2|1<<INT1|1<<INT0)
	OUT	GICR,R22
	OUT	GIFR,R22
;ldi r16, 0x33
;OUT	GICR, r16
4.Чтобы не было недоразумений при работе порта С, отключите JTAG

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

 LDI R16,1<<JTD
 OUT MCUCSR,R16
5. Добавил таймер Т1 на выдержку ~1 секунды для счетчика
Спойлер

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

.include "m16adef.inc"
.cseg
.org 0
jmp RESET
.org INT0addr ; External Interrupt Request 0
;reti
rjmp ext_int0
.org INT1addr ; External Interrupt Request 1
;reti
rjmp ext_int1
.org OC2addr ; Timer/Counter2 Compare Match
reti
.org OVF2addr ; Timer/Counter2 Overflow
reti
.org ICP1addr ; Timer/Counter1 Capture Event
reti
.org OC1Aaddr ; Timer/Counter1 Compare Match A
reti
.org OC1Baddr ; Timer/Counter1 Compare Match B
reti
.org OVF1addr ; Timer/Counter1 Overflow
	RJMP	OVER_T1
;reti
.org OVF0addr ; Timer/Counter0 Overflow
reti
.org SPIaddr ; Serial Transfer Complete
reti
.org URXCaddr ; USART, Rx Complete
reti
.org UDREaddr ; USART Data Register Empty
reti
.org UTXCaddr ; USART, Tx Complete
reti
.org ADCCaddr ; ADC Conversion Complete
reti
.org ERDYaddr ; EEPROM Ready
reti
.org ACIaddr ; Analog Comparator
reti
.org TWIaddr ; 2-wire Serial Interface
reti
.org INT2addr ; External Interrupt Request 2
;reti
rjmp ext_int2
.org OC0addr ; Timer/Counter0 Compare Match
reti
.org SPMRaddr
reti

OVER_T1:
	SBIW	XL,1
	BRNE	OVER_T1_OUT
	INC	R18	
	OUT	PORTA,R18
	LDI	XH,HIGH(1*Fo/65536)
	LDI	XL,LOW(1*Fo/65536)
OVER_T1_OUT:
	RETI
;*******************************
RESET:
	ldi r16, 0x04
	out SPH,r16
	ldi r16, 0x5f
	out SPL,r16

	LDI R16,1<<JTD
	OUT MCUCSR,R16	; отключить JTAG

	SBI	ACSR,ACD	; отключить аналоговый компаратор

	ldi r18, 0
	ldi r21, 0x00

ldi r16,0xff
out DDRC,r16
ldi r16,0x00
out DDRD,r16
ldi r16,0x00
out DDRB,r16
ldi r16,0xff
out PortD,r16
ldi r16,0xff
out DDRa,r16
	OUT	PORTA,R18
;in r16,MCUCR
	LDI r16,(1<<SE)|(1<<ISC01)|(0<<ISC00)|(0<<ISC10)|(1<<ISC11)
	out MCUCR,r16
;in r16, gifr
;sbr r16, (0<<INTF0)|(0<<INTF1)|(0<<INTF1)
;out gifr, r16
	LDI r16, 1<<INT2|1<<INT1|1<<INT0
	OUT GICR,r16
	OUT	GIFR,R16
;*******************************
.equ	Fo=1000000
	LDI	XH,BYTE4(1*Fo)
	LDI	XL,BYTE3(1*Fo)


	LDI	R16,1<<TOIE1
	OUT	TIMSK,R16
	OUT	TIFR,R16

	LDI	R16,1
	OUT	TCCR1B,R16
;*******************************
;in r16,MCUCR
;sbr r16,(1<<sm2)|(1<<sm1)|(1<<sm0)
;out MCUCR,r16
;ldi r16,0xff
;out portc,r16
;ldi r17, 0x02
;ldi r18, 0xff
;ldi r21, 0x00
	sei
WAIT:
	SLEEP
	NOP
	RJMP	WAIT
;a:
;inc r21
;inc r18
;out porta, r18
;ldi r20, 0x00
;ldi r21, 0x00
;ldi r22, 0x0f
;ba:
;dec r20
;brne ba
;dec r21
;brne ba
;dec r22
;brne ba
;rjmp a

EXT_INT0:
	LDI	R17,1
	IN	R16,TCCR1B
	EOR	R16,R17
	OUT	TCCR1B,R16	; переключатель остановки/запуска таймера Т1

	LDI	XH,HIGH(1*Fo/65536)
	LDI	XL,LOW(1*Fo/65536)

;r: jmp r
	reti

EXT_INT1:
	INC	R21
	out portc, r21
	LDI	R16,1
	OUT	TCCR1B,R16
;ra: jmp ra
	reti

EXT_INT2:
;sleep
	LDI	R16,1<<SE
	OUT	MCUCR,R16	; только низкий уровень на INT0,INT1
;	in r16,MCUCR
;	CBR r16,(0<<se)
;	out MCUCR,r16
	reti
.EXIT
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 10
Зарегистрирован: Вс авг 23, 2015 16:12:23

Сообщение Святовит »

Спасибо за подсказки, я все учёл, но не все понял.
Я переписал этот код и теперь дела поправились, но не полностью - поэтому все по пунктам:
1.
А в чем разница - ведь значение адреса памяти статическое значение, и его надо просто вывести?
Я просто посмотрел адрес и так и написал, конечно, это не так культурно, но ведь программа вроде и так и так работает одинаково???
2.
блин, забыл)))
3.
ладно буду теперь внимательнее читать даташит...
4.
хорошо, получается сигналы на портах могут вызвать сбои в работе из-за доп. интерфейсов включенных? а если в будущем нужно будет сразу несколько функций на одно ноге использовать???

5.......
я так боялся таймера... и теперь он работает!!! :))
_____________
а шо цэ такэ??
счетчик? а зачем он??
.equ   Fo=1000000
LDI XH,BYTE4(1*Fo)
LDI   XL,BYTE3(1*Fo
____________
LDI   XH,HIGH(1*Fo/65536)
LDI   XL,LOW(1*Fo/65536)

и я так и не понял как работает SLEEP

и кнопка на INT2 ничего не делает, а надо чтоб контроллер "впадал в спячку", и после нажатия чего-то другого опять оживал, и продолжал работать оттуда где закончил

на кнопках вполне ощутим дребезг, как его уничтожить? :?

и вот еще - а чего обработчик прерывания по переполнению таймера у вас находится перед инициализацией???

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

Сообщение akl »

1. Указатель стека устанавливается в допустимой области RAM контроллера. Вы же установили SP=0x5F04 вместо SP=0x045F
5. Да, это грубый таймер 1 секунды привязанный к тактовой контроллера. Грубый, потому что не учитывает состояние TCNTx. Допустим, время дребезга контакта кнопок ~10мс. Заносим в OCR1B значение (TCNT1+10*Fo/1000) Включаем прерывание OC1B, чистим флаг OCF1B. Таймер отсчитывает заданное время, вызывается прерывание OC1B, в котором чистится флаг INTx. Примерно тоже самое делается при отпускании кнопки, которое так же может вызывать дребезг.
Работу команды SLEEP можно увидеть, подав питание на контроллер через миллиамперметр.
Реклама
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

Вопрос.
Есть у меня датчик температуры DS18B20, он выдает температуру как есть и отрицательную температуру в дополнительном коде, т.е. в старшем бите байта появляется единица.
Итого у меня есть некая переменная temp1, в которую отправляется температура с датчика в вышеуказанном виде, т.е. старший бит - знак температуры, а остальные 7 бит - сама температура в прямом либо дополнительном коде (от знака зависит).

Есть у меня переменная другая - ZUUM, в ней содержится число для сравнения из диапазона +125 до -55.

А вот код, который не пашет, т.к. я делаю что-то не так.

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

	;---------------------------------------- Обработка выхода --------------
						cp  ZUUM, temp1
						brlt ENN
							 cbi KEYPORT,KEYPIN
							 rjmp EN
						ENN: sbi KEYPORT,KEYPIN	
		;------------------------------------------------------------------------	
Как правильно сделать сравнение переменных, чтобы при понижении температуры как в положительной так и в отрицательной срабатывала нагрузка?
У меня в положительной срабатывает, когда падает ниже, например 23 градусов. Но если будет установлен придел до -2, то фигню всякую гонит...
Станислав
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

У DS температура содержится вроде в 2 байтах. Вы правильно в 1 байт конвертируете?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

Да, правильно. ))) Температуру показывает без проблем на индикаторе и даже сравнивает с заданной, но в приделах положительных отлично, а вот с отрицательными беда... . Я конвертирую до целых, просто откинув все десятые и т.п.
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

СКАЗОЧНИК писал(а):он выдает температуру как есть и отрицательную температуру в дополнительном коде, т.е. в старшем бите байта появляется единица.
Вообще-то, ЕМНИП, там не только в старшем байте единица (вот в датчике DHT22 - там да, только единица), а вообще там нормальный дополнительный код, т.е. все старшие разряды в единице.

Всё, что с полученным оттуда 16-битным числом нужно сделать для получения "чистой" температуры в цельсиях - это всего лишь сдвинуть его влево 4 раза (это для DS18B20, а для DS1820 - один раз). Я в ассемблере не силён, но вроде это ASR для старшего байта и LSR + заёмом из C для младшего. А потом уже этот младший байт можно и сравнивать с порогом в ZUUM
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

Вот так я вытаскиваю температуру из него:

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


.......

                 rcall READBYTE			; Читаем первый байт (он будет в ДАТЕ)

				mov XL, DATA		; Закидывааем значение первого байта в младший регистр Х

		rcall READBYTE			; Читаем второй байт (он будет в ДАТЕ)

				mov XH, DATA		; Закидывааем значение второго байта в старший регистр Х

; ---------- ПРЕОБРАЗУЕМ И ВЫВОДИМ НА ИНДИКАТОР -----------

			swap XH					; Переворачиваем полубайты местами
			andi XH, 0xF0			; Накладываем маску, остаются только старшие 4 бита
			swap XL					; Переворачиваем младшие полубайты местами
			andi XL, 0x0F			; Накладываем маску, остаются только младшие 4 бита
			
			add XH, XL				; Складываем, в итоге получается готовая температура в XH
		
	rcall CONVERTBYTE 				; Забиваем значения для единиц, десятков и сотен	
Все верно, отрезаем все лишнее и остается один байт температуры. Все просто.

Изображение

З.Ы. Причем в ZUUM он тоже закидывает отрицательные в таком же формате (в дополнительном коде), т.к. вывод на индикатор у них один и тот же, и отображает все корректно.
Станислав
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

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

Сообщение akl »

СКАЗОЧНИК
Поменяйте местами операнды

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

	cp  temp1,ZUUM
;	cp  ZUUM, temp1
	brlt ENN
Из описания команды BRLT
cp r16,r1 ; Compare r16 to r1
brlt less ; Branch if r16 < r1 (signed)
...
less: nop ; Branch destination (do nothing)
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

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

Ура!!!! Спасибо всем.
akl писал(а):Поменяйте местами операнды
Все правильно вы сказали, так и было раньше, пока не начал эксперименты...
Поменял местами, выдрал и перетащил в более логичное место программы. Все пашет! :beer: :music:
Я в восторге!
Дай Вам всем, кто откликнулся вселенная здоровья и денег побольше. :)
Станислав
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Сообщение ILYAUL »

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

         swap XH               ; Переворачиваем полубайты местами
         andi XH, 0xF0         ; Накладываем маску, остаются только старшие 4 бита
         swap XL               ; Переворачиваем младшие полубайты местами
         andi XL, 0x0F         ; Накладываем маску, остаются только младшие 4 бита
         
         add XH, XL            ; Складываем, в итоге получается готовая температура в XH

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

   andi	rab,0xF0			    // В rab младшее значение
		or		temp1,rab			    // Складываем со старшим
		swap	temp1				    // Меняем местами
К тому же

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

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

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

Почти понял, но не понял...
Вы предлагаете альтернативный вариант, как выделить один байт...
Я почему-то всегда думал, что add не складывает реально, а просто объединяет две половинки... :dont_know: :facepalm: :)
Станислав
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Сообщение ILYAUL »

Ну да , вспомните как записываются байты получаемые с DS или просто посмотрите. Т.ч трех команд достаточно. Чтобы выделить температуру.
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

Помогите начинающему! Скачал ASM Editor как советуют в книжке Ревича, накатил туда компилятор с AVR Studio 4. Но не как не могу получить .hex файл! Он за место них .obj выдаёт. Помогите! Что делать? В книжке об этом ничего не написано. На AVR Studio программировать не хочу, слишком много лишнего.

П.С. Компилятор пишет No errors, просто создаёт .obj заместо .hex
Это не хвост, это антенна
Сообщения: 1495
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Если вы сейчас собираетесь писать на асме, лучше AVR-Studio 4.19 ничего нет. Я с AVR уже почти 10 лет работаю, так что поверьте мне. Есть еще одна альтернатива. IAR. Но в IAR на асме я программы не писал, только на си.
Контактная информация:
Нашел транзистор. Понюхал.
Сообщения: 167
Зарегистрирован: Чт янв 01, 2015 16:34:55

Сообщение ПТУ-шник »

Мне очень сильно избыточен функционал AVR Studio. Пробывал писать в ASM Editor и сразу понравился его минимализм, всё просто и понятно - создал файлик, написал, скомпилировал и всё. А в AVR Studio куча непонятных окошек, каких то настроек, симуляторов. Создать проект и скомпилировать код тот ещё квест. Мне не нужна вся эта мишура, я просто хочу помигать светодиодом :)

Может существует такие же IDE как ASM Editor для AVR? Чтоб можно было просто код писать, как в блокноте но с нумерацией строк и без всяких лишних окошечек чья функция для меня загадка. А лучше с ASM Editor помогите разобратся...
Ответить

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