.equ Digits_P = PORTB .equ Segments_P = PORTD .def Digit_0 = R5 .def Digit_1 = R4 .def Digit_2 = R3 .def Digit_3 = R2 .def PulseEdgeCtrL = R0 .def PulseEdgeCtrH = R1 ; INPUTS .def XL=R16 ; divident .def XH=R17 .def YL=R18 ; divisor .def YH=R19 ; OUTPUTS .def RL=R16 ; remainder .def RH=R17 .def QL=R18 ; quotient .def QH=R19 ; INTERNAL .def QCtrL=R24 .def QCtrH=R25 .macro LOAD_CONST ldi @0, low(@2) ldi @1, high(@2) .endmacro .macro SET_DIGIT mov R16, Digit_@0 rcall DigitTo7segCode ldi R24, 2<<@0 out Digits_P, R24 out Segments_P, R16 rcall DelayInMs .endmacro .cseg ; segment pamięci kodu programu .org 0 ; ustawia pamięć kodu na 0. rjmp timer1_init ; skok po resecie (do programu głównego) .org OC1Aaddr rjmp Timer_isr ; skok do obsługi przerwania timera Timer_isr: ; procedura obsługi przerwania timera ; COUNTER: push R20 push R21 push R22 ldi R20, 1 add PulseEdgeCtrL, R20 clr R20 adc PulseEdgeCtrH, R20 LOAD_CONST R21, R22, 10000 cp PulseEdgeCtrL, R21 brne Counter_End cp PulseEdgeCtrH, R22 brne Counter_End clr PulseEdgeCtrL clr PulseEdgeCtrH Counter_End: rcall NumberToDigits reti ; powrót z procedury obsługi przerwania (reti zamiast ret) Divide: ; X/Y = Q * Y + R push R24 push R25 LOAD_CONST QCtrL, QCtrH, 0 Divide_2: cp XH, YH ;cp porównuje rejestry odejmując je. brcs Divide_2_End ; XH < YH brne Divide_2_Sub ; XH > YH cp XL, YL ; XH = YH brcs Divide_2_End ; XL < YL Divide_2_Sub: sub XL, YL sbc XH, YH adiw QCtrL:QCtrH, 1 rjmp Divide_2 Divide_2_End: mov QH, QCtrH mov QL, QCtrL mov RH, XH mov RL, XL pop R25 pop R24 ret DelayInMs: push R24 push R25 LOAD_CONST R24, R25, 30 Loop_1: rcall DelayOneMs sbiw R24, 1 brne Loop_1 pop R25 pop R24 ret DelayOneMs: push R24 push R25 LOAD_CONST R24, R25, 1750 Loop_2: sbiw R24, 1 brne Loop_2 pop R25 pop R24 ret DigitTo7segCode: push R30 push R31 ldi R30, low(Table<<1) ldi R31, high(Table<<1) add R30,R16 clr R16 adc R31,R16 lpm R16, Z pop R31 pop R30 ret Table: .db 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F NumberToDigits: mov XL, PulseEdgeCtrL mov XH, PulseEdgeCtrH LOAD_CONST YL, YH, 1000 rcall Divide mov Digit_0, QL LOAD_CONST YL, YH, 100 mov XH, RH mov XL, RL rcall Divide mov Digit_1, QL LOAD_CONST YL, YH, 10 mov XH, RH mov XL, RL rcall Divide mov Digit_2, QL mov Digit_3, RL ret Timer1_Init: ; linijka 248 w manualu. .equ Timer_Period = 32150 ldi R16, TCCR1B|(1<