Вообще, задание некорректно сформулировано:
Во-первых, не указано какой именно AVR используется - от этого зависит возможно ли использовать команду mul для умножения или нужно писать свою функцию для этого.
Во-вторых, не указана частота, на которой будет работать МК, а без этого в программе невозможно задать временные интервалы (можно задать интервалы в тактах, а уж сколько это будет миллисекунд - зависит от частоты)
Доброго времени суток. Я пытаюсь разобраться с формированием временных интервалов. Я пытаюсь записать значение TCNT0 в R16 регистр, для последующего сравнения, но этого не происходит, счетчик работает до момента записи в temp и обнуляется. В регистре R16 ноль.
Собственно, не могу разобраться, где я накосячил. Контроллер attiny2313 AtmelStudio 6.1.2730
Вообще говоря, в байте восемь бит. Мелкий огрех, но тем не менее.
Раз уж вы запустили таймер, то может проще все сравнения делать в прерываниях от него? И зачем эти сравнения, если можно задать время прерывания?
Приветствую обитатеелй сей ветки! Не так давно начал осваивать АСМ, и решился таки взяться за (довольно серьёзный для меня на данный момент) проект.
Суть его такова : Нужно сделать что-то типа аналога пульта ДУ, но только с проводным управлением. На руле есть два независимых ряда кнопок, каждая из кнопок в котором коротит на общий свой резистор. Оба ряда одинаковы, сопротивления нажатых клавиш я замерял 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
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Может натолкнёте на мысль, как это всё можно попроще сообразить?
Делается сетка с помощью таймера в режиме СТС с определенным интервалом, в прерывании таймера опрашивается АЦП сразу два канала по очереди, можно и чередовать через один, и сохраняется значение в переменных. В основном цикле считается количество подряд считанных одинаковых значений с допуском определенной погрешности, если нужной выдержки достигли, то выполняем какое-то действие, если не достигли, а значение АЦП изменилось, тогда обнуляем счетчик.
помогите пожалуйста) начал учить асм, уже 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 раз.
Это не спортивно, просто копировать целиком весь байт (весь регистр). Другие же биты портов могут быть использованы для других целей! По-хорошему надо проверять один бит, к которому кнопка подключена, и переключать тоже один бит, со светодиодом. Еще, в реальной жизни обычно делают подтяжку кнопки к плюсу внешним резистором, т.к. внутренняя подтяжка слишком высокоомная. Но в учебных целях сойдет.
Друзья! Всех с Новым Годом! Желаю всем удачи в 2014 году!
- чтоб дома все было хорошо!
- много разных денег!
- крепкого здоровья!
- чтоб все Ваши устройства работали и не глючили
Есть у меня 4 числа в регистрах, по 8 бит каждое. Мне нужно их как-то поставить в ряд и сдвигать вправо, т.е. сдвинуть это большое число вправо 32 раза, чтоб каждый раз можно было прочитать последний его бит, ибо он дальше используется.
Чувствую, что это можно как-то красиво сделать, но как - не соображу за неимением опыта. Помогите кто советом или примером.
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
.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
;
;далее делаем то, что надо
;