Tom's Main Menu

Physical Computing Home

Intro to Physical Computing Syllabus

Networked Objects

Sustainable Practices



code, circuits, & construction

my links


PIC Configuration: Memory Registers

Memory on the PIC is divided into a series of registers. Think of it as a giant grid of bytes, and each byte in the grid has its own address. The addresses are commonly given in hexadecimal numbers. The good news is that you hardly ever need these raw address numbers. Memory is divided into program memory (where the program instructions are stored) and data memory (where the variables are stored). When you download a program to the PIC, it's stored in program memory, and when the program is running, it uses data memory as space to store and manipulate its variables. Data memory is further broken down into general-purpose memory and the special function registers.

The special function registers are where information about the chip's various functions is stored. You might think of it as similar to the preferences file for a desktop application, or more accurately, like a series of DIP switches that you sometimes see on electronic devices, that let you set the functionality of the device. Each function of the chip will have a special function register (or several registers) associated with it: the serial port, the analog-to-digital converters, the timers, and perhaps most important, the input-output pins.

Programming in assembler or C, much of the work that you do involves setting the bits of the special function registers, waiting, then checking the values of other special function registers for a result. in PicBasic Pro and other Basic compilers, the commands are written to do much of that work for you. You can also set the registers yourself in PBPro, but if a given command does it for you, it's often much more convenient just to use it.

The I/O pin registers are perhaps easiest to understand, so we'll start with them. Looking at a typical PIC diagram (the 18F452, for example), you'll see the pins labeled as RA0, RA1, RA2, etc. These names refer to the I/O ports. On the 18F452, for example, there are four I/O ports, ports A, B, C, D, and E. Within each port, the pins are given numbers. For port B, the pins are PORTB.0 through PORTB.7. Be careful, because some ports have less than 8 pins. Port A on the 18F452 has only 6, for example.

Each port has a few special function registers in memory associated with it. The TRIS register for a given port holds information on whether the pins of that port are inputs or outputs. If the bit in the TRIS register associated with a particular pin equals 0, then the pin is an output. If it's 1, then the pin is an input. For example, the statement TRISA.0 = 1 would set pin RA0 to be an input.

The PORT register holds the actual state of the pins. If a pin is high, the port bit for that pin will be 1, and if the pin is low, the port bit will be 0. For example, let's assume we have a switch on pin RB1. We'd set TRISB.1 = 1, to make it an input, and we'd then read PORTB.1. IF PORTB.1 = 1, then the switch is on (high), and if PORTB.1 = 0, then the switch is 0 (low). n.b. I'm assuming the switch is attached to power, not ground.

For example, there is a register with information about the onboard analog-to-digital converters on the PIC 18F452 and 252 chips called ADCON0. It's memory address is 1Fh, meaning that it's the 32nd byte in memory (1F hex = 31 decimal, and memory registers start with address 0, so the 32nd byte has address 31, or 1Fh. Simple, see?)
The great thing about the I/O registers is that, because they're just memory registers, we can set all of our pins at once, in code. For example, let's say we want to set all of the port B pins to outputs. We can write one line of code: TRISB = %00000000. To then set all of the pins of port B high, we write PORTB = %11111111. To set alternating pins high and low, PORTB = %10101010, and so forth. Again, if you think of the registers as DIP switches, you can imagine setting each switch to activate each pin. The % sign in PBPro means that the number following it is in binary format, so %11111111 = 255 in decimal.
Once you understand the I/O registers, the rest of the special function registers aren't much more work to understand. Think of each register as holding information about a function, and each bit as a switch holding information about a detail of the function.

For example, the Analog-to-Digital converters on the PIC have four registers associated with them. The first two, ADCON0 and ADCON1, hold information about the clock speed of the ADC, the channel number of the ADC you're looking at, whether the conversion has started or not, and whether the ADC is turned on or not. The second two registers, ADRESL and ADRESH, hold the value returned from the ADC when the conversion is done. Remember, the PIC's ADC's are 10-bit, so we need more than a byte to store the result. ADRESH and ADRESL together are 16 bits. So at the end of any A-to-D conversion, there are 6 empty bits in one or the other of those two registers.

For more on the ADC registers, see the ADC low-level example.
There is a chapter for each special function of a given PIC in that PIC's data sheet. The data sheets are all available online from the Microchip site.

Note that most pins on a PIC have more than one function. For example, pin 4 on the 18F452 is RA2/AN2/Vref-. In other words, it functions as I/O port A, pin 2; analog in channel 2; or analog in negative voltage reference, depending on the configuration of the various special function registers associated with it. If the A/D converter is on, and set to channel 2, this pin will function as an analog in. If the ADC is configured to take a negative voltage reference signal, this pin will be that reference. If the ADC is off, it'll function as a normal digital I/O pin. If you're ever getting strange functionality from a pin, and you've eliminated the obvious hardware and code mistakes (like mis-wiring or mislabeling the pin in code), check the pin's other functions, and see if perhaps one of the special function registers is set such that the pin is not performing the function you thought it was.

This would be a good time to look over the data sheets for the 18Fxx2 family and the 16F81X family.
The PicBasic Pro compiler won't let you assign general variables to the special function registers, which is a good thing. If you could do so, you could accidentally overwrite a special function register, and cause your PIC to do all sorts of unexpected things. When working in C or assembler, however, it is possible to overwrite these registers if you don't know what you're doing, so you want to understand registers well before jumping into those lower level languages.