Каким образом из 8 у тебя получается 2???
Все понял!
вот блин, сам же написал "формат BCD"
сделай так:
Код: Выделить всё
ldi tmp,0x18
..................
..................
Код: Выделить всё
ldi tmp,0x18
..................
..................
В чем таки заключается ламерство, уважаемый GP1? Встречал проф. программы в которых основное тело как раз и состоит из обработчика прерывания. И что в этом не так?GP1 писал(а):to MTF
1. Судя по коду ты собираешься выводить индикацию в обработчике прерывания T0_OVF, ИМХО это ламерство, без обид, в прерывании формируй флаг, а всю обработку в основном теле программы.
Код: Выделить всё
.equ OutPort = PORTB
.equ dg1 =pb1
.equ dg2 =pb0
.def tmp = r16
.def tmp1 = r17 ;
;****************
.equ pin_dat =pd5 ;*** оч.рекомендую делать именно так
.equ pin_clk =pd6
.def n =<какой нибудь регистр>
.def flags =r19 ;*** определяем регистр флагов
.equ tind =7 ;*** и назначаем флаг индикации
.dseg ;SRAM memory segment
disp : .byte 2 ; буфер для индикации
.cseg
disp_pos: .db 0xF7 , 0xFB ; позиция для инд
; цифры "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
table_code: .db 0xDB , 0x48 , 0xE3 , 0xEA , 0x78 , 0xBA , 0xBB , 0xC8 , 0xFB , 0xFA
;=================
T0_OVF:
.....
.....
sbr flags,tind ;*** установить бит, время индикации истекло
reti
;================ INDICATION =====
display:
clr n ;
next_digit:
;------------------- OFF IND ------------------------------
in tmp , portb ;чтение portB ;*** здесь все норм.
ori tmp , 0x03 ;в 1 pb0 , pb1
out portb, tmp ;погасить индикатор
;-------------------------------------------------------------
ldi ZL , disp_pos*2 ; загр в Z поз индик
ldi XL , disp ; загр в X буфер disp
mov tmp , n
add ZL , tmp
add XL , tmp
ld tmp , X
;------------- Вывод в 74LS164 --------------------
ldi tmp1 , 8 ;8 bits
LS164:
cbi portd, pin_dat ;*** сбрасываем пин в 0
lsl tmp ;***выдавливаем бит в СY
brcc ls164_0
sbi portd, pin_dat ;*** устанавливаем в 1 если CY=1
ls164_0:
sbi portd, pin_clk ;CLOCK strobe for 74LS164
cbi portd, pin_clk ;CLOCK strobe for 74LS164
dec tmp1 ;dec
brne LS164 ;если не 0 то LS164
;*** в регистре нужный код , приступаем к индикации
;*** сбрасываем флаг индикации
cbi flags , tind
;------------------- ON IND ------------------------------
in tmp , portb ;чтение portB ;*** здесь все норм.
lpm
and tmp , r0 ; pb0 или pb1 disp_pos
out portb, tmp ; включ индикатор
;-------------------------------------------------------------
tind1:
sbis flags,tind ;*** и ждем переполнения счетчика
rjmp tind1
inc n
cpi n , 1
brne next_digit
ret
;=================
Код: Выделить всё
; main prog
.....
.....
; загрузка в буфер disp числа 10
ldi XL , disp ; загр disp в X
ldi tmp , 1
rcall bcd_disp
ldi tmp , 0
rcall bcd_disp
M1:
call display ;***вызов процедуры индикации
.....
.....
rjmp M1
bcd_disp: ; преобр в семисегментный код
push tmp
andi tmp
ldi ZL , table_code*2
add ZL , tmp
lpm
st X+ , r0 ;запись в disp кода
pop tmp
ret
Когда вы выполняете кучу дел в прерывании остальные прерывания как правило нервно курят в сторонке, так и данные какие-либо можно пропустить. В этих случаях "особо дальновидные товарищи" начинаю говорит о вложенных прерываниях и т. п. Вложенные прерывания - штука, может быть и хорошая, но нужна крайне редко, при Вашем же подходе, наверняка решением будут как раз они. В результате стек залезает на область переменных, после чего никто и ничто не спасет программу от былинного облома.IM1 писал(а):Нет, Вы меня не убедили.
Все это условности, ...
тут все дело в системе оценок... когда вы собираетесь починить часы, вы запасаетесь пинцетом и лупой, а 300 лет назад мастер располагал кусачками и молотком... да, были левши и тогда, которые могли починить часы, но согласитесь, что это скорее исключение, чем правило...IM1 писал(а):Нет, Вы меня не убедили.
Все это условности, основной цикл - не основной цикл. Все определяется данной конкретной целесообразностью. Ну например, мы занимаемся динамической индикацией и по приходу прерывания по таймеру выполняем кучу полезных дел. Как то: выводим очередной разряд на индикатор, опрашиваем клавиатуру, проверяем и обрабатываем датчики, работаем с синхронными устройствами типа 1-wire, и т.д. и т.п. и если есть время уходим в Ваш любимый основной цикл. Там можно поработать с чем-нибудь асинхронным типа I2C и т.п. А Вы предлагаете, чтобы в основном цикле я только и занимался проверкой: а как поживает мой любимый флаг (признак), откинулся или еще нет?
Все верно, уважаемый ARV. И не такое можно увидеть, все имеет место быть. Но это все крайние методы программирования, как правило все достаточно насыщено: и тело и прерывания.ARV писал(а): ...я встречал проекты, где динамическая индикация делалась в основном цикле, а измерение и формирование символов для вывода делались по прерываниям... не смотря на то, что это были реально работающие проекты, я никогда не поставил бы их ряд "образцов для подражания". поймите меня верно
Прерывания предполагают уход от выполнения основной программы на обработку событий либо весьма редких, либо мало предсказуемых, например делаем системное время с периодом 1мс, время основного цикла при этом 100 мкс, или ждем принятия байта из ПК (кто сказал вообще что он придет?), либо нажатия кнопки (не собираюсь нажимать в течение ближайшего часа). И что будем в таких ситуациях опрашивать линии, регистры и смотреть за состоянием таймеров? А если во время отработки времени, примем байт и нажмем на кнопку? Что в такой ситуации делать, особенно если "кнопарь" у нас - импульсный сигнал длительностью 4 мкс к примеру и ловим передний фронт?IM1 писал(а):И почему по мнению Meteor_а прерывания - это исключительная ситуация, что в них такого особенного для Вас?
Ну в таком случае, только стрелятьсяMeteor писал(а): ...А если во время отработки времени, примем байт и нажмем на кнопку? Что в такой ситуации делать, особенно если "кнопарь" у нас - импульсный сигнал длительностью 4 мкс к примеру и ловим передний фронт?
я ни на никого не навешиваю ярлыков - лох или гуру... но, скажем, не смотря на принципиальную возможность ездить повсюду задним ходом, все-таки это скорее из разряда извращения, нежели нормальной практики - думаю, не один прохожий повертит пальцем у виска, увидев, как кто-то поехал в магазин задним ходомIM1 писал(а):Но это все крайние методы программирования, как правило все достаточно насыщено: и тело и прерывания.
Просто я не согласен с мнением GP1 (а также Meteor): если не выскакиваешь как ошпареный из прерывания, то ламер. Почему не лох или не осел?И почему по мнению Meteor_а прерывания - это исключительная ситуация, что в них такого особенного для Вас?
P.S. Естественно, что автор должен быть хозяином в своей программе и тем более должен максимально защитить ее от любых (мыслимых и немыслимых) чрезвычайных ситуаций, ИМХО.
Речь совсем не о Вас, уважаемый ARV. Я уже писал, что это мое мнение (ИМХО) на замечание GP1 to MTF, при этом никого не хотел обидеть. И речь GP1 шла о динам. индикации, а это как раз тот случай когда можно чуток проехать задним ходом вместо того, чтобы объезжать целый квартал. Но это опять ИМХО, а так пишите как хотитеARV писал(а):...я ни на никого не навешиваю ярлыков - лох или гуру... но, скажем, не смотря на принципиальную возможность ездить повсюду задним ходом, все-таки это скорее из разряда извращения, нежели нормальной практики - думаю, не один прохожий повертит пальцем у виска, увидев, как кто-то поехал в магазин задним ходомтак и с прерываниями.[/quote"]
GP1 писал(а):to MTF
1. Судя по коду ты собираешься выводить индикацию в обработчике прерывания T0_OVF, ИМХО это ламерство, без обид, в прерывании формируй флаг, а всю обработку в основном теле программы.
Код: Выделить всё
.def fbin = r16
.def fbcdl = r16
.def fbcdh = r17
; main prog
.....
.....
; загрузка в буфер disp числа 10
ldi fbin , 10
rcall bin2bcd8
ldi XL , disp ; загр disp в X
ldi tmp , fbcdL ; 0
rcall bcd_disp
ldi tmp , fbcdH ; 1
rcall bcd_disp
M1:
call display ;***вызов процедуры индикации
.....
.....
rjmp M1
bin2bcd8: ;преобразование в 2 bcd
clr fBCDH
BCD8_1:
subi fbin , 10 ;fBCDH = fBCDH - 1
brcs BCDb8_2 ;if carry not set
inc fBCDH
rjmp BCDb8_1 ; loop again
BCD8_2:
subi fbin , -10 ; result = result + 10
ret ;else return
bcd_disp: ; преобр в семисегментный код
push tmp
andi tmp
ldi ZL , table_code*2
add ZL , tmp
lpm
st X+ , r0 ;запись в disp кода
pop tmp
ret
Код: Выделить всё
.equ OutPort = PORTB
.equ dg1 =pb1
.equ dg2 =pb0
.def tmp = r16
.def tmp1 = r17 ;
;****************
.equ pin_dat =pd5 ;*** оч.рекомендую делать именно так
.equ pin_clk =pd6
.def n =<какой нибудь регистр>
.def flags =r19 ;*** определяем регистр флагов
.equ tind =7 ;*** и назначаем флаг индикации
.dseg ;SRAM memory segment
disp : .byte 2 ; буфер для индикации
.cseg
disp_pos: .db 0xF7 , 0xFB ; позиция для инд
; цифры "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
table_code: .db 0xDB , 0x48 , 0xE3 , 0xEA , 0x78 , 0xBA , 0xBB , 0xC8 , 0xFB , 0xFA
;=================
T0_OVF:
.....
.....
sbr flags,tind ;*** установить бит, время индикации истекло
reti
;================ INDICATION =====
display:
clr n ;
next_digit:
;------------------- OFF IND ------------------------------
in tmp , portb ;чтение portB ;*** здесь все норм.
ori tmp , 0x03 ;в 1 pb0 , pb1
out portb, tmp ;погасить индикатор
;-------------------------------------------------------------
ldi ZL , disp_pos*2 ; загр в Z поз индик
ldi ZH , disp_pos*2
ldi XL , disp ; загр в X буфер disp
ldi XH , disp
mov tmp , n
; clr tmp1
ldi tmp1 , 0
add ZL , tmp
add XL , tmp
adc ZH , tmp1 ;
adc XH , tmp1 ;
ld tmp , X
;------------- Вывод в 74LS164 --------------------
ldi tmp1 , 8 ;8 bits
LS164:
cbi portd, pin_dat ;*** сбрасываем пин в 0
lsl tmp ;***выдавливаем бит в СY
brcc ls164_0
sbi portd, pin_dat ;*** устанавливаем в 1 если CY=1
ls164_0:
sbi portd, pin_clk ;CLOCK strobe for 74LS164
cbi portd, pin_clk ;CLOCK strobe for 74LS164
dec tmp1 ;dec
brne LS164 ;если не 0 то LS164
;*** в регистре нужный код , приступаем к индикации
;*** сбрасываем флаг индикации
cbi flags , tind
;------------------- ON IND ------------------------------
in tmp , portb ;чтение portB ;*** здесь все норм.
lpm
and tmp , r0 ; pb0 или pb1 disp_pos
out portb, tmp ; включ индикатор
;-------------------------------------------------------------
tind1:
sbis flags,tind ;*** и ждем переполнения счетчика
rjmp tind1
inc n
cpi n , 1
brne next_digit
ret
;=================
Код: Выделить всё
.def fbin = r20
.def fbcdl = r20
.def fbcdh = r21
; main prog
.....
.....
; загрузка в буфер disp числа 10
ldi fbin , 10
rcall bin2bcd8
ldi XL , disp ; загр disp в X
ldi XH , disp ; загр disp в X
ldi tmp , fbcdL ; 0
rcall bcd_disp
ldi tmp , fbcdH ; 1
rcall bcd_disp
M1:
call display ;***вызов процедуры индикации
.....
.....
rjmp M1
bin2bcd8: ;преобразование в 2 bcd
clr fBCDH
BCD8_1:
subi fbin , 10 ;fBCDH = fBCDH - 1
brcs BCDb8_2 ;if carry not set
inc fBCDH
rjmp BCDb8_1 ; loop again
BCD8_2:
subi fbin , -10 ; result = result + 10
ret ;else return
bcd_disp: ; преобр в семисегментный код
push tmp
push tmp1
andi tmp
clr tmp1
ldi ZL , table_code*2
ldi ZH , table_code*2
add ZL , tmp
adc ZH , tmp1
lpm
st X+ , r0 ;запись в disp кода
pop tmp
pop tmp1
ret
Код: Выделить всё
;-------------------------------------------------------------
ldi ZL , disp_pos*2 ; загр в Z поз индик
ldi ZH , disp_pos*2
ldi XL , disp ; загр в X буфер disp
ldi XH , disp
mov tmp , n
; clr tmp1
ldi tmp1 , 0
add ZL , tmp
add XL , tmp
adc ZH , tmp1 ;
adc XH , tmp1 ;
ld tmp , X