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

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 444
Зарегистрирован: Вс ноя 28, 2010 15:18:52
Откуда: Минск

Сообщение ANALOG »

Вообще, задание некорректно сформулировано:
Во-первых, не указано какой именно AVR используется - от этого зависит возможно ли использовать команду mul для умножения или нужно писать свою функцию для этого.
Во-вторых, не указана частота, на которой будет работать МК, а без этого в программе невозможно задать временные интервалы (можно задать интервалы в тактах, а уж сколько это будет миллисекунд - зависит от частоты)
Реклама
Родился
Сообщения: 2
Зарегистрирован: Пн дек 02, 2013 20:30:52

Сообщение tohafox »

Благодарю всех за помощь, особую благодарность выражаю pyzhman.
Реклама
Родился
Сообщения: 1
Зарегистрирован: Пт дек 13, 2013 00:19:21

Сообщение valera_sr »

Доброго времени суток. Я пытаюсь разобраться с формированием временных интервалов. Я пытаюсь записать значение TCNT0 в R16 регистр, для последующего сравнения, но этого не происходит, счетчик работает до момента записи в temp и обнуляется. В регистре R16 ноль.
Собственно, не могу разобраться, где я накосячил. Контроллер attiny2313 AtmelStudio 6.1.2730

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

  ldi temp, 0b0000001;
 out TCCR0,temp; задаем предделитель
 
 Start:

nop
nop
nop
nop
nop
nop


 out TCNT0, temp; значение таймера записываем в R16
 nop

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

Сообщение akl »

valera_sr писал(а):Я пытаюсь разобраться с формированием временных интервалов. Я пытаюсь записать значение TCNT0 в R16 регистр
Для этого нужно

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

IN R16,TCNT0
Сейчас Вы заносите 1 в TCNT0 в конце каждого цикла.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

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

ldi temp, 0b0000001;
Вообще говоря, в байте восемь бит. Мелкий огрех, но тем не менее.
Раз уж вы запустили таймер, то может проще все сравнения делать в прерываниях от него? И зачем эти сравнения, если можно задать время прерывания?
Docendo discimus
Контактная информация:
Реклама
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Замечу, что

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

LDI R16,0b1
или

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

LDI R16,0b00000000000001
студией (3.21 и 4.19) понимаются одинаково.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

как и

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

LDI R16, 1
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

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

Сообщение 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
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

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

Сообщение 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 раз.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

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

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

Сообщение alex38779 »

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

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

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

Сообщение ploop »

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

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

Сообщение 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
Контактная информация:
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

Сообщение SmarTrunk »

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

Сообщение coredumped »

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

Сообщение alex38779 »

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

Сообщение Seriyvolk »

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

Сообщение 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
Контактная информация:
Ответить

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