|  
   
 
    | 
    
 
  | 
  
  
 
  Library of Routines
 
 
  
 
   
 
  
  P10  A - Mask        
 
  Go to:
 P10(lower)   
  
 
 
  
 
      
 
 INDEX 
   
 
  
  
  
  
 
   
     
  
    
  
 
   
 
 
  
  The following is a list of sub-routines, ideas and help for the  PIC16F84.  They
  apply to any project using the  PIC16F84. 
  They can be pasted into your program and modified in any way - especially to
  suit the input/output lines.  
  Your program should be created on a template in a text editor such as NotePad,
  using  blankF84.asm as a starting layout.
  Download the template
  as a .zip file and extract it to get blankF84.asm. 
  It provides the correct layout and spacing.  
  The most 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 or fault 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, click on:  Lib-1.asm  
  It will appear in NotePad format and contain all the routines below. You can 
  download the file as a .zip: 
  Lib-1.zip
  (extract it to get Lib-1.asm).
  Copy and Paste them into your program as needed. Additional sub-routines can be found in the
  PIC Programming
  Course. 
   
  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 and RETURNs are
  functional and Labels have not been used elsewhere. 
  The following library is presented in alphabetical order. Using these routines will get you started very quickly and will usually assist you
  with 70% - 90% of a new project.   
  Read through the entire library so you know the content.   
  Simply think of a word or requirement for each part of a program. Go to the
  word and read the comments. Go to the equivalent
  section in NotePad and copy the instructions.  
  Paste them into your program and modify them to suit. Follow through each of
  the lines exactly as the micro will interpret them and make sure you have a
  RETURN to Main, somewhere in the sub-routine. 
  Get each small addition to work 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. 
    
 
 
 
   
 
 
 
  
 Add a
  value to a File
  
 
 
  The PIC12C508A does not have an instruction to add a number to a file. Two 
  instructions are needed to carry out this operation so that the program you 
  are producing is 
  suitable for both a PIC12C508A and PIC16F84.  
  
  
  
  
 
  
          
        
          
                   
              
              Add 
               | 
              
                MOVLW 0CCh 
                ADDWF 0Eh | 
              
                ;Put CCh into W 
                ;CC will be added to the contents of file 
              "E." | 
             
           
            |   
 
 
   
 
 
 
  
 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 files we are talking
  about are the "empty" files from 0C to 4F.  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 1A,0 
                DECFSZ 1A,1 
                INCF 1A,1
                
               | 
              
                ;Copy file 1A into W 
                ;Decrement file 1A 
                ;Increment file 1A
                            | 
             
           
            |   
 
 
  
  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.
  
  
  
   
 
 
 
   
 
 
 
Beep see
Tone 
A Beep is a tone of short duration. 
 
   
 
    
  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. 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 PIC16F84A chip.
     
    But the CALL instruction only works to the first 256 locations (half the memory 
    - called the first page of memory and sometimes referred to as Page0) in 
    a PIC12C508A.  
    To use the CALL instruction in a PIC12C508A, use the first 256 
    locations in the normal way and if any more sub-routines are required, they are accessed as a GOTO. At the end of the sub-routine you 
     place a GOTO to take the microcontroller back to the Main program. Remember 
     this: any sub-routine with a GOTO can only be accessed ONCE from Main. 
    (Alternatively you can place all the instructions of these extra 
    sub-routines in Main.)  If 
     you want to access a sub-routine many times, put it in the first 256 
     locations and use CALL. Always put Tables in the first 256 locations, and 
    remember, a Table cannot extend over the 256 byte boundary,
    for a PIC12C508A. 
     
    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 1A 
                DECFSZ 1A,1 
                GOTO DelA 
                RETURN
                
               | 
               
                 
               
               
               
               
                ;Put
                80h into W 
                ;Copy 80h into file 1A 
                ;Decrement file 1A 
                ;Loop until file 1A 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 PC 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 1A,0 
                CALL Table 
                MOVWF 06
               | 
              
                ;File 1A contains 05. Move it to W 
                ;W will return with display-value for "5" (6D) 
                ;Output display value to 7-segment display
               | 
             
           
         
      
       | 
     
   
    
 
  
    
      
        
          
            
            
              
              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.  
              ;0    format= gfedcba 
              ;1     
              ;2     
              ;3 
              ;4 
              ;5 
              ;6 
              ;7 
              ;8 
              ;9 
               | 
             
           
         
 
 |  
 
      
    
   
 
  
 
   
 
 
 
 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.
   
 
 
    
 
 
   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. See 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. This is called BIT MANIPULATION. This
  prevents touching (and upsetting) other lines.  
  See Toggle to change the direction of a line. 
  
 
 
 
    
 
 
 
 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 1A,0           ;Move one file into W 
 
               
XORWF 1B,0         ;XOR W and 1B 
 
               
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 1A,0           ;Move one file into W 
 
               
SUBWF 1B,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 0CD         ;Move 15h to file 0C 
 
               
MOVLW 15h          ;Put 15h in W 
 
               
SUBWF 0C,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 1E) 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 1E if it is zero,  
	             XORWF 1E,0        
;XOR file 1E with W 
	             BTFSC 03,2         
;Test the zero flag to see if file 1E is zero 
	             GOTO TestA1      
;File 1E is zero
     
  
 
       
       
    The SUBWF
    operation below subtracts the W register (via a process called the 2's
    complement method) from file 1E and the carry flag in the Option register (file 03)
    will be SET if 1E is equal to W or more than W (i.e: 4 or more).  
     
	             MOVLW 04      
        
        ;Put 04 into W for subtract operation 
	             SUBWF 1E,0   
         
        ;Carry will be set if 1E 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 file 1E: 
         If 1E = 0   C = 0  (we have eliminated
    the possibility of zero via the first 4 lines above) 
         If 1E = 1   C = 0  (carry is zero -
    this is not the CARRY BIT it is the SET (1) or clear (0) indicator) 
         If 1E = 2   C = 0 
         If 1E = 3   C = 0 (carry is clear) 
         If 1E = 4   C = 1 (carry is set) 
         If 1E = 5   C = 1 
         If 1E = 6   C = 1 
         If 1E = 7   C = 1 
         If 1E = 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 1E can only be 1, 2, or 3.  
       
       
   
 
 
 
 
 
  
  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.     
                
             Decrement 
            To decrement a file, use the instruction: 
            DECF 1A,1. This puts the new value back into the file. Do not use 
            DECF 1A,0 as the new value goes into W! 
            To decrement a file twice, use: 
            DECF 1A,1 
            DECF 1A,1 
            To halve the value of a file, the contents is shifted right: 
            RRF 1A,1- the file must not have a bit in bit0.  
            A file can be decremented until it is zero:    
            DECFSZ, 1A,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 
            1A,1 and GOTO DelA will take 3uS.    80h loops = 127 
            loops x 3 + 1 loop x 2uS  +  2uS on entry + 1uS on exit 
            = 386uS       
            code 
            
               
               
                 
                   
                    
                       
                         
                          Del  
                           
                          DelA   | 
                        MOVLW 
                          80h 
                          MOVWF 1A 
                          DECFSZ 1A,1 
                          GOTO DelA 
                          RETURN   | 
                        ;Put 
                          80h into W 
                          ;Copy 80h into file 1A 
                          ;Decrement file 1A 
                          ;Loop until file 1A 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.       
            code 
             
               
               
                 
                   
                    
                       
                         
                          Del  
                           
                            | 
                        NOP 
                          DECFSZ 1A,1 
                          GOTO Del 
                          RETURN   | 
                         
                          ;Decrement file 1A 
                          ;Loop until file 1A 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): code 
               
                 
                 
                   
                     
                      
                         
                           
                            Del  
                             
                              | 
                          NOP 
                            DECFSZ 1A,1 
                            GOTO Del 
                            DECFSZ 1B,1 
                            GOTO Del 
                            RETURN   | 
                           
                            ;Decrement file 1A 
                            ;Loop until file 1A is zero 
                              ;Decrement file 
                            1B 
                            ;Loop until file 1B is zero   | 
                         
                       
                     
                   | 
                 
                 
               
              
                260mS Delay 
              
               If you want a 
                delay between 1mS and 256mS, you will need to pre-load file 1B. 
                For each value loaded into file 1B, a delay of 1mS will be produced. 
                A 125mS delay is shown below:      
              code 
               
                 
                 
                   
                     
                      
                         
                           
                            Del  
                             
                            Del1   | 
                          MOVLW 
                            7Dh 
                            MOVLW 1B 
                            NOP 
                            DECFSZ 1A,1 
                            GOTO Del1 
                            DECFSZ 1B,1 
                            GOTO Del1 
                            RETURN   | 
                          ;Load 
                            W with 125 for 125mS delay 
                             
                             
                            ;Decrement file 1A 
                            ;Loop until file 1A is zero 
                            ;Decrement file 1B 
                            ;Loop until file 1B is zero   | 
                         
                       
                     
                   | 
                 
                 
               
              125mS Delay  
               
                
Detect 
                a value  
If a file has been incremented in a sub-routine 
                you may want to know the value it contains.  
                You may want to know its exact value or if it is higher or lower 
                than a certain value.  
                To see if it is an exact value, it is XORed with a known value. 
                See XOR.   
                To detect a particular value, they are XORed together. See 
                XOR.  
                You can also detect a particular value by BIT TESTING. You must 
                make sure that all the numbers being tested can be distinguished 
                by testing a single bit. For example: 1, 2, 4, 8, 10h can be tested 
                via bits 0, 1, 2, 3, 4. But if 3 is included in your requirement, 
                you cannot test a single bit.    
                  
             
            Different 
            To find out if two numbers are different, they are 
            XORed together. See XOR 
               
              
              Divide 
               
              Simple division such as divide by 2 
              can be performed by the RRF instruction. Successive RRF's will divide 
              by 4, 8, sixteen etc. Other divisions are beyond the scope of this 
              course. The number cannot have a bit in bit0, if an accurate 
              division is required. 
                   
                
             Double 
               
            To double the value of the contents of a file, it is 
            shifted LEFT (RLF 1A,1).    The number must be less than 
            80h. (it must not have a bit in location bit7). 
               
              
             EEPROM  
               
              The PIC16F84 has 64 bytes of EEPROM to permanently store data.  
              If you need to store only a few bytes of data for a short period 
              of time, use files that are not required for the running of the 
              program. This information will be lost when power is removed.  
              The 64 bytes of EEPROM requires a special set of instructions to 
              place data into EEPROM. The actual writing time for this data is 
              very long (in computer terms) and can be done in the background, 
              while the main program is executing. A flag will SET when the data 
              has been written and this will allow another byte of data to be 
              entered.  
              Each EEPROM cell can be written about 1 million times.  
               
              Before reading a value in a location in the EEPROM, it must be loaded 
              with a value during "burning."  
              To load the first location in EEPROM with a value, the following 
              instructions are placed in a program.  The EEPROM starts 
              at location 2100h and the term DE means: "define EEPROM." 
              There are 64 EEPROM locations and by following the layout in the 
              second table, any location can be addressed during burning.  
                    
            code 
            
              
             
               
               
                 
                   
                    
                        
                         
                           
                           
                            | 
                         
                        ORG 
                          2100h   
                          DE 00h   
                          END  | 
                         
                         
                        ;Starting 
                          point of EEPROM on 16C84 or 16F84 
                          ;First 
                          EEPROM location initialized to zero  | 
                         
                     
                   
                 | 
               
               
             
             To load more locations in EEPROM, the following layout is used: 
            
               
                 
                   
                    
                       
                         
                           
                           
                            | 
                        ORG 
                          2100h   
                          DE 84h, 16h, 23h, 80h, 0CAh, 32h, 7Bh, 0A2h  
                          DE 34h, 53h, 25h, 02h, 0FFh, 20h, 03h, 04h  
                           
                          END  | 
                          
                        ;Starting 
                          point  
                          ; 
                          ; 
                           
                          ;for up to eight lines   | 
                         
                     
                   
                 | 
               
             
             
             Example: 
              To read the value at the first address in EEPROM, DECrement 
              it and write the new value into the first address, use the following 
              sub-routine:  
            
              
                 
                 
                   
                     
                      
                         
                           
                            Dec  
                             
                              | 
                          MOVLW 
                            00h  
                            MOVWF 09h  
                            CALL EERead 
                            MOVWF 1E   
                            DECF 1E, 0  
                            CALL EEWrite 
                            CALL EERead 
                            RETURN   | 
                           
                            ;EEPROM Address is file 09  
                            ;Get EEPROM value 
                            ;Move to temp file 1E  
                            ;DECrement and put new value into W 
                            ;Write new value to EEPROM  
                            ;Get new EEPROM value 
                              | 
                         
                       
                     
                   | 
                 
                 
               
                
               READ 
                EEPROM: 
               
              The sub-routine to read a value in the EEPROM is shown below. It 
              reads EEPROM data at location specified in EEADR and returns the 
              value in W       
                    
              code
              
                 
                 
                   
                     
                      
                         
                           
                            EERead  
                             
                              | 
                          BSF 
                            Status, RP0   
                            BSF EECON1, RD  BCF Status, RP0  MOVF 08, 
                            W  
                            RETURN   | 
                          ;Go 
                            to Bank 1 
                            ;Set the RD bit  
                            ;Back to bank 0  
                            ;EE Data is file 08.  Put into W  
                              | 
                         
                       
                     
                   | 
                 
                 
               
                
             
            
               WRITE 
                TO EEPROM:   
                The sub-routine to write to EEPROM is shown below.        
                      
              code 
                 
               
                 
                   
                     
                      
                           
                           
                            Delay1 
                             
                            Delay1a 
                             
                             
                             
                             
                             
                             
                            EEWrite 
                             
                              | 
                            
                           
                            MOVLW 13h 
                            MOVWF 1B 
                            NOP 
                            DECFSZ 1A,1 
                            GOTO Delay1a 
                            DECFSZ 1B 
                            GOTO Delay1a 
                            RETLW 00 
                             
                            MOVWF 08 
                            BSF 03,5 
                            BCF 0B,7 
                            BSF 08,2 
                            MOVLW 55h 
                            MOVWF 09 
                            MOVLW 0AAh 
                            MOVWF 09  
                            BSF 08,1 
                            CALL Delay1 
                            BCF 08,2 
                            BSF 0B,7 
                            BCF 03,5 
                            RETURN   | 
                            
                           
                            ;Create a 20mS delay 
                            ;20 loops 
                             
                            ;4uS x 256 loops=approx 1mS 
                             
                             
                             
                            ;Return 
                             
                            ;W to EEData 
                            ;Switch to bank 1 
                            ;Disable interrupts 
                            ;Write Enable bit set 
                            ;Toggle EEPROM Control   
                                         
                            Register bits 
                            ;Toggle EEPROM Control   
                                         
                            Register bits 
                            ;Begin write sequence 
                            ;Call Delay1 
                            ;Disable any further writes 
                            ;Enable Interrupts 
                            ;Back to data bank 0 
                            ;Return  | 
                           
                       
                     
                   | 
                 
               
            
               
               
               
                  
              
                
             
            End 
              of Table 
               
            The end of a table can be detected in 
            two different ways. 
            If a value such as FF is not used in any of the data, it can be used 
            as an End of Table marker. The sub-routine calling the table 
            must look for 0FFh to detect End of Table. 
            
               
                 
                   
                    
                       
                         
                          Table 
                           
                           
                           
                           
                           
                           
                           
                           
                           
                            | 
                         
                          ADDWF 02h,1 
                          RETLW 3Fh 
                          RETLW 06h 
                          RETLW 5Bh 
                          RETLW 4Fh 
                          RETLW 66h 
                          RETLW 6Dh 
                          RETLW 7Dh 
                          RETLW 07h 
                          RETLW 7Fh 
                          RETLW 6Fh 
                          RETLW 0FFh  | 
                         
                          ;Add W to the Program Counter to create a jump.  
                          ;0    format= gfedcba 
                          ;1     
                          ;2     
                          ;3 
                          ;4 
                          ;5 
                          ;6 
                          ;7 
                          ;8 
                          ;9  
                          ;End of table marker  | 
                       
                     
                   
                 | 
               
             
            The other method is to count the number of items in 
              a table and make sure the sub-routine calling the table doe not 
              CALL values beyond this value. 
                
             FSR 
               
            See Indirect Addressing  
            This is a special file called File Select Register. 
            It has the address 04. It is not a file like the other files in the 
            micro but a POINTER FILE and is used in conjunction with another file 
            called INDF.  
            INDF has the address 00.  
            INDF is not actually a file but a robot arm. It grabs the contents 
            (or delivers contents) to a file pointed to by FSR. These are two 
            special files (devices) that allow very powerful (low instruction) 
            programming to be produced.   
            For instance, if FSR is loaded with 0C, it will tell INDF to grab 
            (or deliver) contents to file 0C.  
            To do this, we need the instructions: 
            MOVLW 0C 
            MOVF 04 
            If we now put 8Fh into INDF, the value will actually go into file 
            0C.  
            This is called INDIRECT ADDRESSING.   
               
               
              
             Halt 
             
            Do not use the word "Halt" as a label, the assembler does 
            not like it. Use Loop, Pause, Stop, Wait.  See Loop 
            and Stop. 
               
               
             Halve 
              (Half) 
                
            To halve (half - divide by two) the value of the contents 
            of a file, it is shifted RIGHT (RRF 1A,1).    The number 
            must be an even number (it cannot have a bit in bit0).  
               
              
            Higher 
               To find out if a number is higher than a know value, 
              a comparison is made. See Comparison.  
                
              Increment 
              To increment a file, use the instruction: 
              INCF 1A,1. This puts the new value back into the file. Do not use 
              INCF 1A,0 as the new value goes into W! 
              To add two to a file, it can be incremented twice: 
              INCF 1A,1 
              INCF 1A,1 
              To double the value of a file, the contents is shifted left: 
              RLF 1A,1 
              A file can be incremented until it "rolls over to zero."  
              Normally a file is decremented to zero and a skip occurs when it 
              is zero. But the same effect can be produced by incrementing a file:  
              INCFSZ, 1A,1   
                
               
                  
              
               
             
             
              Indirect 
            Addressing    
            A number of files can be addressed by a sub-routine and the information 
            can be moved into each file or read from each file. The files must 
            be a group. 
            Suppose we have 8 files and need to read the contents and output it 
            to a display.  
            The files are:  21h, 22h, 23h, 24h, 25h, 26h, 27h, and 28h.  
            There are two special files that allow a sub-routine to be created 
            to look at the 8 files and read the contents.  
            They are: INDF and FSR 
            The INDF file is not a real file. It is like a Robot Arm. It reaches 
            down the list of files and picks up the contents or delivers the contents 
            of a file to the programmer. The file it reaches is determined by 
            the value in FSR.  
            FSR is loaded with the address of the file you wish to read or write.  
            This arrangement has an advantage. By loading FSR with a value, you 
            can reach a file and by incrementing FSR, you can reach the next file 
            etc.  
            If you load a value into INDF, you will actually load the value into 
            the file pointed to by FSR. 
            If you read INDF, you will actually read the contents of the file 
            pointed to by FSR.  
            You can consecutively read 8, 10 or 20 files or clear 20 files or 
            load into 20 or more files with a simple looping sub-routine. It's 
            a very powerful feature.  
            The following instructions put a value of 8Fh into file 21h.  
             
            
               
               
                 
                   
                    
                       
                         
                           
                           
                           
                            | 
                        MOVLW 
                          21h 
                          MOVWF 04 
                          MOVLW 8Fh 
                          MOVWF 00   | 
                        ;Load 
                          W with start of 8 files 
                          ;Load 21h into FSR 
                          ;Put 8F into W 
                          ;Put 8Fh into file 21h   | 
                       
                     
                   
                 | 
               
               
             
             
            The animation below shows how the information passes 
              to the files: 
              
              
              Using INDF 
              and FSR  
            
   The following instructions put a value of 8Fh 
              into files 21h, 22h, 23h, 24h, 25h, 26h, 27h and 28h.  
             
               
                 
                   
                    
                       
                         
                           
                           
                           
                           
                           
                          Loop1   | 
                        MOVLW 
                          08 
                          MOVWF 20h 
                          MOVLW 21h 
                          MOVWF 04 
                          MOVLW 8Fh 
                          MOVWF 00 
                          INCF 04 
                          DECFSZ 20h 
                          GOTO Loop1 
                          RETURN   | 
                        ;8 
                          loops of the program 
                          ;File 20h is the decrementing file 
                          ;Load W with start of 8 files 
                          ;Load 21h into FSR 
                          ;Put 8F into W 
                          ;Put 8Fh into file 21h 
                          ;Increment FSR to make INDF go to next file   
                         | 
                       
                     
                   
                 | 
               
             
            The following instructions read files 21h, 22h, 23h, 
              24h, 25h, 26h, 27h and 28h and output to port B (file 06).  
             
               
                 
                   
                    
                       
                         
                           
                           
                           
                           
                          Loop1 
                            | 
                        MOVLW 
                          08 
                          MOVWF 20h 
                          MOVLW 21h 
                          MOVWF 04 
                          MOVF 00,0 
                          MOVWF 06 
                          CALL Delay 
                          INCF 04 
                          DECFSZ 20h 
                          GOTO Loop1 
                          RETURN   | 
                        ;8 
                          loops of the program 
                          ;File 20h is the decrementing file 
                          ;Load W with start of 8 files 
                          ;Load 21h into FSR 
                          ;Copy file 21h (or next file) into W 
                          ;Move W to output Port B 
                          ;Show value on 7-segment display etc 
                          ;Increment FSR to make INDF go to next file   
                         | 
                       
                     
                   
                 | 
               
             
               
             INDF 
               
            See Indirect Addressing 
            and FSR 
            This is a special file called INDirect File.  
            INDF has the address 00.  
            INDF is not actually a file but a robot arm. It grabs the contents 
            (or delivers contents) to a file pointed to by FSR.  
            This is used in an operation called INDIRECT ADDRESSING.   
               
               
              Input 
             
            The files (also called Registers) we are dealing with in this section 
            are actually the TRIS files. These are located in Bank1 and the address 
            is 05 for PortA and 06 for PortB.  
            PortA for a PIC16F84 has 5 lines: RA0, RA1, RA2, RA3, and RA4.  
            PortB for a PIC16F84 has 8 lines: RB0, RB1, RB2, RB3, RB4, RB5, RB6, 
            and RB7. 
            Port A is usually the input lines and Port B is usually the output 
            lines.  
            To make a line INPUT, the corresponding TRIS bit must be "1." 
            To make a line OUTPUT, the corresponding TRIS bit must be "0." 
            To make a line INPUT (or OUTPUT), the instructions must be placed 
            inside  BSF 03,5 and BCF 03,5. 
            For example, to make the lowest line of Port A, an INPUT, the following 
            instructions are needed:  
            
               
                 
                   
                    
                       
                         
                           
                           
                           
                            | 
                         
                          BSF 03,5 
                          MOVLW 01 
                          MOVWF 05 
                          BCF 03,5  | 
                         
                          ;Go to Bank 1 
                          ;Load W with 0000 0001 
                          ;Make RA0 input 
                          ;Go to Bank 0 - the program memory area.  | 
                       
                     
                   
                 | 
               
             
            The other individual lines are: 
               MOVLW 02    ;Load W 
              with 0000 0010  
               MOVWF 05    ;Make 
              RA1 input 
               
              MOVLW 04    ;Load W with 0000 0100  
               MOVWF 05     ;Make 
              RA2 input 
               
              MOVLW 08    ;Load W with 0000 1000  
               MOVWF 05     ;Make 
              RA3 input 
               
              MOVLW 10    ;Load W with 0001 0000  
               MOVWF 05     ;Make 
              RA4 input 
               
              MOVLW 20    ;Load W with 0010 0000   
               MOVWF 05     ;Make 
              RA5 input 
               
              To make more than one line (with a single instruction) an input, 
              the hex values are added. 
               
              MOVLW 0F    ;Load W with 0000 1111  
               MOVWF 05     ;Make 
              RA0, RA1, RA2, RA3 input 
               
              MOVLW 12    ;Load W with 0001   0010  
               MOVWF 05     ;Make 
              RA1, RA4 input 
               
              This also applies to port B: 
               
              MOVLW 33    ;Load W with 0011  0011  
               MOVWF 06     
            ;Make RB0, RB1, RB4, RB5 input 
             
            Port direction can be changed at any time during the running of a 
            program. You must make sure that any input or output devices 
            on the line will not upset the running of the program.   
            In this case it is best to SET or CLEAR a BIT. This involves setting 
            or clearing an individual bit. This prevents touching any other lines. 
            Eg: To make the lowest line of port B an input: 
            
               
                 
                   
                    
                       
                         
                           
                           
                            | 
                         
                          BSF 03,5 
                          BSF 06,0 
                          BCF 03,5  | 
                         
                          ;Go to Bank 1 
                          ;Make RB0 input 
                          ;Go to Bank 0 - the program memory area.  | 
                       
                     
                   
                 | 
               
             
             
            Carry out instructions using the input line, then make the line an 
            output:  
            
               
               
                 
                   
                    
                       
                         
                           
                           
                            | 
                         
                          BSF 03,5 
                          BCF 06,0  
                          BCF 03,5   | 
                         
                          ;Go to Bank 1 
                          ;Make RB0 output 
                          ;Go to Bank 0 - the program memory area.  | 
                       
                     
                   
                 | 
               
               
             
 
  
            
               
              
             
             
             
             
             
            
 
  
             Less than   
            - see Comparison   
              
             Load 
              a file  
              This operation cannot be done directly. A number (a value) is called 
              a LITERAL. It is loaded into W then the value in W is moved to a 
              file. The two instructions are:  
             
               
               
                 
                   
                    
                       
                         
                           
                            | 
                        MOVLW 
                          0FFh 
                          MOVWF 1A  | 
                        ;Load 
                          a value (called a Literal) (00 to 0FFh) into W 
                          ;Move the value in W to a file   | 
                       
                     
                   
                 | 
               
               
             
               
              Look 
              at an Input 
             
            There is no instruction called "look."  If a switch 
            or button is connected to an input line such as the lowest line on 
            Port A, the instruction is: 
            
               
               
                 
                   
                    
                       
                         
                           
                            | 
                        BTFSS 
                          05,0 
                          GOTO No 
                          GOTO Yes   | 
                        ;Is 
                          button pressed? 
                          ;No 
                          ;Yes   | 
                       
                     
                   
                 | 
               
               
             
            This assumes the switch is connected to the positive rail and the 
            input goes HIGH when the button is pressed.  
            This instruction also works for a signal on line 05,0. You must make 
            sure line 05,0 is an INPUT via the SetUp routine.  
            The two instructions after BTFSS 05,0 
            can be "GOTO Yes", "GOTO No"   by changing 
            the first instruction. The decision will depend on the number of instructions 
            for the "Yes" or "No" answer, as the instruction 
            placed directly after BTFSS 05,0 must be a GOTO.  
            
               
                 
                   
                    
                       
                         
                           
                            | 
                        BTFSC 
                          05,0 
                          GOTO Yes 
                          GOTO No   | 
                        ;Is 
                          button pressed? 
                          ;Yes 
                          ;No  | 
                       
                     
                   
                 | 
               
             
              
            
 Loop 
               The action of looping is carried out 
              for a number of reasons. The micro does not have a Halt or Stop 
              feature and must carry out instructions at all times. A loop will 
              hold the micro in one place.  
              To get out, a set of instructions such as "look" is needed 
              inside the loop. These instructions see if a button has been pressed 
              etc. Alternatively, if the watchdog timer is SET, the micro will 
              come out of the loop and go to location 04. The instructions to 
              create a loop are as follows:  
             
               
             Lower 
              
            To find out if a number is lower than a 
            know value, a comparison is made. See Comparison.  
               
               
             Main 
               The Main routine is constantly looped 
              and generally consists of sub-routines that are CALLed.   
              
             
               
                 
                   
                    
                         
                         
                         
                          Main  
                           
                            | 
                        CALL 
                          Switch 
                          CALL Display 
                          CALL Beep 
                          GOTO Main   | 
                           
                         
                           
                           
                          ;Loop Main  | 
                       
                     
                   
                 | 
               
             
             
               
             Mask 
               
              If you want to remove a number of bits from a file, the operation 
              is called MASKING.  
              You can remove the high or low nibble (a nibble is a set of 4 bits) 
              or any other bits. Any number from 0 - 7 can be obtained by masking 
              (removing) bits 3,4,5,6,7, and leaving only bits 0, 1 and 2. 
              To mask (remove) the upper nibble, the number is ANDed with 0F. 
              To mask the lower nibble, the number is ANDed with F0.  (this 
              is written: 0F0h in the program)   
              
              
                 
                  |  
                     number: 
                      W: 
                      answer: 
                    | 
                   
                  1001 0111 
                    1111 0000 
                    1001 0000 | 
                   
               
             
            
               
                 
                   
                    
                       
                         
                           
                           
                            | 
                        MOVLW 
                          97h 
                          MOVWF 1A 
                          MOVLW 0F0h 
                          ANDWF 1A,1  | 
                        ;Put 
                          97h into W 
                          ;Move 97h into file 1A 
                          ;put the "masking value" into W  
                          ;AND 97h with file 1A. The result will be in file 1A.  
                         | 
                       
                     
                   
                 | 
               
             
 
  
            
 
  
            
               
              
             
             
             
             
 
             Go to next page   
     |   
     |