Reputation: 8787
I have this code - all LEDs are turn on and off every 1 second (using MPLAB X IDE, assembler, oscillator frequency is 4MHz):
#include <p16f84a.inc>
__CONFIG _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _FOSC_HS
;General registers for delay
CounterA equ h'0c'
CounterB equ h'0d'
CounterC equ h'0e'
org 0
Start:
; select bank 1
bsf STATUS, RP0
; set port B as output
movlw b'00000000'
movwf TRISB
; select bank 0
bcf STATUS, RP0
MainLoop:
; turn on LEDS
movlw b'11111111'
movwf PORTB
call Delay_1s
movlw b'00000000'
movwf PORTB
call Delay_1s
goto MainLoop ;Repeat
Delay_1s:
movlw d'6'
movwf CounterC
movlw d'24'
movwf CounterB
movlw d'168'
movwf CounterA
loop:
decfsz CounterA,1
goto loop
decfsz CounterB,1
goto loop
decfsz CounterC,1
goto loop
return
end
Could someone explain how the Delay_1s
is working? I have tried to multiply 168 * 24 * 6 = 24192 µS, but that is incorrect, I should get 1000000 µS..
EDIT:
I'm getting closer - decfsz CounterA,1
takes 1 µS, and goto loop
takes 2 µS to process. So I think the answer should look like (168 * 3) * (24 * 3) * (6 * 3) = 653184 µS. Of cource I should add 6 µS while setting values to CounterA
, CounterB
and CounterC
. Is there something I missing?
EDIT2:
I've added time valus to each operation below. Do I understand it right?
Delay_1s:
movlw d'6' ; 1µS
movwf CounterC ; 1µS
movlw d'24' ; 1µS
movwf CounterB ; 1µS
movlw d'168' ; 1µS
movwf CounterA ; 1µS
loop:
decfsz CounterA,1 ; 1µS
goto loop ; 2µS (the same while skipping)
decfsz CounterB,1 ; 1µS
goto loop ; 2µS (the same while skipping)
decfsz CounterC,1 ; 1µS
goto loop ; 2µS (the same while skipping)
return ; 1µS ??
Upvotes: 1
Views: 3480
Reputation: 11
I have reviewed this program and found that the number of cycles this routine spends is 1,003,827 which is equivalent to 1.003827 seconds.
I did it by three different methods and I have always got the same result.
Method 1: A formula Method 2: A simulation in Python Method 3: Using the MPLAB simulator, setting breakpoints and observing the cycle counter before and after the function call.
The formula is deduced as follows
Let's first ask ourselves how many cycles a program like the following takes:
loop: decfsz x, f This line runs x times, x-1 times does not jump and 1 time jumps, so the number of cycles is x-1) +2 goto loop This runs x-1 times so cycles are 2 (x-1) in total, cycles are (x-1) + 2 + 2 (x-1) = 3x-1 cycles
Let's consider that x is between 1 and 256 (includes 1 and 256, if x is 0, it equals 256)
So the number of cycles of the complete program is
Counter cycles A The first time when B has its initial value 3A-1 The following times of counter B (B-1) * (3 * 256-1) The next times of counter C (C-1) * 256 * 767 Counter B cycles The first time when C is 6 3B-1 The following times of C (C-1) * 767 Counter C cycles The first and only time 3C-1 The call, the Return and 6 initialization lines 10 ------------------------- total: 3A + 770B + 197 122C-197879
Substituting A for 168, B = 24 and C = 6 gives the value of 1,003,837 better values would have been A = 172 B = 19 C = 6 which produces 999,999 adding a nop in variable initialization would give 1,000,000
Upvotes: 1
Reputation: 11
Sorry that I'm not good at explaining, but I hope this will give you some clue:
Using a 4MHz Xtal OSC
Set OPTION_REG to b'11010100'
'xxxxx100' = 1 instruction :32 uSeconds
32 uSeconds * 250 = 8 milliseconds
8 milliseconds * 125 = 1 second
PORTB (all outs) = B'00000000'
EIGHT_MS EQU 0x10
INIT
BSF STATUS, RP0
MOVLW B'11010100'
MOVWF OPTION_REG
MOVLW B'00000000'
MOVWF TRISB
BCF STATUS, RP0
CLRF PORTB
RETURN
START
L0 CLRF TMR0
L1 MOVF TMR0, W
XORLW .250
BTFSS STATUS, Z
GOTO L1
CLRF TMR0
INCF EIGHT_MS
MOVF EIGHT_MS, W
XORLW .125
BTFSS STATUS, Z
GOTO L1
CALL LIGHT_LED
GOTO L1
LIGHT_LED
...
CALL DELAY
...
RETURN
MAIN
CALL INIT
CALL START
GOTO MAIN
Upvotes: 1