Ассемблер (ASM) для AVR в вопросах и ответах
Да, всё работает! Все 32 байтика шлются по ИК как в аптеке!
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- Реклама
Поздравляю! 
Docendo discimus
- Сообщения: 52
- Зарегистрирован: Пн май 27, 2013 17:02:32
Здравствуйте.
В моей программе для 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 ; Конец таблицы прерыванийВедь адреса следуют друг за другом в порядке возрастания без пропусков...
Конечно, необязательно, для АТмега8. Просто тут сделано все максимально "строго".
Без "оргов", если пропущена одна строчка, то будут проблемы - таблица сместится.
Вот для АТмега32, например, там операторы JMP и RETI имеют разную длину (32 и 16 бит), так что просто убрать "орги" не выйдет.
RETI тоже не обязательны, и написаны "на всякий случай" (которого не произойдет, в грамотно написанной программе).
.cseg тоже необязательно писать, т.к. по-умолчанию это так и есть. Нужно, только если перед этим было .dseg или типа того.
Вообще все это необязательно, если ни одного прерывания не используется. Просто начинаем писать программу с первой строчки.
Без "оргов", если пропущена одна строчка, то будут проблемы - таблица сместится.
Вот для АТмега32, например, там операторы JMP и RETI имеют разную длину (32 и 16 бит), так что просто убрать "орги" не выйдет.
RETI тоже не обязательны, и написаны "на всякий случай" (которого не произойдет, в грамотно написанной программе).
.cseg тоже необязательно писать, т.к. по-умолчанию это так и есть. Нужно, только если перед этим было .dseg или типа того.
Вообще все это необязательно, если ни одного прерывания не используется. Просто начинаем писать программу с первой строчки.
Не обязательно. Но вдруг вы очепатку сделаете и напишете "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 г.)
- Реклама
Парни, привет всем опять! Нуждаюсь в толчке в нужном направлении. Опять-же протокол NEC, на этот раз нужно организовать его приём по ИК. Описание протокола я скидывал чуть выше, повторяться не буду.
Может кто-то подскажет, как это сделать красиво, и лучше бы на живом примере.
Сам дошёл до того, что по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг), но прерывание выходит очень громоздким, некрасиво как-то... Надеюсь на помощь.
Может кто-то подскажет, как это сделать красиво, и лучше бы на живом примере.
Сам дошёл до того, что по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг), но прерывание выходит очень громоздким, некрасиво как-то... Надеюсь на помощь.
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
Главный критерий - работоспособность. А что до
на вкус и цвет товарищей, как известно, нет.Seriyvolk писал(а):некрасиво как-то
Docendo discimus
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
Тут http://radiokot.ru/forum/viewtopic.php?f=61&t=87127 я как то выкладывал свой вариант читалки на Си, думаю перевернуть для асма, проблем не составит...
Если сам не сможеш, помогу, как чуть время появится......
Если сам не сможеш, помогу, как чуть время появится......
pyzhman - главный критерий - аккуратность во всём, иначе я просто бы начал изучение МК с Си.
А то, что прерывание занимает больше, чем остальной код - хорошего ничего в этом нет.
shads, сейчас у меня нечто похожее и есть, но выглядит оно не сильно здорово, согласись.
А то, что прерывание занимает больше, чем остальной код - хорошего ничего в этом нет.
shads, сейчас у меня нечто похожее и есть, но выглядит оно не сильно здорово, согласись.
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
По мне, определение длительности паузы приводит к необходимости двух разных типов прерываний - по фронту и по спаду. А вот если определять длительность посылки между двумя фронтами, то получается проще. Вот попробовал написать в предположении, что входной сигнал подается на вход INT0 и инвертирован по отношению к протоколу.Seriyvolk писал(а):по прерыванию сравниваю время паузы меду импульсами от большего к меньшему и по итогам сравнения уже идёт какое-либо действие (запись 1/0 в регистр и его сдвиг)
Спойлер
Код: Выделить всё
;TEST_Seriyvolk
.include "tn13def.inc" ; Используем Tiny13
.set Fo=9600000 ; встроенный генератор 9.6MHz
;//////////////////////////////////////////////////////////////////////////////
;//////////// ПЕРЕМЕННЫЕ /////////////
;//////////////////////////////////////////////////////////////////////////////
.CSEG
;/////////////////////////////////////////////////////////
;//////////// ПРЕРЫВАНИЯ /////////////
;/////////////////////////////////////////////////////////
RJMP START
IJMP ; обслуживание прерывания посылки
RETI
TIME_OVER:
ADIW XH:XL,1
CP R19,XL
CPC R18,XH
BRLO START
RETI
;***********************************
ISR_INT_BEG:
CLR XH
CLR XL
LDI ZL,LOW(ISR_INT_END)
RETI
ISR_INT_END:
SET
RET
;/////////////////////////////////////////////////////////
;//////////// ИНИЦИАЛИЗАЦИЯ /////////////
;/////////////////////////////////////////////////////////
Start:
LDI R16,RAMEND
OUT SPL,R16
CLR ZH
CLR XH
CLR XL
LDI R16,0b00000010
OUT PORTB,R16
OUT DDRB,R16
NOP
OUT DDRB,ZH
LDI R18,HIGH(120000/(1000000/(Fo/256))) ;порог для определения отсутствия
LDI R19,LOW (120000/(1000000/(Fo/256))) ;операций
LDI R20,HIGH(13000/(1000000/(Fo/256))) ; длительность синхропосылки
LDI R21,LOW (13000/(1000000/(Fo/256))) ; минус защитный интервал
LDI R16,0b00100010
OUT MCUCR,R16 ; разрешение прерывания по спаду INT0
LDI R16,$40
OUT GIMSK,R16 ; разрешение прерывания INT0
LDI R16,0b00000010
OUT TIMSK0,R16
SER R16
OUT TIFR0,R16
OUT GIFR,R16
LDI ZL,LOW(ISR_INT_BEG)
LDI R16,1
OUT TCCR0B,R16
CLT
SEI
WAIT_SINHRO:
SLEEP
BRTC WAIT_SINHRO
CLT
CP XL,R21
CPC XH,R20
BRLO START ; не, это не синхропосылка
; принята синхропосылка
RESEIVE_CODE_BEGIN:
CLR R10
CLR R11
CLR R12
CLR R13 ;очистить регистры приёма
LDI R22,32 ; счётчик битов
GO_RESEIVE:
CLR XH
CLR XL
LDI R20,HIGH(1680/(1000000/(Fo/256))) ;порог для определения 1 или 0
LDI R21,LOW (16800/(1000000/(Fo/256))) ;
SER R16
OUT TIFR0,R16
OUT GIFR,R16
LDI ZL,LOW(ISR_INT_END)
LDI R16,1
OUT TCCR0B,R16
CLT
SEI
WAIT_CODE:
SLEEP
BRTC WAIT_CODE
CLT
; принят очередной бит
CP XL,R21
CPC XH,R20
BRLO SET_0 ;
SET_1:
SEC
RJMP SET_GND
SET_0:
CLC
SET_GND:
ROR R10
ROR R11
ROR R12
ROR R13
DEC R22
BRNE GO_RESEIVE
; принят адрес и код команды
;
;
RJMP GO_RESEIVE
; RJMP START
; END
Последний раз редактировалось akl Вс янв 19, 2014 18:30:48, всего редактировалось 1 раз.
Да, длительность посылки вполне реально определять между фронтами, а поскольку с ИК приёмника сигнал идёт инвертированным - фронты спадающие.
Идею почти понял, ща немного раскурю этот кусок кода и попробую воплотить его в жизнь
Идею почти понял, ща немного раскурю этот кусок кода и попробую воплотить его в жизнь
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
Хотите сказать, что на Си не возможно писать аккуратно?Seriyvolk писал(а):pyzhman - главный критерий - аккуратность во всём, иначе я просто бы начал изучение МК с Си.
Вообще то большой код в прерывании, совсем не означает, что оно выполняется долго (я так понял вы именно это имели ввиду)...Seriyvolk писал(а):А то, что прерывание занимает больше, чем остальной код - хорошего ничего в этом нет.
На сам деле, обычно туда включено много (коротких и быстрых) ветвей алгоритма... и именно поэтому код может кажется громоздким.....
В целом, вот как я решил у себя http://radiokot.ru/forum/viewtopic.php? ... 6#p1623176Seriyvolk писал(а):Да, длительность посылки вполне реально определять между фронтами
В целом, на данный момент я имею крайне схожее решение, но оно мне не нравится.shads писал(а):В целом, вот как я решил у себя http://radiokot.ru/forum/viewtopic.php? ... 6#p1623176
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
Чем?Seriyvolk писал(а):В целом, на данный момент я имею крайне схожее решение, но оно мне не нравится.shads писал(а):В целом, вот как я решил у себя http://radiokot.ru/forum/viewtopic.php? ... 6#p1623176
Алгоритмом, вестимо. Так же вся борода обрабатывается в прерывании. Много сравнений/переходов и всяких других действий.
Да, без знания основ - невозможно.Хотите сказать, что на Си не возможно писать аккуратно?
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
И что из за этого у вас в программе страдает?Seriyvolk писал(а):вся борода обрабатывается в прерывании.
По другому у вас получится калека, а не декодер...Seriyvolk писал(а):Много сравнений/переходов и всяких других действий.
Согласен... основы не помешаютSeriyvolk писал(а):Да, без знания основ - невозможно.
- Сообщения: 52
- Зарегистрирован: Пн май 27, 2013 17:02:32
Здравствуй, РадиоКот.
Ты меня пока ни разу не подводил.
Уверен, что не подведёшь и сейчас.
Помоги мне, пожалуйста, а то я уже голову сломал.
Пишу часики на ассме.
Для ATMega16 всё написано, просимулировано, работает отлично, посмотреть можно тут.
Но решил я впихнуть свои часики в ATMega8, ибо жирновато им быть в 16-й Меге.
И тут появились траблы.
Во-первых, Протеус не может симулировать в реальном времени, ругается, что чрезмерная загрузка проца.
Во-вторых, 9-й и 10-й выводы контроллера походу работают в режиме GPIO (PB6, PB7), хотя настроены на работу с часовым кварцем.
Блин, но в проекте для ATMega16 таких проблем не возникало!!!
Где искать баги???
Ну и собстно прилагаю сам код, из которого вырезал всё лишнее, оставил только индикацию для одного семисегментника.
Ты меня пока ни разу не подводил.
Уверен, что не подведёшь и сейчас.
Помоги мне, пожалуйста, а то я уже голову сломал.
Пишу часики на ассме.
Для ATMega16 всё написано, просимулировано, работает отлично, посмотреть можно тут.
Но решил я впихнуть свои часики в ATMega8, ибо жирновато им быть в 16-й Меге.
И тут появились траблы.
Во-первых, Протеус не может симулировать в реальном времени, ругается, что чрезмерная загрузка проца.
Во-вторых, 9-й и 10-й выводы контроллера походу работают в режиме GPIO (PB6, PB7), хотя настроены на работу с часовым кварцем.
Блин, но в проекте для ATMega16 таких проблем не возникало!!!
Где искать баги???
Ну и собстно прилагаю сам код, из которого вырезал всё лишнее, оставил только индикацию для одного семисегментника.
По-моему, Вы слишком рано выключаете разряд, нужно немного попозже, примерно одну четверть времени от полного цикла вывода всех четырех разрядов.
P.S. Организация дисплея конечно не очень. Посмотрите в протеусе, есть хороший пример с драйвером для семисегментника на асме, в папке C:\Program Files\Labcenter Electronics\Proteus 7 Professional\SAMPLES\VSM for AVR\AVR Tiny15 Demo, главное поймите как это работает
P.S. Организация дисплея конечно не очень. Посмотрите в протеусе, есть хороший пример с драйвером для семисегментника на асме, в папке C:\Program Files\Labcenter Electronics\Proteus 7 Professional\SAMPLES\VSM for AVR\AVR Tiny15 Demo, главное поймите как это работает
Последний раз редактировалось zero648 Чт янв 23, 2014 23:41:35, всего редактировалось 1 раз.
в протеусе в свойствах контроллера указать CKSEL fuses - внешний кварц, и указать частоту кварцаBlYur писал(а):Протеус не может симулировать в реальном времени
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Эт снова я!
По старой доброй традиции опять с проблемой...
Суть её такова: В регистре (допустим R25) имею число в диапазоне от нуля до 99 по десятичной системе. Мне это число нужно вывести на дисплей 44780, и всего-то.
Для вывода пользуюсь функцией, в переменную которой (R17) нужно загружать код символа перед выводом.
Т.е. примерно так:
LDI R17,0b00100000
DATA_WR //Вывели на дисплей пробел
DATA_WR //Вывели ещё один пробел
Может кто скажет, как это проще делается?
Суть её такова: В регистре (допустим R25) имею число в диапазоне от нуля до 99 по десятичной системе. Мне это число нужно вывести на дисплей 44780, и всего-то.
Для вывода пользуюсь функцией, в переменную которой (R17) нужно загружать код символа перед выводом.
Т.е. примерно так:
LDI R17,0b00100000
DATA_WR //Вывели на дисплей пробел
DATA_WR //Вывели ещё один пробел
Может кто скажет, как это проще делается?
Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.


