Страница 1 из 1

Стиковка подпрограммы измирения и индикации

Добавлено: Вс дек 06, 2009 14:15:15
sad-angel
Есть подпрограмма для измирения переменного напряжения: по прерыванию таймера Т1 каждых 625 мкс запускаеться АЦП,делает замер,и в обработчике АЦП обрабатывает результат (возводить в квадрат результат измирения,сумирует квадраты за 32 выборки,потом усредняет результат и извлекает квадратный корень).
виборки производиться в течении 20мс (периода синусоиды)

Другая подпрограмма - динамическая индикация: у меня есть два варианты реализации на таймере Т0 и в главном цикле программы.

Отдельно подпрограммы работают,вместе нет!
Не могу понять в чем причина!

c индикацией на таймере Протеус на индикаторах показивает всякую чушь,но “бежучая единица” (используються тран.ключи) едет и заметно что идут даные на индикатор. Программа не реагирует на изминения напряжения на входе АЦП.

При индикации в главном цикле - отображаеться “0″ но не идут даные на дисплей и нет “бежучей единицы”

Добавлено: Вс дек 06, 2009 14:21:07
sad-angel
МК ATmega8

Добавлено: Вс дек 06, 2009 14:55:28
AI_Disable
Да уж. Только названия МК тут и нехватало. А если серьёзно, то пока в теме не появится исходик, наврятли вам сможет кто-либо помочь.

Добавлено: Вс дек 06, 2009 15:17:55
sad-angel
AI_Disable писал(а): А если серьёзно, то пока в теме не появится исходик, наврятли вам сможет кто-либо помочь.
Измирения:
.include "m8def.inc"
.def temp=r17
.def al=r0
.def ah=r1
.def ADSL=r2
.def ADST=r3
.def ADSH=r4
.def ACT=r5

.def rzl=r6
.def rzt=r7
.def rzh=r8


.macro outi
ldi r16,@1
out @0,r16
.endmacro

.org 0
rjmp reset
.org OC1Aaddr
rjmp T1_comp
.org ADCCaddr
rjmp Result



reset:
ldi temp,32
mov ACT,temp

outi ddrd,0xff
outi SPH,High(RamEnd)
outi SPL,Low(RamEnd)

outi ADMUX,0b11000000
outi ADCSR,0b10011110

outi TIMSK,0x10; // 0001 0000
outi OCR1AH,High(5000)
outi OCR1AL,Low(5000)
outi TCCR1B,0x9; // 0000 1001
outi TCNT1H,0x0; // 0000 0000
outi TCNT1L,0x0; // 0000 0000

sei

loop:rjmp loop

T1_comp:
sbi ADCSR,ADSC
reti

Result:

in aL,ADCL ;r0
in aH,ADCH ;r1

; відкидання двох молодших біт із 10 розядів (-> 8 резул.)
clc
ror ah
ror al
clc
ror ah
ror al ; результат залишиться в r18 (r19=0)

;математика
;;****(квадрат і сумування квадратів)
mul al,al ; піднесення в квадрат al (r1;r0 рез)

clr temp
smcvd: ;нагромадження суми квадратів за 32 вимірювання
add ADSL,r0 ;дадаваня мол знач квад.(r0)
adc ADST,r1 ;додавання ст знач квад.(r1)
adc ADSH,temp ;додаваня значення нуль (для врах. переносу)

dec ACT
brne exit


movw rzt:rzl,ADST:ADSL
mov rzh,ADSH

clr ADSL
clr ADST
clr ADSH

ldi temp,32
mov ACT,temp
clr temp

div32:
lsr rzH
ror rzT
ror rzL
inc temp
cpi temp,5
brne div32

movw r3:r2,rzT:rzL ;пересилка суми квадратів за
; 32 виборки до r3:r2
;для добування квадратного кореня

;добування квадратн. кореня, результат в r16 (r17=0)
Sqrt16:
ldi R17,0xc0 ; Rotation mask register
ldi R16,0x40 ; Developing sqrt
clc ; Enter loop with C=0

_sq16_1:
brcs _sq16_2 ; C --> Bit is always 1
cp R3,R16 ; Does value fit?
brcs _sq16_3 ; C --> bit is 0

_sq16_2:
sub R3,R16 ; Adjust argument for next bit
or R16,R17 ; Set bit to 1

_sq16_3:
lsr R17 ; Shift right rotation mask
lsl R2
rol R3 ; Shift left argument, C --> Next sub is MUST
eor R16,R17 ; Shift right test bit in developing sqrt
andi R17,0xfe ; Becomes 0 for last bit
brne _sq16_1 ; Develop 7 bits
brcs _sq16_4 ; C--> Last bit always 1
lsl R2 ; Need bit 7 in C for cpc
cpc R16,R3 ; After this C is last bit

_sq16_4:
adc R16,R17 ; Set last bit if C (R17=0)
;результат знаходиться
;mov r16,r2 ;в end_dat (r16)
out PortD,r16
clr r3
clr r2
exit:
out sreg,r9
reti

Добавлено: Вс дек 06, 2009 15:22:08
sad-angel
Индикация:

.include "m8def.inc"
.def tmpl=r17
.def tmph=r18


.macro outi
ldi r16,@1
out @0,r16
.endmacro

.org 0
rjmp reset
.org OVF0addr
rjmp T0_OF

_symtab:
;таблица истинности декодера
; hgfedcba hgfedcba
.db 0b00111111,0b00000110 ;0,1
.db 0b01011011,0b01001111 ;2,3
.db 0b01100110,0b01101101 ;4,5
.db 0b01111101,0b00000111 ;6,7
.db 0b01111111,0b01101111 ;8,9

reset:
outi ddrb,0xFF; // 1111 1111
outi ddrd,0x7; // 0000 0111

outi TIMSK,1<<TOIE0
outi TCNT0,256-62 ;частота індикації 42 Гц
outi TCCR0,0b00000101
sei


loop:
ldi tmpl,Low(145) ;для примера
ldi tmph,High(145)
rjmp loop

T0_OF:
outi TCNT0,256-62

binBCD3:
clr zh
clr zl ;обнуляем счетчик сотен (потом десятков)

; считаем сотни
_bin100:
subi tmpl,100
sbci tmph,0
brcs _bin100end
inc zl
rjmp _bin100
_bin100end:
_codtosym100:
adiw zl,_symtab*2
lpm r19,z

subi tmpl,-100
clr zl

; считаем десятки
_bin10:
subi tmpl,10
brcs _bin10end
inc zl
rjmp _bin10
_bin10end:
_codtosym10:
adiw zl,_symtab*2
lpm r18,z

subi tmpl,-10

; в остатке - единицы
mov zl,tmpl
adiw zl,_symtab*2
lpm r17,z



sbic portd,0
rjmp d1
sbic portd,1
rjmp d2
sbic portd,2
rjmp d0

d0: ;молодший розряд
cbi portd,2
cbi portd,1
sbi portd,0
out portb,r17
rjmp end

d1:
cbi portd,2
cbi portd,0
sbi portd,1
out portb,r18
rjmp end

d2: ;старший розряд
cbi portd,1
cbi portd,0
sbi portd,2
out portb,r19

end:
reti

Добавлено: Вс дек 06, 2009 17:07:39
GP1
вопрос, а что за компилятор?
я например таких инструкций не знаю:

Код: Выделить всё

outi ddrd,0xff 
outi SPH,High(RamEnd) 
outi SPL,Low(RamEnd)

Добавлено: Вс дек 06, 2009 17:23:29
ARV
GP1 писал(а):вопрос, а что за компилятор?
я например таких инструкций не знаю:

Код: Выделить всё

outi ddrd,0xff 
outi SPH,High(RamEnd) 
outi SPL,Low(RamEnd)
это макросы, они определены прямо в исходнике - ассемблер, судя по всему, обычный AVR-Studio-шный

Добавлено: Вс дек 06, 2009 17:26:08
GP1
позор на мою седую голову :oops:
не заметил.

Добавлено: Вс дек 06, 2009 18:45:49
sad-angel
ARV, Вы на своем сайте описывали "Измерение действующего значения напряжения"

Мне интиресно как у Вас сделано измирения и индикация,я так понял тоже на прерываниях, но у меня они мешають друг другу.

приорирет прерываний такой:

1.Т1
2.Т0
3.АЦП

Добавлено: Вс дек 06, 2009 21:31:03
DrWatson
Смысл прерываний в том, чтобы прервать по какому-то событию основную программу, быстренько обработать это событие и вернуться в основную программу. прерывание на индикацию, если я хоть что-то понял из исходника, у тебя содержит цикл задержки. в прерывании задержки не нужны. если прерывание по таймеру настроено правильно, то без всяких задержек индикация будет работать перебирая разряды с заданными интервалами.
Сделай так:
индикация в прерывании от таймера Т0. по каждому прерыванию высвечивается очередной разряд из буфера, выбирается следующий, выход из прерывания.
запуск преобразования АЦП по прерыванию от таймера Т1. по каждому прерыванию запускается АЦП, выход.
в основном цикле программы она ожидает готовности результата АЦП, обрабатывает очередной отсчет, когда окончательный результат готов - пишет его в буфер индикатора.
И вообще по правильному: попробуй по текстовому описанию составить блок-схему алгоритма, а уже по ней запрограммировать это все не составит большого труда.

Добавлено: Вс дек 06, 2009 21:42:02
sad-angel
DrWatson писал(а):Смысл прерываний в том, чтобы прервать по какому-то событию основную программу, быстренько обработать это событие и вернуться в основную программу. прерывание на индикацию, если я хоть что-то понял из исходника, у тебя содержит цикл задержки. в прерывании задержки не нужны. если прерывание по таймеру настроено правильно, то без всяких задержек индикация будет работать перебирая разряды с заданными интервалами.
Сделай так:
индикация в прерывании от таймера Т0. по каждому прерыванию высвечивается очередной разряд из буфера, выбирается следующий, выход из прерывания.
запуск преобразования АЦП по прерыванию от таймера Т1. по каждому прерыванию запускается АЦП, выход.
в основном цикле программы она ожидает готовности результата АЦП, обрабатывает очередной отсчет, когда окончательный результат готов - пишет его в буфер индикатора.
И вообще по правильному: попробуй по текстовому описанию составить блок-схему алгоритма, а уже по ней запрограммировать это все не составит большого труда.
Нет у меня никаких задержек. Все сделано так как описали Вы.Но неработает,не могу найти грабли.! Дело в том что пооддельности все работает,вместе нет!

Добавлено: Пн дек 07, 2009 22:24:12
DrWatson
Самое интересное, что никто не видел код, который получился после объединения частей измерительной и индикационной. (только не надо постить его целиком в форум - сделай в виде вложенного файла).
Действительно, то что я принял за задержку - преобразование числа в отдельные цифры, верно? но почему это делается в обработчике прерывания, неужто нельзя это сделать в основном цикле, а в обработчике только выставлять уже готовые коды очередных цифр на выводы портов? И вообще эти циклические вычитания можно было бы заменить делением с остатком (памяти они занимают всяко не больше чем вычисление квадратного корня).

Добавлено: Пн дек 07, 2009 22:46:53
sad-angel
DrWatson писал(а):Самое интересное, что никто не видел код, который получился после объединения частей измерительной и индикационной. (только не надо постить его целиком в форум - сделай в виде вложенного файла).
Действительно, то что я принял за задержку - преобразование числа в отдельные цифры, верно? но почему это делается в обработчике прерывания, неужто нельзя это сделать в основном цикле, а в обработчике только выставлять уже готовые коды очередных цифр на выводы портов? И вообще эти циклические вычитания можно было бы заменить делением с остатком (памяти они занимают всяко не больше чем вычисление квадратного корня).
Если что то сделал слишком складно - недостаток опыта,выслушаю все советы! У вложении измирение сделано на прерываниях, а индикация в главном цыкле + схема в Proteus

Добавлено: Пн дек 07, 2009 23:08:54
DrWatson
Если это дипломный проект, то почему-то я не увидел блок-схему алгоритма, или сейчас это не требуется? В коде черт ногу сломит, другой выворотит - вижу что что-то не то, но не могу понять что именно :shock:
В общем мой тебе совет - нарисуй сначала блок-схему алгоритма, разберем ее, а потом рабочий код по ней проще будет изобразить.
Вот, совершенно бесплатно примерная блок-схема алгоритма: