# Creating a delay using TIMER0 module on PIC16F1939

Suppose we are using an external oscilaltor at 8 MHz and needed a voltage high for approximately 1 second at pin RA0. One instruction cycle takes 0.5 $\mu s$. I made a subroutine that takes 25 ms, with the prescaler set to $\frac{1}{256}$.

delay
clrf TMR0
L0
movf TMR0,w
xorlw d'195'
btfss STATUS, Z
goto L0
return


This subroutine( accounting for the call and return instructions that use up two cycles each) takes up 49924 cycles.

So, to create a one second delay, all I need to do is to call this routine 40 times.

   counter equ 0x21
movlw d'40'
movwf counter

bsf LATA, 0
bcf BSR, BSR1
L1

call delay
decfsz counter
goto L1

bsf BSR, BSR1
bcf LATA, 0


However, in MPLAB's logic analyzer I get some strange results, the RA0 pin doesn't even go to HIGH! I am self teaching on this subject, and if you know any good online articles on this subject I would be very happy to read them. Also how can we do this using the INTCON register?

HERE is the datasheet of the pic I am using. The OPTION_ REG is on page 187, and the INTCON regsister is at page 90.

• I think stack overflow is the better selection for this question. – Decapod Oct 30 '16 at 14:55
• @Decapod Why would it be? – Emir Šemšić Oct 30 '16 at 14:58
• Over there is more knowledge. – Decapod Oct 30 '16 at 16:36
• @Decapod Should I just copy the question or perhaps it will be moved by the moderators? – Emir Šemšić Oct 30 '16 at 17:19
• Copy over there and delete here. I do not know at the moment. – Decapod Oct 30 '16 at 17:27

First off, you should read the MPASM user guide to find out about features which can make your code easier to write and follow. Use cblock or res to allocate variables, and skpz in place of btfss STATUS, Z. Wherever possible use #define to give symbolic names to 'magic' numbers, and use the predefined symbols for hardware registers and bits (eg. bsf LATA, RA0 instead of bsf LATA, 0). Put radix dec at the start so you don't have to explicitly specify decimal numbers. I also recommend adding a colon at the end of address labels so they can be easily identified. Give each label a descriptive name, indent opcodes, and comment everything!

I get some strange results, the RA0 pin doesn't even go to HIGH!

This may be because you haven't set the port up properly. At Reset all I/O pins are set to input and (if capable) analog mode. Before using a pin for output you must clear the associated bit in the TRIS register.

The PIC16F1939 has a lot of registers - too many to be addressed linearly - so they are split into banks. TRISA is in Bank 1, so you must select Bank 1 before accessing it. The BANKSEL directive is provided to do this painlessly. So to make RA0 an output you would write:-

  BANKSEL TRISA
BCF     TRISA,RA0   ; RA0 is output
.
.
BANKSEL xxx         ; for next register not in same bank


You have bsf BSR, BSR1 in a couple of places. Normally you should use BANKSEL or MOVLB to manipulate the Bank Select register. Your code would change to Bank 2 if it was previously set to Bank 0, but not if it was any other bank.