EEE305 Microcontroller Systems
Lecture 5: Embedded C using PIC microcontrollers
Simple I/O and XC8
(last changed 23/3/13)
Teaching resources are at
My office 5B18, telephone 028 90 366364
My email [email protected]
Microchip Inc
• Ranked number 4 (after Renesas, Freescale and
• Atmel make the chips that are in arduino boards.
• Microchip make nearly 3000 different types of MCU
• Make microcontrollers/MCUs in 5 families (as well as
serial memory and analogue products, sensors etc.,)
• Families include 10F,12F,16F,18F and then the
24F,30F and 33F as well as the 32F parts.
• We will use the 16F877A
• This is available to us in a 40 pin DIP package.
• Its datasheet is 234 pages long, and worth reading –
we will select relevant chapters.
Start up MPLAB X It is very important you use the “projects”way of working
- Create a new project -> Microchip Embedded ->standalone Project
- Select Device -> Mid Range… ->PIC16F877A (but check your board)
- Hardware tools ->Pickit 2 or 3 (the 2 is black, the 3 is red)
- Select Compiler – XC8
- Give the project a name and make a new folder. One folder per program!
- To get started; under the project window on the top left hand side
- Right click on sources and select a NEW – C Main File, name it sensibly .c
(we will try and stick to single file C programs)
You need to include the special header file <xc.h> - it loads PIC16F877A.h
MPLAB infers this from the project file. It is better to use XC.h as it is more portable.
You need to #define _XTAL_FREQ 4000000 // or whatever you board has
You need to find and load up the datasheet for the PIC16F877A and possibly look at
The device specific header file PIC16F877A, this allows you to use predefined names
Such as PORTB and TRISB
I/O pins; PORTS A-E Similar but different
Accessing special function registers (SFRs) in XC8
The Special Function Registers (SFRs) are registers which control aspects of the MCU
operation or that of peripheral modules on the device.
Memory-mapped SFRs are accessed by special C variables that are placed at the
address of the register. (Variables that are placed at specific addresses are called
absolute variables). These variables can be accessed like any ordinary C variable so
that no special syntax is required to access SFRs.
The names of the structures that hold the bit-fields will typically be those of the
corresponding register followed by bits. For example, the following shows code that
includes the generic header file, clears PORTA as a whole, sets bit 0 of PORTA using a
bit variable and sets bit 2 of PORTA using the structure/bit-field definitions.
#include <xc.h>
void main(void)
PORTA = 0x00;
// how we access alll 8 bits
RA0 = 1;
// how we could access one bit
PORTAbits.RA2 = 1; // an alternative way of accessing a bit
Internally we need to configure the PIC
This used to use the __CONFIG macro but the modern way is to use #pragma keyword
To get the PIC to work correctly we must plant a
pattern of ‘1’s and ‘0’s in a special register on
powerup. This is the CONFIG register (there can be
more than one of these depending on the PIC)
Examine chapter 14 of the datasheet;
The XC8 compiler documents in the folder
C:/Program Files (x86)/Microchip/xc8/v1.11/docs/pic_chipinfo.html
#pragma config CP=OFF, DEBUG=OFF, PWRTE=OFF
#pragma config CPD=OFF, LVP=OFF
#pragma config BOREN=OFF
#pragma config WRT=OFF
#pragma config
#pragma config FOSC=HS
Important CONFIG fuses; Oscillator Type and Watchdog disable
The config fuse setting for the
oscillator affects the bias current
applied to the oscillator circuitry
within the PIC
Important CONFIG fuses; Watchdog
A watchdog circuit forces reset active unless activated every so often, e.g every 20 seconds.
Some systems are unsafe if a microprocessor “hangs” so it may be better to force a reset if a
hardware failure occurs.
The designer should ensure that the system is safe in the reset state – relays, motors,
heaters, solenoids all in a safe state.
Watchdogs should only be added near the end of the system design, when a complete study
of failure mechanisms is undertaken.
It also confuses things if the PIC could reset at any time. You have to add code to every loop
to reset the watchdog counter, it must be sent to zero before it reaches its trigger level.
Hence it is best to disable it.
PORTB: typical input or output port (like A,C,D and E though A is 6 bits and E 3bits)
The top 4 bits of PORT B are special in
that they have extra circuitry to cause
and “interrupt on change” – we can
use that to wake up the MCU from low
power sleep mode or use it for high
priority inputs;
In addition RB6 and RB7 should NOT
be used by the user – they are used by
the PICKIT programmer.
Electrical details: chapter 17 of datasheet
Simple output: LEDs
Look up a datasheet from
->products->Optoelectronics->LEDs Standard
Farnell have 4062 different LEDS! Select green (545) Show All and click on price
ascending (the orange triangle) The first non surface mount device is FEC 1652494
An output pin driving an LED
When the output is low it is maybe
at 0.6V, the LED will require 2.1Volts
across it and a current of 20,A to
light. Hence the resistor must drop
5-2.1-0.6 = 2.3 volts across it, which
if it is carrying 20mA means its value
is V/I = 2.3/20 kOhms = 0.115 or
Roughly 120 Ohms,
What value should it be for 10mA to
flow (still a reasonably bright LED)
Multiple LEDs
Bar Graphs
7 seg displays – either
Alphanumeric – smart
– serial in, serial out
Starburst displays
(14 segment)
5x7 Dot Matrix - common cathode
common anodes also available or 8x8
An output pin driving a Relay
Some 12 Volt relay might have a
coil resistance of 300 Ohms. This
means 40mA. We could parallel
port pins, but it is easy to use a
transistor to carry the higher
current. Cheaper relays need more
The power dissipated in the
transistor is Vcesat * 40mA – quite
If the Beta of the transistor is 40
then 1ma will flow, the pin output
is maybe 4 volt, and the Base
emitter is at 0.6v so R should drop
3.4 volts at 1ma = 3k3
Look at and search for farnell parts
FEC1455510 and FEC1094428 read the datasheets.
Typical Relays:
(Use, or RS)
E.G Enter relays into the search box on the Farnell website, (7,014 products)
Pick Power-General purpose or Automotive as a category.
Note ticked blue triangle and PDF icons below part photo
Driving multiple outputs – many relays or 7 segment displays
Multiplexed output
One output to
feed 1 Led or
Relay is easy.
You may run out
of pins!
You can either
add extra devices
or sometimes
multiplex the
Multiplex means
to make a pin do
two different
From on 26/3/13
Be careful, use NPN transistors if
common cathode displays.
From on 26/3/13
Problems with multiplexing displays
Humans have persistence of vision, but only up to a point.
Peak currents need to be high to avoid splitting the perceived brightness
Processor has little time to do other things. It needs to “update” the display (move to
next digit) every 20 milliseconds)
We can use hardware timers and interrupts to help with this but it complicates code.
There are special interface chips – display drivers that will do the multiplexing for us.
E.g using the SPI or IIC (I2C or I2C) interfaces – these save lots of pins! (c.f later)
Or we can use ways of increasing the number of i/o pins and effectively avoid
multiplexing. Still makes PCB and wiring a nuisance though…
Expanding I/O
There are specialist chips to do this – using SPI or IIC, you can even send a RS232
message to a second or third PIC to achieve the same overall effect. – master-slave PICs
But we can use simple 8 bit latches or shift registers (c.f EEE324!)
e.g Look at the datasheets for a 74AC573 (£0.22). Also a ‘595 , ‘165 and ‘164 (any prefix)
Using 11 lines to give 24 outputs
From on 26/3/13
Shift registers – output using 74HC595
Example- 4 digit 7-segment display using 74595 shift registers
From on 26/3/13
Shift registers – input using 74HC165 (£0.31)
Software should keep CE low, put PL low then high and read
Q7, bring clock (CP) high then low, read Q7 and repeat. As
each bit is read it should be shifted into a byte you receive the
most significant bit first. After 8 shifts the 8 inputs are in the 8
bit variable (an unsigned char in C)
From on 26/3/13
Reading 8 inputs using 3 lines from a micro
1. pulse LOAD low
then high to load
parallel inputs.
2. read Q7’ (pin 7)
and store data bit.
(you can also use Pin
9 instead)
3. pulse CP high then
low to shift next
data bit out.
4. go back to Step 2
and repeat until 8
bits are read
This works with any simple digital i/o lines. You can also use the built in USART peripheral in a PIC is
synchronous mode – when it outputs its clock. With a 74HC165 and 74HC164 you can do 8 bit i/o over
2 lines. (c.f book by Han-Way Huang/ “Pic Microcontroller: An Introduction to Software and Hardware
interfacing” )
From on 26/3/13
Using digital inputs
If you need to read the logic state of a chip and it has the same power supply as the
PIC then you just read a ‘1’ or a ‘0’. The PIC will require very little current and has
voltage thresholds given in the datasheet.
Chips that use 3.3V are becoming common, this can just about drive a PIC input to a
readable value – if the current from the 3.3V output only drives the PIC input. You can
add a buffer chip to ensure this, or you can add a 3.3 to 5 volt translator chip.
If you choose to run the PIC itself from 3.3V then you need to ensure you do not
damage the PIC, check if you have 5V tolerant pins (some are some aren’t), use
translator chips, use a potential divider (this wastes current)
You can use a transistor or mosfet. This is the reverse of the open collector circuit you
used to drive a 12 volt relay, in this case use a pullup to VDD of the PIC.
You can use opto-isolators (opto-couplers) to avoid electric shock or to deal with
voltages that might damage the PIC or are too low or where the “earth” or zero volts of
two circuits are not common.
Optocoupler (£0.42p from Farnell)
The LED should have nearly 10mA through it to illuminate the phototransistor sufficiently;
Datasheet states Vf is 1.5V max so if the driving voltage is 4.5 Volts we need 330 Ohms. Use the
next bigger in case the 330 is 5% too low.
The current transfer ratio tells us that we can draw up to 10mA from the collector , 10k is ok as
a pull up. – we will draw 0.5mA when switched on. Note these can be slow devices.
From on 26/3/13
Multiplexing inputs
Ironically we use outputs to read inputs. If
the output port outputs the patterns
{1110, 1101, 1011, 0111} repetitively and
checks on the input port that the 4 inputs
are all still 1111 then no key has been hit
Read in
Having Output
i.e We know COL1 was active
when ROW3 went low – tells us
which switch is depressed
If a low is read then this gives us a ROW
where a key has been hit. Since the
software knows which COLUMN is has
outputted low then the combination of
the ROW and COLUMN tells us which key
has been hit.
We need to scan reasonably quickly and
this puts restraints on what else the
software can do. There are also special
key encoder chips that you can add –
extra facilities such as debounce
Lab exercise HW1
1. Examine the circuit diagram of
the millenium board and the
board itself to look at ports,
LEDs D1-D3 and pushbuttons
2. Wire up an LED to RB0 and get
it flashing twice a second
3. Read (and use) the code on
OHP 15
4. Wire up a pushbutton switch to
RD0 and read it, if it is ‘1’ light
the LED, else do not light the
LED (and repeat for ever)
5. Wire up three LEDs and three
pushbutton switches, create an
infinite loop that lights each
LED if the corresponding switch
is depressed

similar documents