Ассемблер (ASM) для AVR в вопросах и ответах
А предделитель поменять нет? и Free timer c двумя прерываниями OCR
- Реклама
Эээ... Чаго?ILYAUL писал(а):Free timer c двумя прерываниями OCR
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Спойлер
Код: Выделить всё
;**************************************************
;* ;;/Initialization TIMER1;;* *
;**************************************************
outi OCR1BH, high(7)
outi OCR1BL,low(7)
ldi temp,1<<OCIE1A|1<<OCIE1B
outr TIMSK1,temp
ldi temp,1<<CS11|1<<CS10
outr TCCR1B,temp Код: Выделить всё
;-Задержка на 40us(25кгц) для Xtal 110592MHz
;******************************************
Wait40us:
sbi TIFR1,OCF1A
inr temp,TCNT1L
inr temp1,TCNT1H
subi temp,(low(-6+1))
sbci temp1,(high(-6+1))
outr OCR1AH,temp1
outr OCR1AL,temp
sbis TIFR1,OCF1A
rjmp PC-1
ret
;**************************************
;- Задержка на 1,5ms
;**************************************
Wait1_5ms:
sbi TIFR1,OCF1B
inr temp,TCNT1L
inr temp1,TCNT1H
subi temp,(low(-259+1))
sbci temp1,(high(-259+1))
outr OCR1BH,temp1
outr OCR1BL,temp
sbis TIFR1,OCF1B
rjmp PC-1
ret
;**************************************
;- Задержка на 20 ms
;**************************************
Wait20ms:
sbi TIFR1,OCF1A
inr temp,TCNT1L
inr temp1,TCNT1H
subi temp,(low(-3456+1))
sbci temp1,(high(-3456+1))
outr OCR1AH,temp1
outr OCR1AL,temp
sbis TIFR1,OCF1A
rjmp PC-1
retА можно спросить, для какого камня(ей) работают конструкции типа
?
Код: Выделить всё
sbi TIFR1,OCF1A
;
;
sbis TIFR1,OCF1AПодъебалakl писал(а):А можно спросить, для какого камня(ей) работают конструкции типа
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Реклама
?
SBI-ки работают с младшими 32-мя регистрами, у Меги8 TIFR под номером 56.
SBI-ки работают с младшими 32-мя регистрами, у Меги8 TIFR под номером 56.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Atmega 164P и иже. Atmega48 и ... ATTiny2313-4313akl писал(а):А можно спросить, для какого камня(ей) работают конструкции типа?Код: Выделить всё
sbi TIFR1,OCF1A ; ; sbis TIFR1,OCF1A
Кстати , когда работа прерываниям - эти строки естественно не нужны.
И раздельчик такой есть в DS :
Register summary
- Вложения
-
- Delays_TIMER1.rar
- (9.95 КБ) 161 скачивание
Спасибо, Илья! Правда, уже сам нашёл такие ATmega. У ATtiny (12,13,2313,4313,24...84 и т.д.) такой возможности нет.
Да , это попутал .akl писал(а): У ATtiny (12,13,2313,4313,24...84 и т.д.) такой возможности нет.
мяу)
почему в atmega128 не срабатывает команда sbr flags,(1<<clk)?
почему в atmega128 не срабатывает команда sbr flags,(1<<clk)?
Думаю, ошибка в объявлении.
Код: Выделить всё
.def flags=R16 ;R16...R31
.set clk=0 ;0...7
sbr flags,exp2(clk)
clr flags
sbr flags,(1<<clk) ;установит в flags бит clk
.set clk=0b00001110
sbr flags,clk ; установит биты объявленные clk
Коллеги, как я понял, все метки, объявленные внутри макрокоманды - временные. А нет ли возможности сгенерить внутри макрокоманды постоянную метку? Чтобы она действовала не только внутри макрорасширения, но и в основном тексте?
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Тогда это будет подпрограмма.
Docendo discimus
Ну а сам как думаешь ? Вызвал N раз макрос, получил N макрорасширений с N метками. Все они глобальные, причем адреса разные, а имя одно.afz писал(а): все метки, объявленные внутри макрокоманды - временные. А нет ли возможности сгенерить внутри макрокоманды постоянную метку? Чтобы она действовала не только внутри макрорасширения, но и в основном тексте?
Поставил метку пред макровызовом - она и будет глобальной, делов-то.
А вообще попытка rjmp внутрь чего-то ( неважно - подпрограммы, макрорасширения ) - это порочный стиль "через опу". Языки высокого уровня это не допускают, и правильно делают, но на ассемблере можно и выпендриться. Как говорится, в сумасшедшем доме и не такое делают.
Ничего личного. Просто мое убеждение, основанное на рекомендациях корифеев и 40 годах практики.
Если эти 40 лет практики захватили Систему 360, ты должен помнить фиктивные секции - исключительно удобная фенечка. Вот я и собирался склепать нечто подобное. Увы.Jack_A писал(а): Ничего личного. Просто мое убеждение, основанное на рекомендациях корифеев и 40 годах практики.
Опять же, если твои 40 лет практики захватили PDP-11 и наши ее клоны, то ты должен помнить, что в приличных системах глобальными называют метки, которые определены и/или используются в другом, отдельно транслированном модуле, а связь их происходит на этапе линковки. И вообще, решение для временных меток в Макро-11 близко к идеалу, хотя, на мой взгляд, лучший ассемблер всех времен и народов был все-таки у Системы-360, те же фиктивные секции - рулез немерянный, да и язык макрогенерации (средства условной трансляции, набор и работа с макропеременными и пр.) у Системы-360 на голову выше всех остальных.( Кстати, нет временных и постоянных, есть локальные и глобальные . Временная - это как : после того, как к ней обратились - она стирается ?) .
Вот кусочек текста:А вообще попытка rjmp внутрь чего-то ( неважно - подпрограммы, макрорасширения ) - это порочный стиль "через опу".
Спойлер
Код: Выделить всё
; R4 to HEX
; Вход: R4 - исходный байт
; Выход - два байта по X+
; Рабочий регистр - R18
HEX:
add r2,r4
mov r18,r4
swap r18
rcall hex1
mov r18,r4
HEX1:
andi r18,0x0F
cpi r18,10
brlt hex2
subi r18,('0'-'A'+10)
HEX2:
subi r18,0xD0 ; -'0'
st x+,r18
ret
Этот прием был рекомендован в DEC-овских руководствах по программированию на Макро-11 и работает на любых машинках, где вдрес возврата после CALL'а сохраняется в стеке.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
я уже многое забыл, но по-моему у AVR-овского ассемблера метки внутри макросов остаются глобальными, а чтобы они были локальными, нужен какой-то особый синтаксис - то ли @1, то ли что-то похожее... проверьте, а то я и сам не уверен в том, что говорю - смутные воспоминания...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Нет. @0,@1... - это параметры макровызова. А метки внутри макросов таки внутренние и вне макрорасширения конкретного макровызова не видны. Собственно, столкнувшись с этим я и поднял этот вопрос.ARV писал(а):я уже многое забыл, но по-моему у AVR-овского ассемблера метки внутри макросов остаются глобальными, а чтобы они были локальными, нужен какой-то особый синтаксис - то ли @1, то ли что-то похожее... проверьте, а то я и сам не уверен в том, что говорю - смутные воспоминания...
Проблема в следующем. Мне категорически не нравится рекомендованная производителями метода заполнения таблицы векторов. Я придумал свой вариант - подробно он описан в теме http://radiokot.ru/forum/viewtopic.php? ... 4&start=20, последнее сообщение, вкратце же - копипастим из даташита ассемблерный пример заполнения таблицы векторов, переделываем листинг примера в набор команд (r)jmp и размещаем его в начале .cseg, далее копипастим его второй раз и переделываем в набор меток (тех, на которые ссылались rjmp), это получится набор заглушек для неиспользуемых прерываний, после которого ставим reti или что-то диагностическое, вроде rjmp .-1. Естественно, комментарии и там, и там оставляем. Собрался использовать какое-то прерывание - скопипастил из этой таблицы в нужное место соответствующую строчку, в таблице ее закомментировал, и вперед, не забыть только подправить метку для ADC, если он есть.
Несколько раз применял это решение на 8-й Меге, все было прекрасно, пока не стал переносить один проект на Мегу-8515. Слегка накосячил при замене этих таблиц, долго искал ошибку и понял, что это решение не самое лучшее, хотя и много лучше рекомендованного. Тогда я решил воспользоваться макрокомандами, чтобы в тексте в начале .cseg поставить макрокоманду AVRStart, а в нужном месте - AVRUnusedVec, которая сгенерит метки для неиспользуемых прерываний (посредством .ifndef). Тогда при смене чипа достаточно будет заменить в начале .incude, вызывающий блок макрокоманд для соответствующего контроллера, и все. Сделал, не поленился, сочинил программулю для писюка, которая из листинга, скопированного из даташита, генерит этот набор макрокоманд, попробовал, и тут прилетела птица Обломинго - метки внутри макрорасширения строго локальные...
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Всё придумано до нас. Таблица векторов представляет собой .inc/asm файл, индивидуальный для каждого типа контроллера. Подключается в начале программы. И никакой путаницы.afz писал(а):Мне категорически не нравится рекомендованная производителями метода заполнения таблицы векторов. Я придумал свой вариант
Где не нужно - заглушка RETI, где нужно - прыжок на обработчик. По мне, так самое удобное решение.
Спойлер
Код: Выделить всё
.CSEG
.include "vectors.asm" ; Подключаем таблицу векторов прерывания
.org INT_VECTORS_SIZE ; Конец таблицы прерыванийКод: Выделить всё
.ORG 0x0000 ; Проц стартует с нуля, но дальше идут вектора
RJMP Reset ; прерываний, поэтому отсяюда сразу же прыгаем
; на начало программы. На метку Reset
; Тут распологается таблица векторов важнейшая вещь. Если про нее забыть, то
; можно огрести такие неразрешимые глюки, что просто капец. Так что не забываем.
; я его тупо скопировал из файла m8def.inc и заменил все .equ на .org, а потом
; дописал везде команду RETI. На случай если прерывание вдруг вылезет, чтобы
; вернулось туда же откуда прервалось.
; ***** INTERRUPT VECTORS ************************************************
.org INT0addr ; External Interrupt Request 0
RJMP Interrupt_0
.org INT1addr ; External Interrupt Request 1
RJMP Interrupt_1
.org PCI0addr ; Pin Change Interrupt Request 0
RETI
.org PCI1addr ; Pin Change Interrupt Request 1
RETI
.org PCI2addr ; Pin Change Interrupt Request 2
RJMP Pin_Change_Interrupt_2
.org WDTaddr ; Watchdog Time-out Interrupt
RETI
.org OC2Aaddr ; Timer/Counter2 Compare Match A
RETI
.org OC2Baddr ; Timer/Counter2 Compare Match A
RETI
.org OVF2addr ; Timer/Counter2 Overflow
RETI
.org ICP1addr ; Timer/Counter1 Capture Event
RETI
.org OC1Aaddr ; Timer/Counter1 Compare Match A
RETI
.org OC1Baddr ; Timer/Counter1 Compare Match B
RETI
.org OVF1addr ; Timer/Counter1 Overflow
RETI
.org OC0Aaddr ; TimerCounter0 Compare Match A
RJMP TimerCounter0_Compare_Match_A
.org OC0Baddr ; TimerCounter0 Compare Match B
RJMP TimerCounter0_Compare_Match_B
.org OVF0addr ; Timer/Couner0 Overflow
RJMP Timer_Couner0_Overflow
.org SPIaddr ; SPI Serial Transfer Complete
RETI
.org URXCaddr ; USART Rx Complete
RETI
.org UDREaddr ; USART, Data Register Empty
RETI
.org UTXCaddr ; USART Tx Complete
RETI
.org ADCCaddr ; ADC Conversion Complete
RJMP ADC_Complete
.org ERDYaddr ; EEPROM Ready
RETI
.org ACIaddr ; Analog Comparator
RETI
.org TWIaddr ; Two-wire Serial Interface
RETI
.org SPMRaddr ; Store Program Memory Read
RETI Прибор, защищённый предохранителем, сгорает первым, защитив предохранитель. Закон Мерфи.
То есть такая же самоделка, что и предложил я. Только у меня более-менее универсальная, а здесь под каждый проект нужно клепать отдельную, у меня отдельная нужна только под каждый контроллер. Вот пример для Меги 8515 в исходном виде (без макрокоманд). Начинать новый проект - одно удовольствие, а вот переносить на другой камень - можно допустить ошибку, которую долго придется искать.Seriyvolk писал(а): Всё придумано до нас. Таблица векторов представляет собой .inc/asm файл, индивидуальный для каждого типа контроллера. Подключается в начале программы. И никакой путаницы.
Где не нужно - заглушка RETI, где нужно - прыжок на обработчик. По мне, так самое удобное решение.Спойлер
Код: Выделить всё
.CSEG .include "vectors.asm" ; Подключаем таблицу векторов прерывания .org INT_VECTORS_SIZE ; Конец таблицы прерыванийКод: Выделить всё
.ORG 0x0000 ; Проц стартует с нуля, но дальше идут вектора RJMP Reset ; прерываний, поэтому отсяюда сразу же прыгаем ; на начало программы. На метку Reset ; Тут распологается таблица векторов важнейшая вещь. Если про нее забыть, то ; можно огрести такие неразрешимые глюки, что просто капец. Так что не забываем. ; я его тупо скопировал из файла m8def.inc и заменил все .equ на .org, а потом ; дописал везде команду RETI. На случай если прерывание вдруг вылезет, чтобы ; вернулось туда же откуда прервалось.
Спойлер
Код: Выделить всё
.include <m8515def.h>
rjmp RESET ; Reset Handler
rjmp EXT_INT0 ; IRQ0 Handler
rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_COMPA ; Timer1 Compare A Handler
rjmp TIM1_COMPB ; Timer1 Compare B Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
rjmp SPI_STC ; SPI Transfer Complete Handler
rjmp USART_RXC ; USART RX Complete Handler
rjmp USART_UDRE ; UDR0 Empty Handler
rjmp USART_TXC ; USART TX Complete Handler
rjmp ANA_COMP ; Analog Comparator Handler
rjmp EXT_INT2 ; IRQ2 Handler
rjmp TIM0_COMP ; Timer0 Compare Handler
rjmp EE_RDY ; EEPROM Ready Handler
rjmp SPM_RDY ; Store Program memory Ready Handler
RESET: ldi r16,high(RAMEND) ; Main program start
out SPH,r16 ; Set Stack Pointer to top of RAM
ldi r16,low(RAMEND)
out SPL,r16
sei ; Enable interrupts
; Здесь пишем свою программу
;****************************************************************
; Заглушки для неиспользуемых прерываний
; Если понадобится, скопировать строку отсюда и поместить в
; соответствующее место программы, а здесь ее закомментировать
EXT_INT0: ; IRQ0 Handler
EXT_INT1: ; IRQ1 Handler
TIM1_CAPT: ; Timer1 Capture Handler
TIM1_COMPA: ; Timer1 Compare A Handler
TIM1_COMPB: ; Timer1 Compare B Handler
TIM1_OVF: ; Timer1 Overflow Handler
TIM0_OVF: ; Timer0 Overflow Handler
SPI_STC: ; SPI Transfer Complete Handler
USART_RXC: ; USART RX Complete Handler
USART_UDRE: ; UDR0 Empty Handler
USART_TXC: ; USART TX Complete Handler
ANA_COMP: ; Analog Comparator Handler
EXT_INT2: ; IRQ2 Handler
TIM0_COMP: ; Timer0 Compare Handler
EE_RDY: ; EEPROM Ready Handler
SPM_RDY: ; Store Program memory Ready
reti ; При получении незапланированного
; прерывания молча выходим.
; При нужде можно поставить ловушку типа RJMP *
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)


