Talking Electronics PIC Theory

LIBRARY
OF
ROUTINES
Program Space to Sleep


PROGRAM SPACE 
The '508A has 511 address locations for program or data. These locations are 12 bits wide and each line of code takes up one address location. 
To access one byte of data, it must be added to the instruction RETLW and placed in a table. Because of this requirement, one byte of data also occupies one address location. The byte of data contains 8 bits. See Program Layout. 

PROGRAM TEMPLATE 
To make programming easy, we have made a Program Template. It contains a layout for a program that you "add to" when creating a program. Before using Program Template, (PTplate1), copy it as PTplate2 etc so that PTplate is not destroyed. See Equates for more details. 

PSEUDO'508A 
PSEUDO'508A is the name given to a mini PC board carrying a PIC16F84 chip that can be programmed like a PIC12C508A microcontroller. The board has an 8 pins plug on a flying lead that can be plugged into an 8-pin socket on a development module such as '508A Proto-1 Module or '508A Express-1 Module. It has an on-board 4MHz crystal. See '508A Proto-1at end of chapter. 

PULL-DOWN RESISTOR 
A resistor connected between an in/out pin and 0v (ground). The resistor produces a default (0) on the pin when the pin is read as an input. 

PULL-UP RESISTOR 
A resistor connected between an in/out pin and 5v. The resistor produces a default HIGH (1) on the pin when the pin is read as an input. 

PWM 
Pulse-Width-Modulation can be used to vary the speed of a motor or dim a lamp without overheating the driver transistor. When a transistor is switched on fully or completely off, it dissipates very little 
energy and thus it does not heat up very much. If a transistor is half-turned-on, it dissipates approx the same amount of energy as the load it is driving. If a transistor is turned on fully for a very short period of time then switched off for a long period time, the average energy delivered to the load will be small but the transistor will not heat up. If the duty-cycle is adjusted to say 50:50, the energy delivered will be half the fully turned on amount but the transistor will still remain cold. This is the principle of PWM. 

PRODUCING AN ANALOGUE SIGNAL using PWM 
PWM can also be passed through a resistor and capacitor network as shown in the diagram to produce an analogue voltage from a digital output. 
There are two ways of delivering a PWM signal. The micro can spend all its time delivering a HIGH then a LOW or it can deliver a HIGH then go away and do other things then return and deliver a LOW. This is multi-tasking and allows the program to respond to a signal from a button to tell when to cease outputting etc. 

RAM - Random Access Memory 
The '508A does not have any RAM however any unused files can be used to store information. Files used as RAM should be consecutive. For instance files 07 to 15h could be used for RAM and files 16h to 1F used for programming. This gives fifteen files for RAM and they can be accessed via the INDF and FSR registers as shown below. 
In setUp, put the start of the files for use as RAM into FSR via W. 

SetUp      MOVLW 07h        ;Put start of files into W 
               MOVWF 04,1       ;07h into FSR - pointer 

As each new piece of data is received from input lines GP0, GP1, GP2, GP3, GP4, and GP5 it is placed in the next available file. 

               MOVF 04,0 
               XORLW 15h 
               BTFSC 03,2 
               GOTO Down 
               MOVWF 00          ;Put W into what FSR sees 
               INCF 04,1             ;Increment pointer 
Down        ------------ 
                ------------ 

To read files 07 to 15h, use SetUp above to put 07h into FSR and call the following routine: 

               MOVF 04,0 
               XORLW 15h 
               BTFSC 03,2 
               GOTO Down 
               MOVF 00,0            ;Put what FSR sees into W 
               INCF 04,1              ;Increment pointer 
Down        ------------ 
                ------------ 

The first pass of the routine will put the value in file 07h into W. Remember, input GP0 to GP5 is only 6 lines (6-bits) and will produce values from 00 to 3F (00 to sixty-three). The second pass will put the value in 08h into W etc. 

RANDOM NUMBERS 
Computers find it very difficult to produce random numbers. Some of the ways to produce a random number are: 
1. Increment a file during the execution of a routine where a button is pressed. This introduces a human factor and when the button is pressed, the file is read. 
This produces a number from 0 to 256 (00 to FF). The file can be ANDed with 0F to produce a number from 0 to fifteen or with 07 etc to limit the number of possibilities. These values can then be used for a "look-up" table for a display etc. 
If zero is not required, a table can be used or the following instructions will increment random file 1F, if it is zero: 

              MOVLW 00 
              XORWF 1F,1 
              BTFSS 03,2 
              GOTO Below 
              INCF 1F,1 
Below      --------------- 
               --------------- 

2. Create a table of any length and increment down the table. At the end of the table the "jump file" starts at the beginning again. 
3. Use a Random Number generator routine. 

Main       ------- 
              ------- 
              CALL RanNum 
               ------- 

RanNum   SWAPF 1C,0            ;swap nibbles. Put in W 
                ANDLW 0F0h            ;AND 1C with F0 
                ADDWF 1C,1            ;ADD W and 1C 
                MOVLW 0A3h           ;Put A3 into W 
                ADDWF 1C,1             ;ADD W and 1C 
                RETLW 00h               ;RETURN 

File 1C is used to store the random number. It can start with zero and will contain 255 different values. 

READ 
There is no PIC instruction to read a value of data at an address. 
Data has to be put in a table and each byte needs a RETLW instruction. 
For details on producing a table: see Relative addressing, Table, Write. 

READ AN INPUT - see also INPUT 
To read all the input lines at once: 

                   MOVF 06,0 

This puts GP0 to GP5 into W (only 6 bits of information). 
To read an input line (called an input bit - say GP3: 

                    BTFSS 06,3 
                    GOTO 1 
                    GOTO 2 

If GP3 is HIGH, the program will skip the GOTO 1 instruction and carry out the GOTO 2 instruction. 
To read 2 lines at the same time: 
To see if say GP0, GP3 are BOTH high: 

                     MOVLW 09          ;0000 1001 
                     ANDWF 06,0 
                     BTFSS 03,2         ;Test Z flag 
                     GOTO 1 
                     GOTO 2 

If both lines HIGH = Match, program will skip GOTO 1 and execute GOTO 2. 

READ A PORT 
- See also INPUT 

To read a Port (an input) the bit (the line - such as GP3) must be set as an input bit (line). Put the following 2 instructions in SetUp: 

To make GP3 input (for '508A): 

                     MOVLW 08        ;0000 1000 
                     TRIS 06             ;Make GP3 input 

To make GP3 input (for Pseudo '508): 

                     BSF 03,5              ;Select Page1 
                     MOVLW 08           ;Make GP3 input 
                     MOVWF 06,1        ;Load TRISB file 
                     BCF 03,5              ;Select Page0 

To read GP3: 
                     BTFSC 06,3 

The above instruction "reads" or tests bit 3 of the input port and skips the next instruction if it is clear. 

RE-BURNING '508A's 
The '508A chip is a one-time programmable device however there are ways to use the unused portion of the PROGRAM SPACE. 
1. Read the chip and count the number of bytes in the program. Add this number of NOP's to the front of your new program and re-burn the chip. The program will be part-way down the program-space but 
this will not affect the running. 
If a table is included in the program, make sure the table does not go over the first-page boundary (0FFh) when the chip is re-burnt. 
If an instruction in a sub-routine needs to be changed, place the sub-routine at the end of the program and ACCURATELY replace each instruction of the sub-routine with a NOP. 

2. You can "NOP out" an instruction or data value (such as RETLW 07h), provided the instruction or value does not affect the operation of the program. 
3. You can "burn down" any location to a lower value providing the bit(s) are being changed from "1" to "0." 
For example 0F (0000 1111) can be burnt down to any lower value but 08 (0000 1000) can only be burnt down to 00. 

REGISTER PAIRS 
Some microcontrollers have a feature where registers (files) can be combined so that you can increment the lower file and when it reaches FF, the higher file is automatically incremented. In this way numbers up to FF x FF = 65,536 can be counted. This feature can be created in six program steps: 

Pair       CLRF 0C           ;Clear file 0C 
             CLRF 0D           ;Clear file 0D 
Pair1      INCFSZ 0C,1     ;Inc file 0C, Skip if zero 
             GOTO Pair1       ;Inc the low file 
             INCFSZ 0D,1      ;Inc the high file 
             GOTO Pair1 
                                   65,536 loops to here. 

RELATIVE ADDRESSING 
If data is placed in a table and accessed by a RETLW instruction, it is called Relative Addressing. 
The table must be in the first 00 to FF locations as the routine for Relative Addressing only allows the Program Counter to be increased (via an ADD instruction) from 00 to FF. 
To access data in a table, load W with the number of locations you want the program counter to jump down the table. In other words the "Offset" value. Then CALL Table1. 
Table1 will have an instruction to ADD the Offset value to the Program Counter and cause the micro to jump down the table. Each location will have the instruction RETLW, then a byte of data. The W register will return to the sub-routine with the data byte in W. 

The Table routine is as follows: 

                     MOVLW 04          ;Load 4 into W 
                     CALL Table1
                     MOVWF 0C         ;3C will be loaded into  file 0C 

Table1            ADDWF 02,1      ;Add W to Program Counter 
                     RETLW 9D 
                     RETLW 4B 
                     RETLW 3A 
                     RETLW B5 
                     RETLW 3C 
                     RETLW 

                     RETLW is a double-feature instruction. It is a return instruction that carries a value (a literal) in W back to the originating routine. 

RESET 
The '508A does not have an instruction or a pin on the chip that performs a reset operation. When power is first applied to the chip it waits a short period of time and begins to execute the program from the first address in memory. Thus, by turning the power OFF and ON, the chip will perform a simple RESET operation. If you think your program may "crash" or "freeze up" you can include the WATCHDOG TIMER feature. When this feature is activated, the micro will go to the first address in the program if the watchdog is not reset every few hundred milliseconds. This is done by clearing the Watchdog Timer (WDT) by using the instructions: CLRWDT on a regular basis. By including this instruction at one or more points in a program, your project will run smoothly. If it "runs off the end of the program" or freezes up, the watchdog timer will cause a RESET. 

The PIC16F84 has a "HARD RESET" as well as the watchdog feature described above. By adding a push button to pin 4, as shown in the diagram below, the chip will reset when the button is pressed. 

RETURN 
The '508A instruction-set does not have RETURN. This does not matter as most assemblers interpret RETURN as RETLW and you have the added feature of having the value in W available for use in the routine being returned to. 
You should get into the habit of using RETLW at the end of each called sub-routine. 
A RETURN (RETLW) statement must be placed at the end of a sub-routine that has been CALLed. 
Remember: Only two embedded CALLs are available with the '508A as the stack is only "2-high." Two embedded calls are as follows: 
The Main routine makes a CALL to a sub-routine. While executing this sub-routine (say sub-routine1), you can make a CALL to another sub-routine (say sub-routine2). 
At the end of sub-routine2 the RETLW statement takes you back to sub-routine1. The RETLW statement at the end of sub-routine1 takes the program back to Main. You can then make further CALLs. 
You can also have a RETLW at the end of GOTO sub-routine. Here's what happens: 
The Main routine makes a CALL to a sub-routine. While executing this sub-routine (say sub-routine1), you have a GOTO sub-routine2. 
At the end of sub-routine2 the RETLW statement takes you back to Main. 

REVERSE 
Reverse will work on any of the 5 I/O lines (GP3 is input ONLY). It reverses the direction of the data. 
For example: If GP0 is an input, REVERSE makes it an output. If it's an output, REVERSE makes it an input. You do not have to know the condition of the line before REVERSE - it simply reverses the state. 
For example: 
RevGP0 Reverses output GP0 and makes it input, or if GP0 is an input RevGP0 makes it an output. 
Since TRIS register is a "Write-only" register, its condition has to be backed up by a file that can be tested. We use file 1D for long-term storage. In set-up, prepare GP0 as an output by making 1D 
= 00. When GP0 is CALLed, file 1D is placed in W register and XORed with 01. The 00 will change to 01. The next time file 1D is XORed with 01, its value of 01 will change to 00. 

In SetUp, prepare GP0 as an output by making file 1D 00. 

SetUp            CLRF 1D         ;Clear file 1D 
                     CALL Main 

In Main, 
                     CALL RevGP0        ;GP0 will become input 
                     your own code 
                     your own code 
                     CALL RevGP0         ;GP0 will become output 

Before Main, include the sub-routine: 

RevGP0         MOVF 1D,0       ;Put 0000 0000 in W 
                     XORLW 01        ;XOR W with 01 
                     MOVWF 1D      ;Put 01 into file 1D 
                     TRIS 06            ;Put 01 into TRIS register 

If you want GP1 to REVERSE: 

RevGP1         MOVF 1D,0       ;Put 0000 0000 in W 
                     XORLW 02        ;XOR W with 02 
                     MOVWF 1D      ;Put 02 into file 1D 
                     TRIS 06            ;Put 02 into TRIS register 

If you want GP2 to REVERSE: 

RevGP2         MOVF 1D,0      ;Put 0000 0000 in W 
                     XORLW 04       ;XOR W with 04 
                     MOVWF 1D     ;Put 04 into file 1D 
                     TRIS 06           ;Put 04 into TRIS register 


If you want GP4 to REVERSE: 

RevGP4         MOVF 1D,0      ;Put 0000 0000 in W 
                     XORLW 08       ;XOR W with 08 
                     MOVWF 1D     ;Put 08 into file 1D 
                     TRIS 06           ;Put 08 into TRIS register 

ROTATION See Shifting

SECRET CODE 
Also called Secret entry code. 
To prevent unauthorised altering of timer values or any alterable data, a simple entry code can be added to the program. 
To access the secret code, the chip is turned off and button 0 is pressed while the chip is turned on. The LED will flash 4 times to indicate the program is in Secret Code mode. By entering the code 
7, 8, 9, 0, (or any code you wish to write into the program), you will be able to change the timer settings. See the Secret Code program in the Programs section. 

SET 
A bit is SET when it is changed to a "1." 

SET-UP 
Set up a port for '508A: 

SetUp             MOVLW 08      ;Load W with 0000 1000 
                     TRIS 06             ;Load W into TRIS register 
                     CLRF 06            ;Removes junk in file 

Set up a port for Pseudo '508A: 

SetUp            BSF 03,5           ;Select Page1 
                     MOVLW 08        ;GP3 input 
                     MOVWF 06,1     ;Load TRISB file 
                     BCF 03,5           ;Select Page0 
                     CLRF 06            ;Removes junk in file 

SHIFTING - Also called ROTATING 
Shifting (or ROTATING) the bits in a file allows you to do three things: 

1. Shifting LEFT doubles the value of the contents. The maximum value that can be doubled is 0111 1111 = 7F as the next shift will produce 1111 1111 = FF. 
Before shifting, the carry bit must be CLEARed. This is done by the following instruction: 

                     BCF 03,0           ;CLEAR the carry bit 

2. Shifting RIGHT halves the value of the file. The minimum value that can be halved is 0000 0001 as the next shift right produces 0000 0000. 
Before shifting, the carry bit must be CLEARed as shown above. 
3. Shifting can be done to test a particular bit. By shifting and testing say bit 0, all the 8 bits in a file can be tested in a loop routine, if RRF instruction is executed. 
In a shift (ROTATE) operation, the end bit goes into the carry and makes the carry flag either SET or CLEAR, depending on the value of the bit. 0 = CLEAR, 1 = SET. 
The carry flag is located in the status register and the state of the carry flag from a previous operation will move into the opposite end of the file being rotated. The carry flag can be tested by including 
the following instruction in the program: 

           BTFSS 03,0          ;Test the carry flag.  skip if SET. 
or        BTFSC 03,0          ;Skip if CLEAR 

Do not to use the file being rotated for its numerical value as it may be corrupted by the carry bit. To remove the carry bit, rotate the file 9 times and it will return to its original value! 

SINKING 
To provide a current path to ground. An output line on a '508A will SINK a current (approx 25mA) when it is LOW (0v). Any device connected between the line and 5v will be turned on when the line is an OUTPUT and is LOW. 

SLEEP 
The '508A chip consumes approx 2mA while operating with its internal 4MHz RC oscillator. When powered-down the oscillator is turned off and the consumption falls to approx 1uA. 
To power down, the SLEEP instruction must be included in the program. To wake the micro from SLEEP, change the state of GP3. This line must be an input before SLEEP is executed. For the lowest current consumption while in SLEEP mode, GP3 should be at a logic HIGH level, before and 
during SLEEP. A change to LOW will wake the device from SLEEP. 
Before entering SLEEP, any of the pins that are assigned as inputs, must be read. This action sets bits within the micro. When in SLEEP, wake up occurs when any input pin changes from the state they were at the last reading. 
In addition, Bit7 in the OPTION register must be made "0" to enable the wake-up on pin change feature. 

In summary, these are the three instructions: 

                     BCF OPTION,7          ;Enable GPWU 
                     MOVF 06,1 
                     SLEEP