В подпрограмме обработки выполняю однократное измерение АЦП в канале 7, после чего разрешаю прерывания от АЦП, предварительно сбросив флаг ADIF и запускаю режим Free Running.
В один прекрасный момент времени (от секунд, до 5-ти часов) происходит сброс флага ADIE, регистра ADCSRA. И все - работа устройства нарушена. Причем это происходит как в железе, так и в Proteus... При этом состояние счетчика overs в Proteus всегда равно 0! Следовательно логично предположить о том, что затирается флаг ADC_DATA регистра flags+0 именно в момент выхода из прерывания по АЦП и нет выхода на участок обработки. Пробовать менять бит флага на другой? Замена адреса регистра ни к чему не привела...
Косвенную адресацию по коду проглядывал, регистр ADCSRA нигде не портится. Регистр флагов, в котором выставляется флаг готовности данных - тоже. Можно, конечно, заменить этот флаг на проверку запрета прерываний от АЦП - ADCSRA,ADIE... Но это не отменит моего вопроса. Может какие есть подводные камни?
Участки кода:
Прерывания:
Спойлер
ADC_:; По первому прерыванию читаем значение напряжения, меняем канал на ток.
; По второму запрещаем прерывания от АЦП, читаем значение тока и выставляем флаг готовности данных
push r16
in r16,Sreg
push r16
push r17
push r18
push r19
push r20
...
lds r16,overs
dec r16
sts overs,r16
brne ADC_2
; Запрещаем прерывания от АЦП
cbi ADCSRA,ADIE
; Выставим флаг готовности данных для преобразования
lds r16,flags+0
sbr r16,EXP2(ADC_DATA)
sts flags+0,r16
ADC_2:
pop r20
pop r19
pop r18
pop r17
pop r16
out Sreg,r16
pop r16
reti
Спойлер
lds r16,flags+0sbrc r16,ADC_DATA
rcall oversampling ; подсчет напряжения по наличию нужного количества отсчетов
Спойлер
oversampling:cbr r16,EXP2(ADC_DATA)
sts flags+0,r16
...
in r16,ADMUX
andi r16,(1<<REFS1|1<<REFS0|1<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0) ; clear MUX
ori r16,(0<<REFS1|0<<REFS0|0<<ADLAR|0<<MUX3|1<<MUX2|1<<MUX1|1<<MUX0) ; set MUX ADC7
out ADMUX,r16
ldi r16,(1<<ADEN|0<<ADSC|0<<ADFR|0<<ADIE|1<<ADPS2|0<<ADPS2|1<<ADPS0)
out ADCSRA,r16
rcall Delay_100uS ;Нужно для отключения free running, т.к.
; бит ADSС в режиме free running не выключается!
ldi r16,(1<<ADEN|1<<ADSC|0<<ADFR|0<<ADIE|1<<ADPS2|0<<ADPS2|1<<ADPS0)
out ADCSRA,r16
ADC_7:
sbic ADCSRA,ADSC
rjmp ADC_7
in r16,ADCL
in r17,ADCH
...
sbi ADCSRA,ADIF ; сбросим признак прерывания по АЦП перед его разрешением
ldi r16,(1<<ADEN|1<<ADSC|1<<ADFR|1<<ADIE|1<<ADPS2|0<<ADPS2|1<<ADPS0)
out ADCSRA,r16
ldi r16,(0<<REFS1|0<<REFS0|0<<ADLAR|0<<MUX3|0<<MUX2|0<<MUX1|0<<MUX0)
out ADMUX,r16
ret


