|
Accessing I/O pins and internal registers with PICBASIC PRO™
Compiler.
Assessing the I/O pins on a PICmicro® is very simple with PICBASIC PRO™.
You will need to know the official names of the port and data-direction
registers. Microchip assigns these names, and they can be found in the
datasheet for the device you are using. If you don't have the microchip
datasheet, stop now and go get it. They're available as free downloads
from Microchip. Don't try to
program without the datasheet.
For the examples in this document, we will use PORTB as the I/O port name and
TRISB as the data-direction register name. These names are common to most
PICmicros. Our PICmicro is a PIC16F877.
Each PICmicro has pins that you can control for output, or read
for input. These pins are grouped into ports so that you can read or write
to as many as 8 pins at once. Typically, an I/O port represents 8 pins.
PORTB on a 16F877 has 8 bits, and each bit controls a pin. When we look
in the Microchip datasheet, we find that the PORTB pins are located on adjacent
pins on the device. RB0 (PORTB.0) is on pin-33, RB1 is pin-34... RB7 is
pin-40.
Input and Output on an individual pin
Let's make our first goal to output 5V (logic 1) on physical pin-40, which is PORTB,
bit-7. If you are familiar with PICBASIC™, you may know that this can be
done with the command, "HIGH 7". This method is valid, but it
hides an important step from you. I want to demonstrate the manual method,
which involves 2 steps.
The first thing you need to do is tell the PICmicro that you want the pin to
be an output. This is done by clearing the corresponding bit in the TRISB
register (the data-direction register). Since we are using bit-7 of PORTB,
we will clear bit-7 of the TRISB register.
|
TRISB.7 = 0 Next, you will write the value that you want on the physical pin to it's
PORTB equivalent.
PORTB.7 = 1
|
The data-direction registers will hold their settings until you change
them. You don't have to waste clock cycles clearing TRISB.7 each time you
change the state of the I/O pin. TRISB.7 = 0 only needs to be in your code
once, near the top, unless you want to change PORTB.7 to an input. You can
change it to an input any time, with "TRISB.7 = 1".
When powered up, all the I/O pins on the device are configured as
inputs. To read the logic state of physical pin 39, just use the port name
and bit exactly like you would a variable name.
|
StateOfRB6 = PORTB.6 or:
If (PORTB.6 = 0) Then ButtonIsPressed
|
Input and Output on a Port (multiple pins)
You can access registers and ports without specifying the bit number.
This allows you to move 8 bits of data with one command.
Lets say you want to repeat the example above, but you want ALL the pins on
PORTB to be driven high. The code is basically the same, but you have to
use 8 bits of data in your commands:
TRISB = %00000000 'set all PORTB pins as output
PORTB = %11111111 'make all PORTB pins high
To set PORTB as all input and read the input states of all pins to a
variable:
TRISB = %11111111 'set all PORTB pins as input
StateOfPortB = PORTB 'read PORTB and store the 8-bit value
in StateOfPortB
Specifying bits with variables
Sometimes it is desirable to specify the bit with a variable in your
program. This allows you to write to different bits, based on some
condition in your code.
Let's write a code snippet which will count 0 to 7 and make the corresponding
bit on PORTB high for each count. To do this, we will use a bit offset.
i var byte ' i will
hold our count
TRISB = %00000000 'set all PORTB pins as output
For i = 0 To 7 'loop for 8 counts
PORTB = %00000000 'make all pins low
PORTB.0[i] = 1
'make pin number i high
Pause
500 'pause for
half a second
Next i 'go to the next count
This method works for setting pins high or low, but should not be used for
more complex commands that accept a pin parameter. An example of this is
the COUNT command.
To use a variable to direct the COUNT command to different pins, you must
make use of the predefined labels for pins as described in the manual.
These labels allow you to use a number to address certain pins, instead of the
port name. This method only works on pins with predefined labels, which
limits its use to 2 ports, or 16 pins. To determine which pins may be
accessed on a particular device, refer to the Pins
section of the manual.
The following example uses a For loop to count pulses on each pin on port
b. This will work on 18, 28, and 40-pin PICmicro MCUs, with the exception
of the 14C000.
i var byte ' i will
hold our count
W0 var
word[8] ' define an array variable to hold the count
result for each pin.
For i = 0 To 7 'loop for 8 counts
Count i, 100, W0[i] '
Count pulses on pin-i, and store result in the corresponding element of word
array W0
Next i
'go to the next count
Assigning friendly names to pins
A common practice is to assign names to certain pins, to make your code
easier to follow. If PORTB.7 controls your warning LED, then you can
assign the alias, "warnled".
warnled var PORTB.7
'assign alias name
TRISB.7 = 0 'set the pin as output
warnled = 1 'light the warning LED
Accessing Internal Registers
As you progress, you will want to read and write to the internal registers on
the PICmicro. These registers allow you to control and check the status of
the hardware on the PIC®.
Once you know the names of the registers and what they do, the process is
exactly the same as above. In fact, we used the internal register TRISB to
configure the PORTB pins. Complete descriptions of all the registers and their
functions can be found in the Microchip datasheet for any PICmicro.
One of the common registers that must be configured for the 16F877 is
ADCON1. This register controls the analog-to-digital converters on the
device. If we want to shut off the converters in order to use the PORTA
pins as digital I/O, we type:
ADCON1 = 7
or
ADCON1 = %00000111
|