Parallel Port I/O
Parallel Port I/O
Wait until input RB3 is low: Test returns true while RB3=1
while (bittst(PORTB,3)) ; so loop exited when RB3=0
V 0.6 2
PORTB Example (cont.)
Individual PORT bits are named as RB0, RB1, ..RA0, etc. so
this can be used in C code instead of using the bittst macros.
Wait until input RB3 is low: Test returns true while RB3=1
while (RB3) ; so loop exited when RB3=0
V 0.6 3
Vdd Switch Input
10K
18F242 External pullup
RB3 When switch is pressed
RB3 reads as ‘0’, else
reads as ‘1’.
V 0.6 4
PORTB Pin Diagram: RB2:RB0
If TRIS bit a 0, tri-state
buffer is enabled, value
in data latch drives the IO
pin.
V 0.6 5
Aside: Tri-State Buffer (TSB) Review
A tri-state buffer (TSB) has input, output, and output-
enable (OE) pins. Output can either be ‘1’, ‘0’ or ‘Z’
(high impedance).
Y A Y
A
OE OE OE = 0, then switch closed
OE = 1, then switch open
Output Enable
(OE) of TSB. If
asserted, output =
input. If negated,
output is high
impedance
(output
V 0.6 disconnected)
6
Bi-directional, Half-duplex Communication
driver driver
PIC18 enabled disabled PIC18
TRIS D Q Q D TRIS
0 1
data bus data bus
D Q Q D
Q D D Q
rd_port rd_port
driver driver
PIC18 disabled enabled PIC18
TRIS D Q Q D TRIS
data bus 1 0 data bus
D Q Q D
Q D D Q
rd_port rd_port
V 0.6 7
PORTB weak pullups
Can enable weak pullups on all
RB pins configured to be inputs
by clearing the RBPU bit in the
OPTION register
RBPU = 0;
or
bitclr(INTCON2,7);
Copyright
Microchip,
from PIC18xx2
Datasheet
DS39564B
V 0.6 9
LATB versus PORTB
A read of LATB
returns the value
of the latch that
drives the external
pin.
A read of PORTB
returns the value of
the external PIN.
LATB holds the last
value written to
PORTB while
PORTB is the value of
the external pin. V 0.6 10
PORTA Parallel IO
On the 18F242, the PORTA RA0:RA3 and RA5 pins are also
used for as the inputs to the analog-to-digital converter
module.
By default, they are analog input pins, not bi-directional
digital I/O pins. If a read is done on these pins while they are
configured as analog inputs, a ‘0’ will always be returned.
To enable RA0:RA3, RA5 pins to functions as digital pins,
the ADCON1 (A/D configuration register) must be set to the
value 0x06:
// configure port A to be all digital inputs
TRISA = 0xff;
ADCON1 = 0x06;
V 0.6 11
PORT A Pin Configuration
Copyright
Microchip,
from PIC18xx2
Datasheet
DS39564B
V 0.6 12
RA4 Pin: Open Drain Output
RA4 is different from RA0:RA3, RA5 in that it is an open drain
output. RA4 can only pull LOW, it cannot pull high.
Copyright Microchip, from PIC18xx2 Datasheet DS39564B V 0.6 Copyright Microchip, from PIC18xx2 Datasheet DS39564B 13
Why Open Drain? Useful because can tie open-drain
outputs together without external logic,
only an external pullup.
Vdd
Assume CPUs A,B,C are all working on
Busy different tasks, and want to know when
CPU A LED all are finished.
V 0.6 14
Mixed Voltage Interfacing using Open
Drain Gates
V 0.6 15
PORTC Parallel IO
• We will not look at PORTC Parallel IO
• PORTC pins shared with many other functions of
the PIC18F242
• If parallel IO is needed, will always use PORTB
first, then PORTA if needed
V 0.6 16
ledflash.c Program Listing
Time delay implemented via
software loops – delay
depends upon clock
frequency and loop count
values.
18F242
RB1
V 0.6 17
Copyright Thomson/Delmar Learning 2005. All Rights Reserved.
DelayUs, DelayMS
V 0.6 19
Copyright Thomson/Delmar Learning 2005. All Rights Reserved.
Count #number of switch press/releases.
A common error:
alternate statements:
int i; if (RB6 == 0) {
TRISB = 0xEF;
RB4 = 0;
if (!(bittst(PORTB,6))) {
i = 0;
while (1) {
if (bittst(PORTB,6) == 0) {
if (!RB6) {
/* switch pressed, increment */
i++;
}
}
Will be incremented MANY times. A human CANNOT
press/release a switch faster than a few milliseconds, so code
in loop executed an unknown number of times.
V 0.6 20
Count #number of switch press/releases
Correct Solution:
int i;
TRISB = 0xEF;
RB4 = 0; while(bittest(PORTB,6));
i = 0;
while (1) {
// wait until button is pressed
while (RB6);DelayMs(30);
// wait for button to be released
while (!RB6);DelayMs(30);
i++;
} while(!bittest(PORTB,6));
Delay to let switch bounce settleV out.
0.6 21
Toggle LED for each switch press/release
V 0.6 22
Copyright Thomson/Delmar Learning 2005. All Rights Reserved.
Toggle LED for each switch press/release,
alternate solution
TRISB = 0xEF; RB4 = 0;
// LED initially off
while (1) {
while (RB6); DelayMs(30) // wait for press
while (!RB6); DelayMs(30) // wait for release
if (LB4) RB4 = 0;
else RB4 = 1; Reads bit 4 of LATB
}
V 0.6 23
Toggle LED for each switch press/release
TRISB = 0xEF; RB4 = 0;
// LED initially off
while (1) {
while (RB6); DelayMs(30); // wait for press
while (!RB6); DelayMs(30); // wait for release
PORTB = LATB ^ 0x10;
}
V 0.6 24
Another LED/Switch Problem
• a. LED initially off
• b. A press & release of switch turns LED on
• c. On next press & release, if RB7 is 0, go back to
“a”, else start LED blinking.
• d. On switch press, stop blinking, freeze LED ON
while button is held down. On button release, goto
“a”.
V 0.6 26
#define LED_OFF 0 // turn off
#define LED_ON 1 // turn on State
#define LED_BLINK 2 // start blinking
definitions
#define LED_STOP 3 // stop blinking
unsigned char state;
main(void){ Holds current state
serial_init(95,1);
pcrlf();
printf("Led Switch/IO started");
pcrlf();
state = LED_OFF; Configure,
// RB7, RB0 are inputs initialize state
TRISB = 0xEF; variable
LATB = 0x00;
// enable the weak pullup on port B
RBPU = 0;
V 0.6 27
while(1) { print statement for debugging
switch (state) {
case LED_OFF:
printf("LED_OFF");pcrlf();
Could use RB4 here
LATB4 = 0; as well
while(RB0);DelayMs(30); // wait for press
while(!RB0); DelayMs(30); // wait for release
state = LED_ON;
break;
change state so next time
case LED_ON: through case statement will
printf("LED_ON");pcrlf(); choose different case.
LATB4 = 1;
while(RB0); DelayMs(30); // wait for press
while(!RB0); DelayMs(30); // wait for release
if (RB7) state = LED_BLINK;
else state = LED_OFF;
Choose next state
break; based on RB7
V 0.6 28
case LED_BLINK:
printf("LED_BLINK");pcrlf();
// while not pressed
while (RB0) {
// toggle LED
if (LATB4) LATB4 = 0; Blink LED as long as
else LATB4 = 1; switch is not pressed
DelayMs(250);
}
DelayMs(30); Exit loop and change state
state = LED_STOP;
break;
on switch press
case LED_STOP:
printf("LED_STOP");pcrlf();
LATB4 = 1; // freeze on
// wait for release
Freeze LED on
while(!RB0);DelayMs(30); and exit state
state = LED_OFF; when switch is
break;
}
released.
}
} V 0.6 29
Typical Output to Console
V 0.6 30
LCD – Liquid Crystal Display Module
Liquid Crystal
Display (LCD)
module : K x N
where k is number
of characters
displayed, N is
number of lines.
8x2 Module
V 0.6 31
Liquid Crystal Display (LCD) module : K x N where k is
number of characters displayed, N is number of lines.
Internal memory has 80 locations (2 lines of 40 characters)
16x2 LCD
V 0.6 34
LCD Commands
V 0.6 36
© Thomson/Delmar Learning, 2005
write data or command to LCD
V 0.6 37
© Thomson/Delmar Learning, 2005
Comments on lcd_write
• ‘cmd’ is 8-bit data to write to LCD
• ‘data_flag’ – if ‘1’, then this is a data byte (set
RS=1), if ‘0’, then this is a command byte (set
RS=0).
• If ‘chk_busy’ is nonzero, then read status flag
from LCD and wait until LCD is non busy. If
‘chk_busy’ is zero, don’t check status flag, just
delay.
• if ‘dflag’ is zero, then only send upper four bits of
‘cmd’ (only needed after power up when LCD is
in 8-bit mode).
V 0.6 38
lcd_init() initializes the LCD module.
putch() is used by printf() function to write one character; define
this as write one character to LCD.
V 0.6 41