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

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

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

Елки, прочитал уже 60 страниц книги Белова (см. выше), очень нравится. Не сильно подробно, но вполне доступно, логично и последовательно подается информация.
Спасибо, что рекомендовали. :beer:
Купил бы в бумажном варианте, но в местном ПродалитЪе нету, а заказывать мне лень... :)))
Станислав
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

ни как не могу улететь в прерывание. мяу :(

мега8, аврстудия, прерывание от таймера Т0
флаг I стоит, TOIE0 тоже.

вот вектор и обработчик прерывания

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

	; птчк взлитай------------------------------
	.org $00
	; старт основной программы------------------
	rjmp Start
	; вектора прерываний------------------------	
	.org $01 ; External Interrupt Request 0
		reti
	.org $02 ; External Interrupt Request 1
		reti
	.org $03 ; Timer/Counter2 Compare Match
		reti
	.org $04 ; Timer/Counter2 Overflow
		reti
	.org $05 ; Timer/Counter1 Capture Event
		reti
	.org $06 ; Timer/Counter1 Compare Match A
		reti 
	.org $07 ; Timer/Counter1 Compare Match B
		reti
	.org $08 ; Timer/Counter1 Overflow
		reti
	.org $09 ; Timer/Counter0 Overflow
		rjmp ovf_tim0
	.org $0a ; Serial Transfer Complete
		reti
	.org $0b ; USART, Rx Complete
		reti
	.org $0c ; USART Data Register Empty
		reti
	.org $0d ; USART, Tx Complete
		reti
	.org $0e ; ADC Conversion Complete
		reti
	.org $0f ; EEPROM Ready
		reti
	.org $10 ; Analog Comparator
		reti
	.org $11 ; 2-wire Serial Interface
		reti
	.org $12 ; Store Program Memory Ready
		reti
	.org INT_VECTORS_SIZE ; конец таблицы прерываний
	;обработка прерываний------------------------------
ovf_tim0:
	ldi r17, $ff
	reti
настройка таймера:

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

   .equ tim0_tccr0 = (1<<CS01)
	.equ tim0_tcnt  = $60
	.equ tim0_timsk = (1<<TOIE0) ; 
и перед главным циклом программы:

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

   ldi r16, tim0_tccr0 
	out TCCR0, r16
	ldi r16, tim0_tcnt
	out TCNT0, r16
	ldi r16, tim0_timsk	
	out TIMSK, r16
	sei	
шо может быть не так?
Контактная информация:
Реклама
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Да, вроде, всё так. Ниже показывается, что каждые 1281/1287 тактов идёт изменение выводов порта B
Спойлер

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

	.INCLUDE "m8def.inc"

   .equ tim0_tccr0 = (1<<CS01)
   .equ tim0_tcnt  = $60
   .equ tim0_timsk = (1<<TOIE0) ;    ; птчк взлитай------------------------------

   .org $00
   ; старт основной программы------------------
   rjmp Start
   ; вектора прерываний------------------------   
   .org $01 ; External Interrupt Request 0
      reti
   .org $02 ; External Interrupt Request 1
      reti
   .org $03 ; Timer/Counter2 Compare Match
      reti
   .org $04 ; Timer/Counter2 Overflow
      reti
   .org $05 ; Timer/Counter1 Capture Event
      reti
   .org $06 ; Timer/Counter1 Compare Match A
      reti
   .org $07 ; Timer/Counter1 Compare Match B
      reti
   .org $08 ; Timer/Counter1 Overflow
      reti
   .org $09 ; Timer/Counter0 Overflow
      rjmp ovf_tim0
   .org $0a ; Serial Transfer Complete
      reti
   .org $0b ; USART, Rx Complete
      reti
   .org $0c ; USART Data Register Empty
      reti
   .org $0d ; USART, Tx Complete
      reti
   .org $0e ; ADC Conversion Complete
      reti
   .org $0f ; EEPROM Ready
      reti
   .org $10 ; Analog Comparator
      reti
   .org $11 ; 2-wire Serial Interface
      reti
   .org $12 ; Store Program Memory Ready
      reti
   .org INT_VECTORS_SIZE ; конец таблицы прерываний
   ;обработка прерываний------------------------------
ovf_tim0:
	OUT	TCNT0,R18
;   ldi r17, $ff
   IN	R16,PORTB
   EOR	R16,R17
   OUT	PORTB,R16
   reti


START:
	LDI	XH,HIGH(RAMEND)
	OUT	SPH,XH
	LDI	XL,LOW(RAMEND)
	OUT	SPL,XL

	LDI	R17,$FF
	OUT	DDRB,R17

   ldi r16, tim0_tccr0
   out TCCR0, r16
   ldi r18, tim0_tcnt
   out TCNT0, r18
;   ldi r16, tim0_tcnt
;   out TCNT0, r16
   ldi r16, tim0_timsk   
   out TIMSK, r16
   sei   

	RJMP	PC
.EXIT
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

Может авр студия погнала? У меня 6 версии, попробую 5 скачать и проверить.

Так и было, в 5 версии все заработало..
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

Помогите с алгоритмом, на си было два цикла, была переменная bool и вокруг нее плясали циклы. true - первый цикл, false - второй. кнопка рулила этой переменной, переключая циклы.
как на асме сделать подобное?

Вот нагородил что то, но думаю не правильно все таки сделал. Может как то использовать регистр, либо флаг T например. Как вообще можно заменить булевый тип в асме?

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

MainLoop:
	; вызываем программы
menu:
	in temp, PIND
	sbrc temp, 0	
	rjmp start_auto
	nop
	nop
	nop
	rjmp menu
start_auto:
	in temp, PIND
	sbrc temp, 0	
	rjmp menu
	nop
	nop
	nop
	nop
	rjmp start_auto
	rjmp MainLoop
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

alex38779 писал(а): in temp, PIND
sbrc temp, 0
Можно использовать 1 команду

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

sbic PIND, 0
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Может так?

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

MainLoop:
   ; вызываем программы
menu:
   SBIS PIND,0   
   rjmp start_auto
   adiw r24, $a		;эта команда работает с регистровыми парами R25:R24, X, Y, Z
;   adiw r16, $a
   nop
   nop
   nop
   rjmp menu
start_auto:
   SBIC PIND,0   
   rjmp menu
   nop
   nop
   nop
   nop
   rjmp start_auto
;   rjmp MainLoop

.EXIT
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 386
Зарегистрирован: Чт окт 31, 2013 10:54:32

Сообщение alex38779 »

Сделал вот так. Работает как надо. Получается кнопка переключает режимы, нажал - один, еще раз нажал другой..

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

MainLoop:
	; вызываем программы
	; обработка кнопки старт-меню
menu:
	sbic PIND, 0	
	rjmp start_auto
	nop
	nop
	nop
	rjmp menu
start_auto:
	sbic PIND, 0	
	rjmp menu
	nop
	nop
	nop
	nop
	rjmp start_auto
	rjmp MainLoop
теперь дальше буду мозги колупать себе.. сделать индикацию для начала на 7 сегментнике.
Контактная информация:
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Переключатель предполагает наличие памяти состояния режима. У Вас получился обработчик nop при нажатой кнопке и ожидание нажатия при отпущенной кнопке.

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

menu:
   sbic PIND, 0   
   rjmp menu
   nop
   nop
   nop
   rjmp menu
;start_auto:
;   sbic PIND, 0   
;   rjmp menu
;   nop
 ;  nop
  ; nop
;   nop
;   rjmp start_auto
;   rjmp MainLoop
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Сообщение ILYAUL »

А давайте просто поговорим о кнопках и их обработке.
Я использую две разновидности тупо АЦП или таймер+внешнее прерывания.
Во втором случае кнопки обычно висят на 595 вместе с устройством отображения ( 7-segment или LCD - не суть)
Таймер с частотой 100гц=10ms выдает по SPI код - сдвиг регистра (ror rol), но тут тонкий момент т.к в прерывании регистр SREG может на входе иметь разное значение бита C , то необходима проверка MSВ или LSB регистра с кодом и корректировка бита С. Конечно не забыть сохранить SREG. INTx - тупой счетчик совпадений от 7-10 , с выходом - флаг, либо с произвольным выходом из прерывания т.б.
на исполняемую функцию обнаруженной кнопки. При этом функции (подпрограммы) можно располагать где угодно , перемещать в процессе написания кода. Компилятор все равно определит их адрес.
Точнее- создаст таблицу их адресов
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Сообщение ILYAUL »

Забыл совсем - в обоих случаях не нужно думать о дребезге.
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

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

Сообщение WiseLord »

А зачем читать PINX? Читайте PORTX
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

PORTX выдаст состояния подтягивающих резисторов, или я что-то не правильно понял?
Часть порта будет настроена на вход, а часть на выход. Нужно не изменить состояние выходов и подтягивающих резисторов (у входов).
Мудрый кот
Аватара пользователя
Сообщения: 1812
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Вариантов не так много, но все они, так или иначе, сводятся к тому чтобы исключить нежелательные последствия. :)
С помощью битовых операций (and/or/xor). Получить только то, что требуется. Модифицировать. Если надо, то добавить к получившемуся то что должно быть на "не нужных" местах. Записать.
Можно ещё цикл или кучу if-ов BRxx-ов совместно с пачкой sbi/cbi по нужным битам.
Если состояние порта может поменяться в прерывании, а модификация происходит в основной программе, то может быть полезным запретить прерывания на время модификации.

И не важно что считывать PIN или PORT - маской выделить только нужное.
Последний раз редактировалось Kavka Вс авг 23, 2015 16:54:18, всего редактировалось 1 раз.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Аватара пользователя
Сообщения: 4966
Зарегистрирован: Сб май 05, 2012 20:19:55
Откуда: Минск

Сообщение Seriyvolk »

Мурик писал(а):Есть на первый взгляд простая задача - вывести данные в часть выводов порта. Но при этом необходимо не изменить состояние и конфигурацию незадействованых выводов.
Почитай, это про тебя. http://easyelectronics.ru/avr-uchebnyj- ... porty.html
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

Kavka писал(а):И не важно что считывать PIN или PORT - маской выделить только нужное.
Как это не важно? :) PIN выдаст то что сейчас реально на порту, а PORT - состояние подтягивающих резисторов. По моему, инженеры Atmel совершили глупость когда совместили в одном регистре вывод в порт и установку подтягивающих резисторов. :shock:
Тут как получается. Если читать из PIN, то скорее всего будет изменено состояние подтягивающих резисторов. Если читать из PORT, то изменится состояние выходов. Попытка совместить, приведет к увеличению размера кода. Уж проще побитово (SBI и CBI) записать данные в нужные выводы порта. Но думал что есть более правильный способ.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Вам советую сначала разобраться с PORTx, DDRx, PINx.

Предположим Вам надо установить на младших трех выходных битах значение 0b101, само собой не меняя другие биты и значение остальных старших бит Вы почему то не знаете.

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

in R16,PORTx
andi R16,0b11111000
ori   R16,0b000000101 
out PORTx,R16
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Мудрый кот
Аватара пользователя
Сообщения: 1812
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Чтение PORT даст вам то что было последний раз в него записано. Как трактовать эти биты (подтяжка или выход пина) зависит от того, что записано в соответствующий биты DDR. Соответственно, чтобы модифицировать только выходные сигналы на порту основываясь только на их текущем состоянии достаточно прочитать PORT. Если вы модифицируете ещё опираясь на входные сигналы того же порта, тогда, да, читать PIN.
А если сигналы надо только установить в известное состояние, и состояние подтяжки известно, то и чтение из PORT не понадобиться. Только код длиннее может получиться. :)

Если это 1-2 бита, то может быть проще через sbi/cbi. А если, например 5-7? :)
Естественно, многое зависит от конкретной задачи.
Z_h_e писал(а):Вам советую сначала разобраться с PORTx, DDRx, PINx.
Скорее с битовыми операциями.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

Kavka писал(а):Как трактовать эти биты (подтяжка или выход пина) зависит от того, что записано в соответствующий биты DDR.
Часть порта используется в другом коде и можно сказать что о состоянии неиспользуемых выводов ничего не известно. Потому что если побитово анализировать DDR и брать биты с PIN или PORT, то код сильно усложнится.
Kavka писал(а):А если, например 5-7
Как раз такой случай. Но видимо проще всего будет побитово изменить состояние выводов о чем писал выше. Думал есть более правильный способ.
Ответить

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