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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

Согласен. Но всё же писать надо правильно.
Docendo discimus
Реклама
Аватара пользователя
Seriyvolk
Друг Кота
Сообщения: 4961
Зарегистрирован: Сб май 05, 2012 20:19:55
Откуда: Минск

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

Сообщение Seriyvolk »

Приветствую обитатеелй сей ветки! Не так давно начал осваивать АСМ, и решился таки взяться за (довольно серьёзный для меня на данный момент) проект.
Суть его такова : Нужно сделать что-то типа аналога пульта ДУ, но только с проводным управлением. На руле есть два независимых ряда кнопок, каждая из кнопок в котором коротит на общий свой резистор. Оба ряда одинаковы, сопротивления нажатых клавиш я замерял 0-58-126-286 Ом.
Схемка предполагаемого чуда:
Изображение
Собсно насколько я успел понять - в тиньке13 2 канала АЦП, поэтому хочу именно её и приспособить, по каналу на свой ряд кнопок.
По нажатию какой-либо кнопки нужно дрыгать ногой, согласно протоколу ИК управления NEC, только без модуляции несущей. Конкретные коды описаны здесь.
Так вот, если я на данный момент отдалённо представляю, как это можно сделать по кратковременному нажатию, то с длинным нажатием есть проблема... Ибо опрос АЦП порушит все тайминги протокола, хоть они и не такие и жёсткие. Т.е. как-то нужно отслеживать нажат кнопарь или нет, и если нажат продолжительно - одновременно слать битики/байтики повтора на вход майфуна. Да и с формированием самой посылки есть очень большие вопросы... Если в тупую дрыгать ногой с вычислением временнЫх интервалов, то тупо просто может не хватить памяти в тиньке на все 8 команд.
Может натолкнёте на мысль, как это всё можно попроще сообразить?
Примерный вариант кода (там есть некоторые макросы, но думаю, что сенсеям будет понятно что к чему):
Спойлер

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

			.include "tn13def.inc"	; Используем Tiny13
			.include "macro.asm"	; Все макросы тут

	
	
	.DSEG							; Оперативка 


//////////////////////////////////////////////////////////////////////////////
////////////                      ПЕРЕМЕННЫЕ                     /////////////
//////////////////////////////////////////////////////////////////////////////
			.def	aBUF	=	R18 ; Буфер АЦП
			.def	aBUF1	=	R19 ; Буфер АЦП вход 1
			.def	aBUF2	=	R20 ; Буфер АЦП вход 2

			.def	FLAG	=	R21 ; независимый регистр флагов
			


	.CSEG

			.include "vectors.asm"	
			.ORG 	INT_VECTORS_SIZE

//////////////////////////////////////////////////////////////////////////////
////////////                     ПРЕРЫВАНИЯ                      /////////////
//////////////////////////////////////////////////////////////////////////////

ADC_OK:						; Прерывание АЦП

		PUSH	R16			; Сохранили R16
		IN		R16,SREG	; Достали SREG в R16
		PUSH	R16			; Запихнули его в стек

		IN		aBUF,ADCH	; Упихали значение АЦП в буфер
		CBR 	FLAG,1<<0	; И поставим флаг что все готово

		POP	R16				; Возвращаем регистры на родину
		OUT	SREG,R16
		POP	R16

		RETI				; Спокойно выходим из прерывания

//----------------------------------------------------------------------------


//////////////////////////////////////////////////////////////////////////////
////////////                   ИНИЦИАЛИЗАЦИЯ                     /////////////
//////////////////////////////////////////////////////////////////////////////			

Reset:		LDI R16, LOW(RAMEND)			; Объявляем стек
 			OUT SPL,R16
			
			.include "initial.asm"			; Инициализация всего остального тут

			CLR	FLAG	; Это мы на всякий случай почистим

			DDLOOP	20,255,255	; Обязательная предстартовая задержка
								; на "расчихление" всей схемы

			SEI								; Вкл. прерывания


//////////////////////////////////////////////////////////////////////////////
////////////                   ТЕЛО ПРОГРАММЫ                    /////////////
//////////////////////////////////////////////////////////////////////////////

Start:
			RCALL	ADCC1		// Опрашиваем первый канал АЦП
			CPI		aBUF1,128	// Нажатие было?
			BRLO	CODE_GEN	// Если было - бежим генерить код


			RCALL	ADCC2		// Опрашиваем второй канал АЦП
			CPI		aBUF1,128	// Нажатие было?
			BRLO	CODE_GEN	// Если было - бежим генерить код
			
			SBR		FLAG,1<<3	//А раз уж мы сюда попали, то поставим флаг отпущенной кнопки
			RJMP Start


CODE_GEN:
			SBRC	FLAG,3		// Проверяем, отпускалась ли кнопка за время нашего отсутствия))
			BREQ	REPEAT		// Если не отпускалась - идём генерить код повтора
								// , а вот если отпускалась, то генерим код стартовой последовательности
	START_ADR_GEN:				// и байта адреса

			SBI PORTB,2
			WAIT 16
			CBI PORTB,2
			WAIT 8         // и так далее многабукв/бит...

			SBRC	FLAG,2		// Потом проверяем, на каком канале АЦП была сработка
			BREQ	KEY5		// Если на втором, генерим код из второй половины таблицы
	KEY1:
			CPI		aBUF1,20
			BRSH	KEY2
			//код первой клавиши
			RJMP END
	KEY2:
			CPI		aBUF1,50
			BRSH	KEY3
			//код второй
			RJMP END
	KEY3:
			CPI		aBUF1,95
			BRSH	KEY4
			RJMP END
	KEY4:
			//код четвёртой и далее по накатанной
			RJMP END
	KEY5:
			CPI		aBUF1,20
			BRSH	KEY6
			RJMP END
	KEY6:
			CPI		aBUF1,50
			BRSH	KEY7
			RJMP END
	KEY7:
			CPI		aBUF1,95
			BRSH	KEY8
			RJMP END
	KEY8:
			RJMP END
	REPEAT:	                                 // Код повтора
			SBI PORTB,2
			WAIT 16
			CBI PORTB,2
			WAIT 4
			SBI PORTB,2
			WAIT 1
			CBI PORTB,2
	END:
	SBR		FLAG,0<<3	// А раз попали сюда, то флаг отпущенной кнопки сбросим
RET




ADCC1:	; подпрограмма опроса нескольких каналов АЦП

		SBR 	FLAG,(1<<0)|(0<<1)
		
		OUTI	ADMUX,0b00100010	; Настроим АЦП на канал ADC2 (первый вход)
		OUTI	ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(7<<ADPS0) // ADEN - включаем АЦП
																// ADIE - разрешаем прерывания по окончании конверсии АЦП
																// ADSC - запуск преобразования
																// ADSC will read as one as long as a conversion is in progress. When the conversion is complete,
																// it returns to zero. (может понадобиться при расчёте временных интервалов)
																// ADPS0 - выбор предделителя частоты АЦП
		
wt_pul:	SBRC	FLAG,0
		RJMP	wt_pul

		MOV	aBUF1,aBUF
RET

ADCC2:	; подпрограмма опроса нескольких каналов АЦП

		SBR 	FLAG,(1<<0)|(1<<1)

		OUTI	ADMUX,0b00100011	; Настроим АЦП на канал ADC3 (второй вход)
		OUTI	ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(7<<ADPS0)
		
wt_pul1:SBRC	FLAG,0
		RJMP	wt_pul1

		MOV	aBUF1,aBUF
RET
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Реклама
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

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

Сообщение zero648 »

Может натолкнёте на мысль, как это всё можно попроще сообразить?
Делается сетка с помощью таймера в режиме СТС с определенным интервалом, в прерывании таймера опрашивается АЦП сразу два канала по очереди, можно и чередовать через один, и сохраняется значение в переменных. В основном цикле считается количество подряд считанных одинаковых значений с допуском определенной погрешности, если нужной выдержки достигли, то выполняем какое-то действие, если не достигли, а значение АЦП изменилось, тогда обнуляем счетчик.
Аватара пользователя
alex38779
Потрогал лапой паяльник
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32
Контактная информация:

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

Сообщение alex38779 »

помогите пожалуйста) начал учить асм, уже 3 день как

написал прогу включения светодиода по нажатию, но что то не так. на порту С светодиод, на В кнопка. что то типа нажал кнопку он горит, отпустил не горит

.include "m8def.inc"

.DSEG
.CSEG
ldi r16,(1<<PC0)
ldi r17,(1<<DDC0)
ldi r18,(1<<PB0)
ldi r19,(0<<DDB0)
out PORTC,r16
out DDRC,r17
out PORTB,r18
out DDRB,r19
start:
nop
nop
in r16,PINB0
cpi r16,1
brne M
nop
nop
rjmp start
M: ldi r17,(0<<PC0)
out PORTC,r17
nop
nop
rjmp start
.ESEG
Последний раз редактировалось alex38779 Вт дек 31, 2013 09:24:55, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

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

in r16,PINB0
 cpi r16,1
Вы проверяете весь порт. А вам нужен только один бит.
Docendo discimus
Реклама
Аватара пользователя
alex38779
Потрогал лапой паяльник
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32
Контактная информация:

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

Сообщение alex38779 »

pyzhman писал(а): Вы проверяете весь порт. А вам нужен только один бит.

так можно сделать? прочитал на форуме про команду sbrc

in r16,PINB0
sbrc r16,0
brne M
Реклама
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

sbrc - пропустить (следующую команду), если бит очищен. Есть ещё sbrs - пропустить, если бит установлен.
Вот и рулите любую логику.

А есть ещё всякие BRхх, переходы по любым флагам SREG.
Аватара пользователя
alex38779
Потрогал лапой паяльник
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32
Контактная информация:

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

Сообщение alex38779 »

сделалллл))))
вот код мож кому пригодиться, ща попробую со стеком сделать

.include "tn2313def.inc"

.cseg

ldi r16, 0
out DDRD,r16
ldi r16,0xff
out PORTB,r16
out DDRB,r16

main: in r16,PIND
out PORTB,r16
rjmp main
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

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

Сообщение SmarTrunk »

Это не спортивно, просто копировать целиком весь байт (весь регистр). Другие же биты портов могут быть использованы для других целей! По-хорошему надо проверять один бит, к которому кнопка подключена, и переключать тоже один бит, со светодиодом. Еще, в реальной жизни обычно делают подтяжку кнопки к плюсу внешним резистором, т.к. внутренняя подтяжка слишком высокоомная. Но в учебных целях сойдет.
Аватара пользователя
coredumped
Опытный кот
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

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

Сообщение coredumped »

Друзья! Всех с Новым Годом! Желаю всем удачи в 2014 году!
- чтоб дома все было хорошо!
- много разных денег!
- крепкого здоровья!
- чтоб все Ваши устройства работали и не глючили :)))
:beer:
Все будет только лучше, в крайнем случае - хуже.
Аватара пользователя
alex38779
Потрогал лапой паяльник
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32
Контактная информация:

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

Сообщение alex38779 »

SmarTrunk писал(а):Это не спортивно, просто копировать целиком весь байт (весь регистр).
согласен, не спортивно, буду дальше пробовать. я пока учу еще основы асма.
Аватара пользователя
Seriyvolk
Друг Кота
Сообщения: 4961
Зарегистрирован: Сб май 05, 2012 20:19:55
Откуда: Минск

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

Сообщение Seriyvolk »

Есть у меня 4 числа в регистрах, по 8 бит каждое. Мне нужно их как-то поставить в ряд и сдвигать вправо, т.е. сдвинуть это большое число вправо 32 раза, чтоб каждый раз можно было прочитать последний его бит, ибо он дальше используется.
Чувствую, что это можно как-то красиво сделать, но как - не соображу за неимением опыта. Помогите кто советом или примером. :)
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

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

.include "tn13def.inc"


.org 0x0000


	ldi	r16,32
loop:
;в этих регистрах данные
	ror	r17
	ror	r18
	ror	r19
	ror	r20
	brcc	m1
;
;сюда попадаем, если младший бит был "1"
;
	rjmp	m2

m1:
;
;сюда попадаем, если младший бит был "0"
;
m2:
	dec	r16
	brne	loop
;
;далее делаем то, что надо
;
Docendo discimus
Аватара пользователя
Seriyvolk
Друг Кота
Сообщения: 4961
Зарегистрирован: Сб май 05, 2012 20:19:55
Откуда: Минск

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

Сообщение Seriyvolk »

Да, всё работает! Все 32 байтика шлются по ИК как в аптеке!
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

Поздравляю! :)
Docendo discimus
Аватара пользователя
BlYur
Открыл глаза
Сообщения: 52
Зарегистрирован: Пн май 27, 2013 17:02:32

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

Сообщение BlYur »

Здравствуйте.
В моей программе для ATMega8 таблица векторов прерываний выглядит следующим образом:

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

.cseg 				
         .ORG $000 
         RJMP   Init	; (RESET) Внешний сброс, сброс при подаче питания, сброс при недопустимом снижении питания, сброс сторожевым таймером
         .ORG $001
         RJMP INT0Intr  ; (INT0) Запрос на внешнее прерывание 0
         .ORG $002
         RETI           ; (INT1) Запрос на внешнее прерывание 1
         .ORG $003
         RETI		    ; (TIMER2 COMP) Срабатывание компаратора таймера-счетчика 2
         .ORG $004
         RJMP Tim2OVF   ; (TIMER2 OVF) Переполнение таймера-счетчика 2
         .ORG $005
         RETI		    ; (TIMER1 CAPT) Захват фронта таймером-счетчиком 1
         .ORG $006
         RETI           ; (TIMER1 COMPA) Срабатывание компаратора А таймера-счетчика 1
         .ORG $007
         RETI           ; (TIMER1 COMPB) Срабатывание компаратора В таймера-счетчика 1
         .ORG $008
         RETI           ; (TIMER1 OVF) Переполнение таймера-счетчика 1
         .ORG $009
         RETI           ; (TIMER0 OVF) Переполнение таймера-счетчика 0
         .ORG $00A
         RETI           ; (SPI,STC) Завершение последовательной передачи интерфейсом SPI
         .ORG $00B
         RETI           ; (USART,RXC) Завершение приема УСАПП
         .ORG $00C
         RETI           ; (USART,UDRE) UРегистр данных УСАПП свободен
         .ORG $00D
         RETI           ; (USART,TXC) Завершение передачи УСАПП
         .ORG $00E
         RETI		    ; (ADC) Завершение преобразования АЦП
         .ORG $00F
         RETI           ; (EE_RDY) Готовность EEPROM
         .ORG $010
         RETI           ; (ANA_COMP) Аналоговый компаратор
         .ORG $011
         RETI           ; (TWI) Двухпроводный Последовательный интерфейс
         .ORG $012
         RETI           ; (SPM_RDY) Готовность записи Памяти программ
          
	 .ORG   INT_VECTORS_SIZE      	; Конец таблицы прерываний
Обязательно ли в программе указывать эти ОРГи с адресами?
Ведь адреса следуют друг за другом в порядке возрастания без пропусков...
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

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

Сообщение SmarTrunk »

Конечно, необязательно, для АТмега8. Просто тут сделано все максимально "строго".
Без "оргов", если пропущена одна строчка, то будут проблемы - таблица сместится.

Вот для АТмега32, например, там операторы JMP и RETI имеют разную длину (32 и 16 бит), так что просто убрать "орги" не выйдет.

RETI тоже не обязательны, и написаны "на всякий случай" (которого не произойдет, в грамотно написанной программе).

.cseg тоже необязательно писать, т.к. по-умолчанию это так и есть. Нужно, только если перед этим было .dseg или типа того.

Вообще все это необязательно, если ни одного прерывания не используется. Просто начинаем писать программу с первой строчки.
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

Не обязательно. Но вдруг вы очепатку сделаете и напишете "JMP Tim2OVF" и у вас есть обработчик "TIMER1 CAPT". С org-ами компилятор ругнётся, а без вы будете париться искать ошибку...
Уже обсуждалось и не раз. Вот, например http://radiokot.ru/forum/viewtopic.php?f=57&t=72364
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
Seriyvolk
Друг Кота
Сообщения: 4961
Зарегистрирован: Сб май 05, 2012 20:19:55
Откуда: Минск

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

Сообщение Seriyvolk »

Парни, привет всем опять! Нуждаюсь в толчке в нужном направлении. Опять-же протокол NEC, на этот раз нужно организовать его приём по ИК. Описание протокола я скидывал чуть выше, повторяться не буду.
Может кто-то подскажет, как это сделать красиво, и лучше бы на живом примере. :)
Сам дошёл до того, что по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг), но прерывание выходит очень громоздким, некрасиво как-то... Надеюсь на помощь. :)
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

Главный критерий - работоспособность. А что до
Seriyvolk писал(а):некрасиво как-то
на вкус и цвет товарищей, как известно, нет.
Docendo discimus
Ответить

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