Special registers in the PIC

In our first web page about the PIC, we described the PIC12C671 machine instructions for performing arithmetic and logic operations. We also looked at a few instructions which altered the flow of control. These could be used to perform simple conditional and iterative actions.

Now we're going to look at a few of the special file registers of the PIC12C671 processor.

Some special file registers

Previously we'd asked you to restrict your RAM consumption for the 96 bytes of file registers numbered from 020h to 0ffh. That's a good beginning, but you really must learn about a few special file regisgters to be a proficient PIC programmers.

The PIC12C671 processor has 17 special file registers. These are used to access and control the chip's:

Each of these registers consists of eight bits, and in some instances each of these eight bits control or access a different function of the PIC. Almost 50 pages of the PIC12C671 documentation describes these registers. We're only going to look at X registers in CSCI 255. That's enough to keep us busy.

Status register

File register 03h is the status register. For us there are two "interesting" bits of this register.

Bit 2 is the Z, or zero, bit. After an aritmetic or logical operations this bit is set (to 1), if the result of the operation is zero, and cleared (to 0), otherwise.

The Z bit is probably the most tested bit of the PIC processor. Suppose you want to write some PIC assembly code corresponding to the following C code:

if (F20 == F21)
    F25 = 7

To accomplish this task, you should subtract F21 from F20 and then check the Z bit to see if the result is zero:

        movwf   20h             ; W = F20
        subwf   21h,W           ; W = F20-F21
        btfss   03h,2           ; skip next instruction if Z bit set
        goto    labelX
        movlw   7               ; W = 7
        movwf   25h             ; F25 = 7
labelX  ...

MPASM, the PIC assembler has special names for 3, the number of the status register, and 2, the bit position of Z. You can use these to rewrite the instruction:

        btfss   03h,2

as the much more readable

        btfss   STATUS,Z

Another useful bit of the status file register is bit 0, the C, or carry, bit. After an addition or subtraction operation, this bit is set to the carry bit. This is useful if you wish to perform 16-bit arithmetic using the PIC's 8-bit adder. Think about it.

The C can also be used to compare numbers. To test if register 20h is less then regester 21h, subtract 21h from 20h and check the C. If C is 1, register 20h is indeed the smaller.

Finally, there is one more use of C. When the RLF and RRF instructions are used to rotate a file register. The rotation is actually performed with the nine bits consisting of the file register plus the C bit.

Indirect register access

Suppose you wanted to store a C-like array of bytes in registers 40h to 4Fh. Since all of our PIC instructions use fixed registers, how could we index into this array? Similar problems would occur in accessing C-like pointers. Suppose register 25h contains the address of any register. How do we perform an operation similar to

The special register pair 00h and 04h allow this sort of indirect address. Register 00h is also known as INDF; and register 04h, as FRS. If you read or write into INDF, you actually read or write into the register whose address is contained in register FRS.

Suppose an array is stored in registers 40h to 4Fh and that register 25h contains an index into that array. Here's a piece of code that uses file register indirection to read the addressed array element.

        movlw   40h     ; W = 40h -- note, W is 40h *not* the contents of F40!
        addlw   20h,W   ; W = W + F20
        movwf   FRS,F   ; FRS = W -- FRS is the address of the array element
        movf    INDF,W  ; W = *FRS -- the indexed array element is loaded

Another use of array indirection is a bit more exotic. On the PIC12C671 processor, operations have 7-bit that can be used to hold the address of file registers. This means that instructions can access file registers 00h to 7Fh. However, there are also a few significant files registers within the range 80h to FFh. The easiest way to access these file registers is via the FRS-INDF pair. For example, the following code sequence loads the contents of special register TRISIO (85h) into the W register.

        movlw   TRISIO
        movwf   FRS,F
        movf    INDF,W

I/O registers

The PIC16C671 chip has six pins that can be used for digital input and output. Four of these six can also be used as a four-channel eight-bit analog-to-digital converter. It takes a few special registers to control these pins. We're going to ignore analog input here. We'll just show you how to set the six pins for digital I/O. We're also going to ignore several registers which can be used to handle interrupts.

On process reset, the chip I/O pins are initialized for analog input. To set the chip for digital input, you must set bits 2 to 0 of special register ADCON1 (9Fh) to 111. Do this with the following code sequence:

        movlw   ADCON1
        movwf   FRS
        movlw   7
        movwf   INDF

We use file register indirection because ADCON1 is in the upper range of file registers.

First, we must have a word about pin numbering and chip configuration. With our PIC program, we'll refer to these pins as GP0 to GP5, bits 0 to 5 within the special file register GPIO. However, externally these bits 0 to 5 of GPIO correspond to pins 7 to 2 of the PIC12C671.

Chip configuration is another complexity. When your program is downloaded to the PIC12C671, and special 14-bit configuartion word is also placed in the processor. This configuration word can specify some special uses for the I/O pins. For example, pin 4 (GP3) can be used as a Master Clear Reset for the chip. Pins 2 and 3 (GP5 and GP4) can also be used for an external clock.

In our programs we are assuming that Master Clear Reset is enabled and that no clockout or external clock is used. This allow us to us GP0, GP1, GP2, GP4, and GP5. The lab handouts will tell you how to specify this configuration.

Bits 5 to 0 of register TRISIO (85h) are used to set specific pins for either input or output. By default pins are set for input. Clear bit b if the b'th pin is to be used for output.

In order to make is very clear to the instructor how your pins are being set, we recommend that you start your program with code to set ADCON1 for digital I/O and immediately follow that with code to set TRISIO. [By the way, TRISIO abbreviates "tri-state I/O".] Your code would be similar to the following:

        movlw   TRISIO
        movwf   FSR     ; FSR = W = &TRISIO
        bsf     INDF,0  ; GP0 (pin 7) is set for input
        bcf     INDF,5  ; GP5 (pin 2) is cleared for output

Finally, we arrive at the special file register for actually reading and writing the pins. It's number is 5, and it's also known as GPIO. To write output pin GPi, just write to bit i of GPIO. Input pins are read similarly.

Here's a simple example. Suppose GP0 is set for input; and GP1 for output. Here's a cryptic piece of code that "copies" GP0 to GP1.

        rlf     GPIO,W
        andlw   2
        iorwf   GPIO,F

Adding the comments is left as an exercise the readers.

Coming attractions

Return to Lab 1.