Library of Routines
for PIC12F629
see: Talking Electronics website
A-E   E-P    P-Z

See the article Start Here with PIC12F629 for helpful programming notes and a map of the files.
The following is a list of sub-routines, ideas, and help for the PIC12F629.  They apply to any project using the PIC12F629.
They can be put into your program and modified in any way -  to suit the input/output lines. 
The "Copy and Paste" version of these sub-routines can be found HERE.
Your program should be created on a template in a text editor such as NotePad, using blank12F629.asm  as a starting layout.  It provides the correct layout and spacing. 
An unusual problem you may get is a failure to compile your program due to hidden formatting/characters. 
MPASM will not produce the needed .hex file if any problem exists in a program but it will produce a .lst file containing the faults. If you open .lst and see unusual mistakes, they will be due to hidden formatting characters. Simply retype all the wording around the mistake (in the .asm file) and the program will compile.  Do not use EditPad as it produces hidden characters.
To use the Library of Routines below, go to the NotePad set of "Copy and Paste" Routines  and "Copy and Paste" them into your program in another NotePad, as needed. 
Additional sub-routines can be found in the PIC Programming Course. This is on the subscription section of the website.

Make sure each sub-routine uses a file (a register) with a name (a hex number) that doesn't clash with any other sub-routine you have created.
Make sure CALLs go to a sub-routine that has a RETURN (use retlw  00) to bring the micro back to the correct pace in the program and create Labels that let you know what the sub-routine is doing.
The following library is presented in alphabetical order. Using these sub-routines will get you started very quickly and will assist you with 70% - 90% of a new project.  
Read through the entire library so you know what is possible.  
Simply think of a word or requirement, go to the word and read about it. Many of the sub-routines are also available in the "Copy and Paste" section.
Paste them into your program and modify them to suit. The micro will take each instruction and carry it out. Make sure you have a RETLW 00 that brings the micro back to Main.
Get each sub-section working correctly before adding more instructions. Gradually build up your program and save it as a NEW NAME so it can be recalled if a major problem develops. Do not save it as the previous name as MPASM will sometimes not assemble it (it will think it has already been assembled and  - do nothing!!) and you will wonder why the improvements do not work!!

Add a value to a File
The PIC12F629 does not have a single instruction to add a number to a file. Two instructions are needed to carry out this operation.

Add
MOVLW 0CCh
ADDWF 2Eh,1
;Put CCh into W
;
CC will be added to the contents of file "2E."

Add "bits" to a port - turn on bits or "lines."
This is handy when more than one output line needs to be turned on.




MOVLW 10h
IORWF GPIO,1
;suppose GPIO has bits 0, 1 and 2 HIGH and we need
;   to turn on bit 5
;Put 10h into W - this is bit 5
;
10h will be added to the contents of file "05."

alternately, bit 5 can be SET

   bsf  GPIO,5

If more than one line needs to be made "HIGH" or "LOW," at the same time, you need to use:

   movlw   xxh
   iorwf     GPIO,1

This is necessary as the PIC12F629 will fail to set two or more lines via the following instructions:

   bsf   GPIO, 0
   bsf   GPIO, 2

The author has found the PIC12F629 will fail to set the second line.

Address a File
This means "to act on" or "work with" a file. It can be to "move a value into a file," "increment a file," "decrement a file" or other similar operation.  Only files can be addressed (the instructions in the program cannot be address or altered). The files we are talking about are the "empty" files from 20h to 5F.  None of the program or the values in the tables can be altered. The values in a table can be accessed and copied by a set of instructions covered in CALL Table.
Typical addressing instructions are:


MOVWF 2A,0
DECFSZ 2A,1
INCF 2A,1
INCF 2A,0
;Copy file 2A into W
;Decrement file 2A
;Increment file 2A
;will put the increment of file 2A into W but file 2A will not alter!!

Addressing a Set of Files
A number of files can be used to store temporary data, such as the digits or letters of a score-board. 
This is sometimes called a "scratchpad" or "scratchpad area."  The files should be sequential to make programming easy. 
Suppose we have 8 files and need to address them with a simple sub-routine to output the data to a display. The sub-routine is called INDIRECT ADDRESSING. See Indirect Addressing.

ALL THE FLAGS AND BITS
Here are some of the common flags and bits.
For the other flags, see
PIC12F629 Data Sheet (.pdf  4,926KB)

bank select:
 
bsf 03,5
bcf 03,5
selects bank 1 - this is where the OPTION register is accessed.
selects bank 0 - this is the normal programming area
carry 03,0 Test the carry bit:
btfss  03,0  ;skip if a carry-out of the most significant bit has  
                        occurred.
prescaler
assigned to
WDT
bsf  Option_reg,3
or:
bsf  81h,3
see: Watchdog timer
Option register is in bank 1
prescaler
assigned to
Timer0
bcf  Option_reg,3
or:
bcf  81h,3
Timer0 is in bank 0
GPIO file 05h see input/output port. "Setting the port bits HIGH or LOW"
TRISIO file 85h see "Setting the ports bits input or output"
Status file 03 Contains the carry, bank select and zero flags.
zero flag
zero bit
03,2 zero flag is bit 2 of file 03 (the STATUS file)
1 = The result of an arithmetic or logic operation is zero
0 =
The result of an arithmetic or logic operation is not zero
You can look at bit 2:
btfss 03,2    ; skip if the zero bit is SET

AND - see also Mask
The AND operation will mask any or all the bits in a file. In this way you can "remove" any bit or the upper or lower nibble etc.
The quickest way to perform the operation is as follows:
To mask (remove) the lower nibble, it is ANDed with F0h (written as 0F0h)
To mask (remove) the upper nibble, it is ANDed with 0Fh (can be written 00Fh)

Place the value (say countA) to be operated on, into w:
     movf      countA,w

     andlw    0F0h           ;only the upper 4 bits will be in w.

ARITHMETIC OPERATORS AND  PRECEDENCE
     - see also Pseudo Instructions

OPERATOR Example
$ Current/Return Program Counter goto $ + 3
( Left parenthesis 1 + ( d * 4)
) Right parenthesis (length + 1) * 256
! NOT (logical complement) if !  (a == b)
Negation (2's complement) – 1 * length
~ Complement flags = ~ flags
* Multiply a = b * c
/ Divide a = b / c
% Modulus entry_len = tot_len % 16
+ Add tot_len  = entry_len * 8 + 1
Subtract entry_len = (tot – 1) / 8
<< Left Shift flags = flags << 1
>> Right Shift flags = flags >> 1
>= Greater or equal if entry_idx >= num_entries
> Greater than if entry_idx > num_entries
< Less than if entry_idx < num_entries
<= Less or equal if entry_idx <= num_entries
== Equal to if entry_idx == num_entries
! = Not equal to if entry_idx ! = num_entries
& Bitwise AND flags = flags & ERROR_BIT
^ Bitwise EXclusive OR flags = flags ^ ERROR_BIT
| Bitwise Inclusive OR flags = flags | ERROR_BIT
&& Logical AND if (len == 512) && (b == c)
| | Logical OR if (len == 512) | | (b == c)
= Set equal to entry index = 0
+= Add to, set equal entry index += 1
= Subtract, set equal entry index = 1
*= Multiply, set equal entry index *= entry_length
/= Divide, set equal entry total  /= entry_length
%= Modulus, set equal entry index %= 8
<<= Left shift, set equal flags <<= 3
>>= Right shift, set equal flags >>= 3
&= AND, set equal flags &= ERROR_FLAG
| = Inclusive OR, set equal flags | = ERROR_FLAG
^ = EXclusive OR, set equal flags ^= ERROR_FLAG
++ Increment i ++
Decrement i  

Beep see Tone
A Beep is a tone of short duration. 

Binary to HEX: see Decimal to Binary to HEX

Button see Switch

CALL see also Stack
CALL means to branch to, and return from a subroutine. It does NOT mean GOTO. GOTO means to branch unconditionally and maybe not return to the present routine. CALL means to branch to another sub-routine and RETURN to the next address. Every CALL must have its own RETURN or RETLW 00 to 0FFh statement.
Use only RETLW 00.   Do not use RETURN.
When a CALL instruction is executed, the next address-value is placed on the stack and the micro goes to the location identified in the instruction.
Do not "GOTO" a sub-routine that has a RETURN at the end of it. The micro will not know where to return as the GOTO instruction does not put a return address into memory (the stack).
The CALL instruction works to the full 1024 locations in a PIC12F629 chip.

USING THE CALL INSTRUCTION
The micro will come to CALL Delay in the sub-routine below. It will then advance down the program to Delay and carry out instructions until it reaches RETURN. The micro will then move up the program to the xxxxxxxxx line. 






Delay

DelA
CALL Delay
xxxxxxxxx
- - - - - - - -
- - - - - - - -
- - - - - - - -

MOVLW 80h
MOVWF 2A
DECFSZ 2A,1
GOTO DelA
RETLW 00






;Put 80h into W
;Copy 80h into file 21A
;Decrement file 21A
;Loop until file 2A is zero

CALL Table   see also Table and Output a Table Value 
The instructions CALL Table uses the value in W and adds it to the Program Counter (PC - location 02 (file 02) - the ,1 indicates the value in W will be placed in the Program Counter file) to create a JUMP VALUE to jump down a Table and pick up a value. The instruction beside each value in a table places the value in W and makes the micro return to the instruction after CALL Table. The next instruction should be to move the value from W to a file.
Call MOVF 2A,0
CALL Table
MOVWF 2C
;File 2A contains 05. Move it to W
;W will return with 6D
;Move 6D to file 2C
 

Table








ADDWF 02h,1
RETLW 3Fh
RETLW 06h
RETLW 5Bh
RETLW 4Fh
RETLW 66h
RETLW 6Dh
RETLW 7Dh
RETLW 07h
RETLW 7Fh
RETLW 6Fh
;Add W to the Program Counter to create a jump. 
 

Carry  - see also ROTATE for one of the operations involving CARRY.
The carry bit is located in the STATUS register (file 03) and is bit 0. 
It is cleared by the instruction: 
BCF 03,0 - clear bit0 in file 03
Carry is SET by the instruction:
BSF 03,0   

To test the carry:
BTFSS 03,0
GOTO AAA     ;The micro will go HERE if the carry is NOT set.
GOTO BBB     ;The micro will go HERE if the carry is SET.

The carry is also used when a file is rotated left or right.
When a file is rotated left, the MSB (most significant bit (bit 7) is passed into the carry and the carry-bit is passed into the file as bit 0. If you don't want the "carry bi" to affect the outcome of the operation it must be cleared before-hand, thus:
       bcf      03,0


CBLOCK
This is a directive used for defining files that will be reserved for an application. The format of  CBLOCK is:

cblock 0x20	;define the start of the files. The first "file" or "register" for a 12F629 is 20h
Lowbyte		;this will be file 20h
Medbyte		;this will be file 21h
Hibyte		;this will be file 22h etc  etc  etc
endc

This method of declaring variables is quite good, but  macros cannot take advantage of it.

The alternative to cblock is:
Lowbyte    equ   20h
Medbyte	equ   21h
Hibyte       equ   22h	

cblock can use other files, starting at say 4Ch:  The 3 files d1, d2 and d3 are files for a 
delay routine and are files 4Ch, 4Dh and 4Eh.

cblock 0x4C
d1
d2
d3
endc


Another method of defining files is:
 

org   20h

save     ds   1
flag       ds   2
count    ds   1
csave   ds    1
temp    ds    2
ontime  ds   1
oftime   ds   1
timer    ds    3
freq       ds    2
mode    ds   1
rate      ds   1
hi         ds   1
low       ds   1
delay    ds   3
 
The compiler will allow one file (20h) for "save" and two files for "flag."    timer will be given 3 files. 

When writing the program, you write the instruction such as   incf    flag,1  for the first flag file and 
btfss   flag+1   for the second flag file. 


Change Direction 
The direction of an input/output line (or a whole port) can be changed at any time during the running of a program.  The file we are loading or setting or clearing is file 85. It is in Bank 1. This file is called TRISIO.



 
BSF 03,5
BSF TRISIO,1
BCF 03,5
;Go to Bank 1
;Make GP1 input
;Go to Bank 0 - the program memory area.




 
BSF 03,5
BCF TRISIO,1
BCF 03,5
;Go to Bank 1
;Make GP1 output
;Go to Bank 0 - the program memory area.

See also: SetUp for setting up the Input/Output lines. See Input for the instruction(s) to make a line Input. See Output to make a line Output. Lines are changed by setting or clearing bits of the TRISIO register. This is called BIT MANIPULATION. This prevents touching (and upsetting) other lines.

See Toggle to change the STATE of a line (from HIGH to LOW or LOW to HIGH). 

Compare
To compare two values, you can use XOR.

To compare two numbers, they are XORed together and if they are the same, the Z flag will be set. Take two numbers: 

number  =  7A    =    0111 1010 
W         =  7A    =     0111 1010 

Starting at the right hand end, ask yourself the question, "Is one OR the other a 1?" The answer is no. The next column. "Is one number OR the other a 1?" No BOTH the numbers are 1! so that's why the answer is NO. In this way every column has the answer NO, when both numbers match. 
When all the answers are Zero, the flag rises! to say the result is ZERO. In other words it is SET. 
To find the zero flag look in the STATUS register, bit 2, i.e. File 03,2. 

e.g: To compare two files: 

                MOVF 2A,0           ;Move one file into W 
                XORWF 2B,0         ;XOR W and 2B 
                BTFSS 03,2           ;Test Z flag  If Z flag is SET (ie 1) the two files are the SAME! 

The same thing can be done by using the subtract operation:

                MOVF 2A,0           ;Move one file into W 
                SUBWF 2B,0         ;Subtract W from 1B 
                BTFSS 03,2           ;Test Z flag  If Z flag is SET (ie 1) the two files are the SAME! 

Same:
Z flag is SET (ie 1) when the two files are the SAME!

Comparison
The contents of a file can be compared with the contents of the working register (W) to determine their relative magnitudes. This is done by subtracting the contents of W from the selected file. By testing the Carry and Zero flags, 4 results can be obtained: 
E.g: 

                MOVLW 22h          ;Put 22h in W 
                MOVWF 3C           ;Move 22h to file 3C 
                MOVLW 15h          ;Put 15h in W 
                SUBWF 3C,1         ;Subtract 15h from 22h 
                BTFSS 03,2           ;Test Zero flag 

OR 

                BTFSS 03,0           ;Test Carry flag 

Zero flag is SET if W = File value = Match 
Zero flag is CLEAR if no Match 
Carry flag is SET if a borrow did not occur (W is less than or equal to file value) 
Carry flag is CLEAR if a borrow occurred (W is greater than file value) 


(Put a value into W and perform SUBWF). Test Carry:


More than: Carry flag is CLEAR if W is greater than file value.

Less than: Carry flag is SET if W is less than or equal to file value.

Suppose a file (file 3E) is incremented to 8 such as in the Logic Probe with Pulser. We need to know if the file is 1, 2 or 3. The first thing to do is eliminate the possibility of zero. 

TestA    MOVLW 00h          ;Eliminate file 3E if it is zero, 
             XORWF 3E,0         ;XOR file 3E with W
             BTFSC 03,2          ;Test the zero flag to see if file 3E is zero
             GOTO TestA1       ;File 3E is zero

The SUBWF operation below subtracts the W register (via a process called the 2's complement method) from file 3E and the carry flag in the Option register (file 03) will be SET if 3E is equal to W or more than W (i.e: 4 or more). 

             MOVLW 04            ;Put 04 into W for subtract operation
             SUBWF 3E,0          ;Carry will be set if 3E is = or more than 4
             BTFSS 03,0            ;Test the carry flag 
             GOTO Hi                ;Go to another sub-routine such as "Hi"

Here is the outcome for all the possibilities for file3E:
     If 3E = 0   C = 0  (we have eliminated the possibility of zero via the first 4 lines above)
     If 3E = 1   C = 0  (carry is zero - this is not the CARRY BIT it is the SET (1) or clear (0) indicator)
     If 3E = 2   C = 0
     If 3E = 3   C = 0 (carry is clear)
     If 3E = 4   C = 1 (carry is set)
     If 3E = 5   C = 1
     If 3E = 6   C = 1
     If 3E = 7   C = 1
     If 3E = 8   C = 1

The carry bit in the Option file is bit 0.  Therefore we test bit 0 of file 03:
       BTFSS 03,0
The result in 3E can only be 1, 2, or 3. 

 Config  - configuration
The configuration word is located at address 2007h and is only accessed during programming.
'__CONFIG' directive is used to embed configuration data within .asm file.
Note the double underbar at the front of "config."
Some of the configuration settings:
_CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _LVP_OFF
Each setting has a single underbar and a "&" sign, with a single space between "&" sign.

Here is an example of how the configuration word is created:

; ----- Configuration Word -----------
; Bandgap                 11                 Highest voltage (00 lowest voltage) for BOD and POR
; Unimplemented           000              Read as '0'
; Data code protection        1             CPD disabled (0=enabled)
; Code protection                 1            CP disabled (0 = program memory code protection enabled)
; Brown-out detect                 1           BOD enabled (0=BOD disabled)
; GP3/MCLRE                         0          digital I/O, MCLR internally tied to Vdd
; Power-up timer                        1         PWRT disabled (0=PWRT enabled)
; Watchdog timer                        0        WDT disabled (0=WDT disabled)
; Oscillator                                   100     INTOSC I/O on GP4 & GP5
 
 __config                b'11000111010100'

Oscillator: 
000  = LP oscillator Low power crystal on GP4 and GP5
001  = XT oscillator  Crystal/resonator on GP4 and GP5
010  = HS oscillator  High Speed
crystal/resonator on GP4 and GP5
011  = EC: I/O function on GP4  ClkIn on GP5

100  = INTOSC oscillator
I/O on GP4 & GP5
101  = INTOSC ClkOut on GP4  I/O on GP5
110  = RC oscillator I/O function on GP4  RC on GP5
111  = RC oscillator ClkOut on GP4  RC on GP5


Count
If you want to count the number of pulses from a push-button or switch, the easiest way is to increment a file. A file will hold up to 255. The result is stored as a hexadecimal number from 01 to FF.
If you want to count to three, pre-load a file with 3 and decrement it and detect zero.


 


 

Data Table - see DT below
 


 

Debounce a Button (Switch)
See Switch and Poll

Debug
This is not a term used in creating a program in PIC language, however we have two suggestions for finding a "bug" or problem in a program. 
1. Go back to your previously saved version and note the differences in the programs. Try to visually detect the fault. 
2. "Home-in" on the faulty section and see how far the micro is getting through by inserting a Wait instruction. (See Wait)   A LED on an output line will illuminate to indicate the micro has reached the instruction.  
  



 

Decimal to Binary to HEX:
                     
0 0000 0000 0 16 0001 0000 10h 32 0010 0000 20h
1 0000 0001 1 17 0001 0001 11h 33 0010 0001 21h
2 0000 0010 2 18 0001 0010 12h 34 0010 0010 22h
3 0000 0011 3 19 0001 0011 13h 35 0010 00110 23h
4 0000 0100 4 20 0001 0100 14h 36 0010 0100 24h
5 0000 0100 5 21 0001 0101 15h 37 0010 0101 25h
6 0000 0110 6 22 0001 0110 16h 38 0010 0110 26h
7 0000 0111 7 23 0001 0111 17h 39 0010 0111 27h
8 0000 1000 8 24 0001 1000 18h 40 0010 1000 28h
9 0000 1001 9 25 0001 1001 19h 41 0010 1001 29h
10 0000 1010 A 26 0001 1010 1Ah 42 0010 0010 2Ah
11 0000 1011 B 27 0001 1011 1Bh 43 0010 10110 2Bh
12 0000 1100 C 28 0001 1100 1Ch 44 0010 1100 2Ch
13 0000 1101 D 29 0001 1101 1Dh 45 0010 1101 2Dh
14 0000 1110 E 30 0001 1110 1Eh 46 0010 1110 2Eh
15 0000 1111 F 31 0001 1111 1Fh 47 0010 1111 2Fh
                   

 
                     
48 0011 0000 30h 64 0100 0000 40h 80 0101 0000 50h
49 0011 0001 31h 65 0100 0001 41h 81 0101 0001 51h
50 0011 0010 32h 66 0100 0010 42h 82 0101 0010 52h
51 0011 0011 33h 67 0100 0011 43h 83 0101 00110 53h
52 0011 0100 34h 68 0100 0100 44h 84 0101 0100 54h
53 0011 0100 35h 69 0100 0101 45h 85 0101 0101 55h
54 0011 0110 36h 70 0100 0110 46h 86 0101 0110 56h
55 0011 0111 37h 71 0100 0111 47h 87 0101 0111 57h
56 0011 1000 38h 72 0100 1000 48h 88 0101 1000 58h
57 0011 1001 39h 73 0100 1001 49h 89 0101 1001 59h
58 0011 1010 3Ah 74 0100 1010 4Ah 90 0101 0010 5Ah
59 0011 1011 3Bh 75 0100 1011 4Bh 91 0101 10110 5Bh
60 0011 1100 3Ch 76 0100 1100 4Ch 92 0101 1100 5Ch
61 0011 1101 3Dh 77 0100 1101 4Dh 93 0101 1101 5Dh
62 0011 1110 3Eh 78 0100 1110 4Eh 94 0101 1110 5Eh
63 0011 1111 3Fh 79 0100 1111 4Fh 95 0101 1111 5Fh
                   


 
                     
96 0101 0000 60h 112 0111 0000 70h 128 1000 0000 80h
97 0101 0001 61h 113 0111 0001 71h 129 1000 0001 81h
98 0101 0010 62h 114 0111 0010 72h 130 1000 0010 82h
99 0101 0011 63h 115 0111 0011 73h 131 1000 00110 83h
100 0101 0100 64h 116 0111 0100 74h 132 1000 0100 84h
101 0101 0100 65h 117 0111 0101 75h 133 10000 0101 85h
102 0101 0110 66h 118 0111 0110 76h 134 1000 0110 86h
103 0101 0111 67h 119 0111 0111 77h 135 1000 0111 87h
104 0101 1000 68h 120 0111 1000 78h 136 1000 1000 88h
105 0101 1001 69h 121 0111 1001 79h 137 1000 1001 89h
106 0101 1010 6Ah 122 0111 1010 7Ah 138 1000 0010 8Ah
107 0101 1011 6Bh 123 0111 1011 7Bh 139 1000 10110 8Bh
108 0101 1100 6Ch 124 0111 1100 7Ch 140 1000 1100 8Ch
109 0101 1101 6Dh 125 0111 1101 7Dh 141 1000 1101 8Dh
110 0101 1110 6Eh 126 0111 1110 7Eh 142 1000 1110 2Eh
111 0101 1111 6Fh 127 0111 1111 1Fh 143 1000 1111 8Fh
                   


 
                     
144 1001 0000 90h 160 1010 0000 A0h 176 1011 0000 B0h
145 1001 0001 91h 161 1010 0001 A1h 177 1011 0001 B1h
146 1001 0010 92h 162 1010 0010 A2h 178 1011 0010 B2h
147 1001 0011 93h 163 10100011 A3h 179 1011 00110 B3h
148 1001 0100 94h 164 1010 0100 A4h 180 1011 0100 B4h
149 1001 0100 95h 165 1010 0101 A5h 181 11011 0101 B5h
150 1001 0110 96h 166 1010 0110 A6h 182 1011 0110 B6h
151 1001 0111 97h 167 1010 0111 A7h 183 1011 0111 B7h
152 1001 1000 98h 168 1010 1000 A8h 184 1011 1000 B8h
153 1001 1001 99h 169 1010 1001 A9h 185 1011 1001 B9h
154 1001 1010 9Ah 170 1010 1010 AAh 186 1011 0010 BAh
155 1001 1011 9Bh 171 1010 1011 ABh 187 1011 10110 BBh
156 1001 1100 9Ch 172 1010 1100 7Ch 188 1011 1100 BCh
157 1001 1101 9Dh 173 1010 1101 ADh 189 1011 1101 8Dh
158 1001 1110 9Eh 174 1010 1110 AEh 190 1011 1110 BEh
159 1001 1111 9Fh 175 1010 1111 AFh 191 1011 1111 BFh
                   


 
                     
192 1100 0000 C0h 208 1101 0000 D0h 224 1110 0000 E0h
193 1100 0001 C1h 209 1101 0001 D1h 225 1110 0001 E1h
194 1100 0010 C2h 210 1101 0010 D2h 226 1110 0010 E2h
195 1100 0011 C3h 211 1101 0011 D3h 227 1110 00110 E3h
196 1100 0100 64h 212 1101 0100 D4h 228 1110 0100 E4h
197 1100 0100 C5h 213 1101 0101 D5h 229 11100 0101 E5h
198 1100 0110 C6h 214 1101 0110 D6h 230 1110 0110 E6h
199 1100 0111 C7h 215 1101 0111 D7h 231 1110 0111 E7h
200 1100 1000 C8h 216 1101 1000 D8h 232 1110 1000 E8h
201 1100 1001 69h 217 1101 1001 D9h 233 1110 1001 E9h
202 1100 1010 6Ah 218 1101 1010 DAh 234 1110 0010 EAh
203 1100 1011 6Bh 219 1101 1011 DBh 235 1110 10110 EBh
204 1100 1100 CCh 220 1101 1100 DCh 236 1110 1100 ECh
205 1100 1101 CDh 221 1101 1101 7Dh 237 11100 1101 EDh
206 1100 1110 CEh 222 1101 1110 DEh 238 1110 1110 2Eh
207 1100 1111 CFh 223 1101 1111 DFh 239 1110 1111 EFh
                   

 

     
240 1111 0000 F0h
241 1111 0001 F1h
242 1111 0010 F2h
243 1111 0011 F3h
244 1111 0100 F4h
245 1111 0100 F5h
246 1111 0110 F6h
247 1111 0111 F7h
238 1111 1000 F8h
249 1111 1001 F9h
250 1111 1010 FAh
251 1111 1011 FBh
242 1111 1100 FCh
243 1111 1101 FDh
254 1111 1110 FEh
255 1111 1111 FFh
     

 

Decrement
To decrement a file, use the instruction: DECF 3A,1. This puts the new value back into the file. Do not use DECF 3A,0 as the new value goes into W!
To decrement a file twice, use:
DECF 3A,1
DECF 3A,1
To halve the value of a file, the contents is shifted right:
RRF 3A,1- the file must not have a bit in bit0. 
A file can be decremented until it is zero:   
DECFSZ, 3A,1   

Delay
A delay sub-routine is needed for almost every program. One of the main purposes is to slow down the execution of a program to allow displays to be viewed and tones to be produced. 
The shortest delay is NOP. This is a "do nothing" instruction that takes 1 micro-second. 
You will need one million "NOP's" to produce a 1 second delay. 
This is impractical as the program space will only allow about 1,000 instructions. 
The answer is to create a loop. If a file is loaded with a value and decremented, it will create a short delay. The two instructions: DECFSZ 3A,1 and GOTO DelA will take 3uS.    80h loops = 127 loops x 3 + 1 loop x 2uS  +  2uS on entry + 1uS on exit = 386uS      
Del

DelA
MOVLW 80h
MOVWF 3A
DECFSZ 3A,1
GOTO DelA
RETLW 00
;Put 80h into W
;Copy 80h into file 1A
;Decrement file 3A
;Loop until file 3A is zero

A simpler delay routine below decrements a file with 256 loops. Each loop is 4uS and the result is slightly more than 1,000uS = 1mS. The routine exits with 00h in the file. On the second execution, the routine performs 256 loops - the file does not have to be pre-loaded. 
The longest delay (such as the one below) using a single file is approx 1mS.      
Del

NOP
DECFSZ 3A,1
GOTO Del
RETLW 00

;Decrement file 3A
;Loop until file 3A is zero

1mS delay

NESTED DELAYS
To produce delays longer than 1mS, two or more files are needed. Each file is placed around the previous to get a multiplying effect. The inner delay produces 256 loops, the output file produces 256 loops of the inner file. This results in 256 x 256 loops = 256mS.
The simplest delay decrements a file to zero. At the end of an execution, a delay contains 00 and this produces the longest delay, the next time it is used. 
This means a file does not have to be pre-loaded. 
The following is a two-file nested delay. The delay time is approx 260mS (say 1/4Sec):
 
Del

NOP
DECFSZ 3A,1
GOTO Del
DECFSZ 3B,1
GOTO Del
RETLW 00

;Decrement file 3A
;Loop until file 3A is zero
;Decrement file 3B
;Loop until file 3B is zero

260mS Delay

If you want a delay between 1mS and 256mS, you will need to pre-load file 3B. For each value loaded into file 3B, a delay of 1mS will be produced. A 125mS delay is shown below: