Цитата(singlskv @ Oct 7 2006, 09:37)

Подправил немного код
GetSmart и
defunct- добавил сохранение SREG в прерываниях
- добавил сброс флага TOV1 в TIFR если делали коррекцию
Код
.def AL = R24
.def Const0 = R8
.def Const1 = R9
.def _Sreg = R10
....
ldi AL, 1
mov Const1, AL
clr Const0
...
; обработчик Input Capture:
TIM1_CAPT:
in _Sreg,SREG
in R4, ICR1L
in R5, ICR1H
tst R5
brne _do_not_correct_result
in AL, TIFR
andi AL, (1 << TOV1)
breq _do_not_correct_result
out TIFR, AL
add R2, Const1
adc R3, Const0
_do_not_correct_result:
mov R6, R2
mov R7, R3
out SREG,_Sreg
; <-- 32-х битный результат в четверке регистров R7-R6-R5-R4 (MSB R7)
reti
; обработчик Timer Overflow:
TIM1_OVF:
in _Sreg,SREG
add R2, Const1; Инкрементировать старшие 16 бит 32-х битного счетчика
adc R3, Const0; учет переноса.
out SREG,_Sreg
reti
Хочу немного покритиковать программу.
1) От возникновения прерывания захвата до команды "in AL,TIFR" может пройти от 12 до 15 МЦ, т.е. достаточно много времени, чтобы произошел перенос от переполнения, следовательно, возможна ошибка в определении времени.
2) Вполне возможно, что если прерывания TIM1_OVF и TIM1_CAPT возникли в течение указанного периода, то прерывание TIM1_OVF выполнится после TIM1_CAPT и ПОВТОРНО скорректирует результат в r3-r2 (не уверен на все 100, надо проверять).
3) Вход в прерывание TIM1_CAPT означает конец интервала измерения и наличие правильного времени в r5-r4 за исключением возможного последнего переноса. Но поскольку перенос из r5-r4 в r7-r6 возможен в одном единственном случае, когда содержимое r5-r4 переходит из состояния 0xFFFF в 0x0000, содержимое регистров r5-r4 надо проверять на 0.
В соответствии со сказанным ниже приведена исправленная программа обработки.
Код
.def temp =r16
.def savreg =r10
; обработчик Input Capture:
TIM1_CAPT: in savreg,SREG
in R4,ICR1L ;точные два младших
in R5,ICR1H ;байта времени
movw r6,r2 ;два старших байта времени
mov temp,r4 ;с возможным переносом
or temp,r5 ;во время захвата
brne nocarry ;не было переноса
subi r6,-1 ;учтем
sbci r7,-1 ;перенос
nocarry: out SREG,Sreg
reti
; обработчик Timer Overflow:
TIM1_OVF: in savreg,SREG
subi r2,-1 ;
sbci r3,-1 ;
out SREG,savreg
reti
Ну и последнее, в подобных случаях предпочитаю использовать конструкцию
Код
subi r2,-1 ;
sbci r3,-1 ;
Вместо эквивалентной
Код
add R2,сonst1 ;
adc R3,сonst0 ;
что очевидно лучше, поскольку освобождаются два регистра сonst0 и сonst1.