Code: Select all
LIST p=16F877A INCLUDE <P16F877A.inc> X EQU 0x20 Y EQU 0x21 ORG 0x00 BANKSEL TRISD BCF TRISD,7 BSF TRISD,2 BANKSEL PORTD state btfss PORTD,2 GOTO main GOTO ledoff main CALL setval BSF PORTD,7 CALL delay CALL setval BCF PORTD,7 CALL delay btfss PORTD,2 GOTO main GOTO ledoff ledoff BCF PORTD,7 GOTO state delay movlw 0xF9 nop loop addlw 0xFF btfss STATUS,Z goto loop decfsz X goto delay decfsz Y goto delay return setval MOVLW 0xFF MOVWF X MOVLW 0x04 MOVWF Y return END
So here goes my explanation for the delay routine.
It's supposed to turn the LED on for 1 second then turn it off for 1 second and repeat the process.
I have a 4Mhz external clock connected to the pic so I know that it takes 1 micro second for each instruction to be executed. So for me to get a delay of 1 second I would need a total of 1 000 000 instruction cycles.
So firstly I made a routine that takes up 1000 instructions in the delay
2 + (3*248) + 6 = 1000 instruction cycles.
(See the code below)
This was obtained by moving the value 249 in the working register as shown above and decrementing it through the instructions:
Code: Select all
delay movlw 0xF9 nop loop addlw 0xFF btfss STATUS,Z goto loop decfsz X goto delay
Now once the value of X has reached zero then the delay function is ran again Y times where the value of Y is 4 as seen in the setval routine.
So 255*1000*4 = 1 020 000 instruction cycles which is approximately 1 second.
I also tested it with the stopwatch and it also approximates to 1 second as well.
It also works for other delays by scaling the value of Y accordingly.
Now I know I probably could have done this delay way more efficiently, but this is what I came up with at the time. The only thing is i'm not sure if my logic in the calculations of the instruction cycles were correct to make the delay and I probably just got lucky. If someone can verify that my logic is sound then that would bet greatly appreciated.
Thanks in advance guys.