Engineer_Keen писал(а):Мастер Ломастер Опередил, как раз хотел вариант с LDI выложить
да, блин, вас опредешь... поспешил вон - и облажался
категорически не рекомендую помещать код в область таблицы векторов! мало того, что в случае с AVR-GCC это весьма нетривиально, так еще и мало модифицируемо впоследствии. как правило, жалкие 20 байт таблицы погоды в программе не делают.
битва с дураками проиграна, победители торжествуют. слава победителям!
категорически не рекомендую помещать код в область таблицы векторов!
Я тоже не рекомендую, это такой мелкий хак, делал, когда пытался вывести на порт программный меандр с максимально возможной частотой. Там каждый такт на счету.
Мастер Ломастер писал(а):категорически не рекомендую помещать код в область таблицы векторов! мало того, что в случае с AVR-GCC это весьма нетривиально, так еще и мало модифицируемо впоследствии.
Это да.
Мастер Ломастер писал(а):как правило, жалкие 20 байт таблицы погоды в программе не делают.
С точки зрения размера да, а вот если критично быстродействие...
Coolish писал(а):ага, всё понятно.
Если ldi не меняет SREG, то тогда вообще замечательно
Кстати есть еще SER, которая выставляет все биты в регистре (в противоположность CLR) - она тоже SREG не меняет.
так все элементарно: CLR Rx - это просто дополнительный мнемокод операции EOR Rx, Rx, т.е. логической операции, а все логические операции изменяют регистр флагов.
а SER Rx- это мнемокод команды LDI Rx, 0xFF - а команды загрузки не меняют регистр флагов. то есть фактически пары CLR - EOR и SER - LDI есть синонимы
битва с дураками проиграна, победители торжествуют. слава победителям!
в данном случае как раз наоборот: разбрасываются командами вон микрочиповцы раньше всегда кричали - у нас всего 23 команды! RISС! а у AVR аж больше сотни! а на поверку добрая половина из этой сотни тупо переводит стрелки на коды из другой половины
битва с дураками проиграна, победители торжествуют. слава победителям!
1 случай:
ldi temp , 0b00000011 ; активирую таймер с делением частоты на 64
out TCCR1B,temp
ldi temp,(1<<TOIE1 ) ;активирую прерывание по переполнению!
out TIMSK,temp
обработчик прерывания:
perepolnenie:
in temp, PortB
eor temp,r18
out PortB,temp
reti
В этом случае светодиод моргает с частотой 1 раз в скунду
2 случай:
ldi temp , 0b00001101 ; запуск таймера T\C1 с делением !!! на 1024 !!!
out TCCR1B,temp ; режим(CTC) сброс при совпадении
ldi temp, 0xFF ;здесь записываю максимальное число
out OCR1AL,temp ;по сути получается "прерывание по переполнению"
ldi temp, 0xFF ;
out OCR1AH,temp ;
ldi temp,( 1<<OCIE1A) ; разрешение прерывание по сравнению
out TIMSK,temp
НО!!! в этом случае, не смотря на то что деление частоты большее,
т.е. таймер должен работать медленней,а моргание происходит чаще!
Как такое может быть?
Работаю на отладочной плате STK500, на Atmega8515
полный код прилагаю.
У вас в OCR1A вместо 0xFFFF записывается чёрт знает что, скорее всего 0x00FF. Отсюда прерывания чаще в 256 раз, а предделитель больше всего в 16 раз. Итого, мигание происходит чаще в 16 раз.
Доступ к 16-разрядным регистрам
Регистры TCNTn, OCRnA/B/C и ICRn являются 16-разрядными, поэтому, доступ к ним через 8-разр. шину данных AVR ЦПУ может быть осуществлен с помощью двух инструкций чтения или записи.
.....
Таким образом, чтобы записать данные в 16-разр. регистр, необходимо сначала записать старший байт, а затем младший. А при чтении 16-разр. регистра, наоборот, сначала считывается младший байт, а затем старший.
Прочитайте про временный регистр подробнее, это важно
/* */
.cseg
.org 0
;стек
ldi r16,low(RAMEND)
out spl,r16
ldi r16,high(RAMEND)
;порт D на выход
ldi r16,0b0000011
out DDRD,r16
;порт B на вход
ldi r16,0
out DDRB,r16
; ждём нажатия кнопки 1 или 2 (в симуляторе ставлю бит в PINB)
one:
in r16,PINB
cpi r16,0b0000001
breq two
in r16,PINB
cpi r16,0b0000010
breq two
rjmp one
two:
out portd,r16
rcall del5;del
rjmp one
;====
del5: wdr
ldi YL,low(5)
ldi YH,high(5)
d5_1: sbiw YL,1
brne d5_1
ret
на симуляторе в AVRStudio5 работает. На МК нет.
что я сделал не так, подскажите пожалуйста.
Последний раз редактировалось killeo Пн фев 20, 2012 21:22:26, всего редактировалось 2 раза.
.cseg
.org 0
; инициализация стека
ldi r16,low(RAMEND)
out spl,r16
ldi r16,0b11111111
out ddrd,r16
out PORTB,r16 ;подтяжка к порту B
ldi r16,0
out DDRB,r16
one:in r16,PINB
cpi r16,0b11111110
breq two
in r16,PINB
cpi r16,0b11111101
breq two
rjmp one
two:out portd,r16
rcall del5;del
rjmp one
;====
del5:wdr
ldi YL,low(5)
ldi YH,high(5)
d5_1: sbiw YL,1
brne d5_1
ret
Кстати, вот подумалось что для начинающих было бы лучше начинать осваивать программирование с метода черного ящика. Вот недавно наткнулся на статью http://ru.wikipedia.org/wiki/%D0%A7%D0% ... 0%B8%D0%BA и понял что же я оказывается постоянно использую при написании каких бы то нибыло программ и в разработке устройств.
самое главное там:
Все иные свойства полностью исключаются из рассмотрения, и о самом их существовании требуется забыть (наиболее трудный момент).