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

Собсно насколько я успел понять - в тиньке13 2 канала АЦП, поэтому хочу именно её и приспособить, по каналу на свой ряд кнопок.
По нажатию какой-либо кнопки нужно дрыгать ногой, согласно протоколу ИК управления NEC, только без модуляции несущей. Конкретные коды описаны здесь.
Так вот, если я на данный момент отдалённо представляю, как это можно сделать по кратковременному нажатию, то с длинным нажатием есть проблема... Ибо опрос АЦП порушит все тайминги протокола, хоть они и не такие и жёсткие. Т.е. как-то нужно отслеживать нажат кнопарь или нет, и если нажат продолжительно - одновременно слать битики/байтики повтора на вход майфуна. Да и с формированием самой посылки есть очень большие вопросы... Если в тупую дрыгать ногой с вычислением временнЫх интервалов, то тупо просто может не хватить памяти в тиньке на все 8 команд.
Может натолкнёте на мысль, как это всё можно попроще сообразить?
Примерный вариант кода (там есть некоторые макросы, но думаю, что сенсеям будет понятно что к чему):
Суть его такова : Нужно сделать что-то типа аналога пульта ДУ, но только с проводным управлением. На руле есть два независимых ряда кнопок, каждая из кнопок в котором коротит на общий свой резистор. Оба ряда одинаковы, сопротивления нажатых клавиш я замерял 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 в вопросах и ответах
Делается сетка с помощью таймера в режиме СТС с определенным интервалом, в прерывании таймера опрашивается АЦП сразу два канала по очереди, можно и чередовать через один, и сохраняется значение в переменных. В основном цикле считается количество подряд считанных одинаковых значений с допуском определенной погрешности, если нужной выдержки достигли, то выполняем какое-то действие, если не достигли, а значение АЦП изменилось, тогда обнуляем счетчик.Может натолкнёте на мысль, как это всё можно попроще сообразить?
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
помогите пожалуйста) начал учить асм, уже 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
написал прогу включения светодиода по нажатию, но что то не так. на порту С светодиод, на В кнопка. что то типа нажал кнопку он горит, отпустил не горит
.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 в вопросах и ответах
Код: Выделить всё
in r16,PINB0
cpi r16,1Docendo discimus
- Реклама
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
pyzhman писал(а): Вы проверяете весь порт. А вам нужен только один бит.
так можно сделать? прочитал на форуме про команду sbrc
in r16,PINB0
sbrc r16,0
brne M
Re: Ассемблер (ASM) для AVR в вопросах и ответах
sbrc - пропустить (следующую команду), если бит очищен. Есть ещё sbrs - пропустить, если бит установлен.
Вот и рулите любую логику.
А есть ещё всякие BRхх, переходы по любым флагам SREG.
Вот и рулите любую логику.
А есть ещё всякие BRхх, переходы по любым флагам SREG.
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
сделалллл))))
вот код мож кому пригодиться, ща попробую со стеком сделать
.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
вот код мож кому пригодиться, ща попробую со стеком сделать
.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
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Это не спортивно, просто копировать целиком весь байт (весь регистр). Другие же биты портов могут быть использованы для других целей! По-хорошему надо проверять один бит, к которому кнопка подключена, и переключать тоже один бит, со светодиодом. Еще, в реальной жизни обычно делают подтяжку кнопки к плюсу внешним резистором, т.к. внутренняя подтяжка слишком высокоомная. Но в учебных целях сойдет.
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Друзья! Всех с Новым Годом! Желаю всем удачи в 2014 году!
- чтоб дома все было хорошо!
- много разных денег!
- крепкого здоровья!
- чтоб все Ваши устройства работали и не глючили

- чтоб дома все было хорошо!
- много разных денег!
- крепкого здоровья!
- чтоб все Ваши устройства работали и не глючили
Все будет только лучше, в крайнем случае - хуже.
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
согласен, не спортивно, буду дальше пробовать. я пока учу еще основы асма.SmarTrunk писал(а):Это не спортивно, просто копировать целиком весь байт (весь регистр).
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Есть у меня 4 числа в регистрах, по 8 бит каждое. Мне нужно их как-то поставить в ряд и сдвигать вправо, т.е. сдвинуть это большое число вправо 32 раза, чтоб каждый раз можно было прочитать последний его бит, ибо он дальше используется.
Чувствую, что это можно как-то красиво сделать, но как - не соображу за неимением опыта. Помогите кто советом или примером.
Чувствую, что это можно как-то красиво сделать, но как - не соображу за неимением опыта. Помогите кто советом или примером.
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Код: Выделить всё
.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
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, всё работает! Все 32 байтика шлются по ИК как в аптеке!
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Здравствуйте.
В моей программе для ATMega8 таблица векторов прерываний выглядит следующим образом:
Обязательно ли в программе указывать эти ОРГи с адресами?
Ведь адреса следуют друг за другом в порядке возрастания без пропусков...
В моей программе для 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 ; Конец таблицы прерыванийВедь адреса следуют друг за другом в порядке возрастания без пропусков...
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Конечно, необязательно, для АТмега8. Просто тут сделано все максимально "строго".
Без "оргов", если пропущена одна строчка, то будут проблемы - таблица сместится.
Вот для АТмега32, например, там операторы JMP и RETI имеют разную длину (32 и 16 бит), так что просто убрать "орги" не выйдет.
RETI тоже не обязательны, и написаны "на всякий случай" (которого не произойдет, в грамотно написанной программе).
.cseg тоже необязательно писать, т.к. по-умолчанию это так и есть. Нужно, только если перед этим было .dseg или типа того.
Вообще все это необязательно, если ни одного прерывания не используется. Просто начинаем писать программу с первой строчки.
Без "оргов", если пропущена одна строчка, то будут проблемы - таблица сместится.
Вот для АТмега32, например, там операторы JMP и RETI имеют разную длину (32 и 16 бит), так что просто убрать "орги" не выйдет.
RETI тоже не обязательны, и написаны "на всякий случай" (которого не произойдет, в грамотно написанной программе).
.cseg тоже необязательно писать, т.к. по-умолчанию это так и есть. Нужно, только если перед этим было .dseg или типа того.
Вообще все это необязательно, если ни одного прерывания не используется. Просто начинаем писать программу с первой строчки.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Не обязательно. Но вдруг вы очепатку сделаете и напишете "JMP Tim2OVF" и у вас есть обработчик "TIMER1 CAPT". С org-ами компилятор ругнётся, а без вы будете париться искать ошибку...
Уже обсуждалось и не раз. Вот, например http://radiokot.ru/forum/viewtopic.php?f=57&t=72364
Уже обсуждалось и не раз. Вот, например http://radiokot.ru/forum/viewtopic.php?f=57&t=72364
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Парни, привет всем опять! Нуждаюсь в толчке в нужном направлении. Опять-же протокол NEC, на этот раз нужно организовать его приём по ИК. Описание протокола я скидывал чуть выше, повторяться не буду.
Может кто-то подскажет, как это сделать красиво, и лучше бы на живом примере.
Сам дошёл до того, что по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг), но прерывание выходит очень громоздким, некрасиво как-то... Надеюсь на помощь.
Может кто-то подскажет, как это сделать красиво, и лучше бы на живом примере.
Сам дошёл до того, что по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг), но прерывание выходит очень громоздким, некрасиво как-то... Надеюсь на помощь.
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Главный критерий - работоспособность. А что до
на вкус и цвет товарищей, как известно, нет.Seriyvolk писал(а):некрасиво как-то
Docendo discimus


