Programming Pic Microcontrollers PDF
Programming Pic Microcontrollers PDF
Number of Lectures: 5
R. Barnett, L OCull
O Cull and S. Fox
Embedded C Programming
and the Microchipp PIC
Thomson (2004)
ISBN 1401837484
Price (Amazon) 47
http://www.mikroelektronika.co.yu/english/product/books/
htt // ik l kt ik / li h/ d t/b k /
PICbook/0_Uvod.htm
PIC architecture
PIC specific limitations and extensions to C
PIC-specific
Programming PIC hardware such as ports, ADC, timers, etc
Using software libraries
This unit
nit will
ill be assessed b
by a m
multiple-choice
ltiple choice test
The multiple-choice
multiple choice test will last for 30 minutes
minutes, during which
20 questions must be answered
The marks from this test will contribute to the overall mark for
the module EE2A2
Answer:
Lecture 1
PIC Architecture
Harvard Architecture:
Data ports A (6
(6-bit)
bit), B (8
(8-bit)
bit), C (8
(8-bit)
bit), D (8
(8-bit)
bit), E (3
(3-bit)
bit)
Timer/counter modules 0 (8-bit), 1 (16-bit), 2 (8-bit), 3 (16-bit)
CCP/PWM modules (2)
I2C/SPI serial
i l portt
USART ((RS-232,, RS-485))
Analogue-to-digital converter (10-bit) with 10 way input
multiplexer
EEPROM (256 byte)
Stack level 1
Stack level 2
..
..
..
.
Stack level 31
Program memory
contains the Reset and High priority int vector 0x0008
Interrupt vectors
Low priority int vector 0x0018
The PIC18F452 has 32k
(0x8000) locations of
program memory
P
Program memory
0x7FFF
0xF80
SFRs
0xFFF
Port A 0xF80
0 F80 SPBRG 0 FAF
0xFAF
...
The memory block Port B 0xF81 ..
0xF80 to 0xFFF (128 Port C 0xF82 Timer1L 0xFCE
locations) references Port D 0xF83 Timer1H 0xFCF
special function ...
Port E 0xF84 ..
registers (SFRs) ...
.. Timer0L 0xFD6
Some of the SFRs Tris A 0xF92 Timer0H 0xFD7
...
are shown
h h
here Tris B 0xF93 ..
Tris C 0xF94 Wreg 0xFE8
...
Tris D 0xF95 ..
Tris E 0xF96 StkPtr 0xFFC
Literal instructions :
MOVLW Move literal to W
ADDLW Add literal
lit l tto W
Data memor
memory program memor
memory operations
operations:
TBLRD*+ Table read with p
post-increment
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 22
Status Register
The 8-bit status register
g is set during
g arithmetic operations
p
- - - N OV Z DC C
Lecture 2
CCS Compiler
C was used
d tto write
it th
the nextt version
i off UNIX system
t
software
It has
h high
hi h llevell constructs
t t
It can handle low level activities
It produces efficient programs
It can be compiled on a wide variety of computers
The related language C++ is too complex for use with the
present g
p generation of PICs
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 28
CCS PIC Compiler
A compiler converts a high-level language program to machine
instructions for the target processor
A cross-compiler
il iis a compiler
il ththatt runs on a processor
(usually a PC) that is different from the target processor
PIC-specific
PIC specific pre
pre-processor
processor directives are provided in addition
to the standard directives (#include, #define etc):
#inline implement the following function inline
#priority set priority of interrupts
In CCS C the long int (16 bit) and int32 (32 bit) types are
processed using multi-precision arithmetic
Als += Bls
Yes
Overflow? Ams ++
No
Ams += Bms
MOVF Bls, W
ADDWF Als
MOVF Bms
Bms, W
ADDWFC Ams
MOVF Bls, W
ADDWF Als
MOVF B1, W
ADDWFC A1
MOVF B2, W
ADDWFC A2
MOVF Bms
Bms, W
ADDWFC Ams
int j = 5, k = 8; int j = 5, k = 8;
swap(&j,
(&j &k);
&k) swap(j,
(j k);
k)
#include <18F452.H>
#fuses HS,NOWDT,NOBROWNOUT,NOPROTECT,PUT
#
#use delay(clock=20000000)
d l ( l k 20000000)
#include "lcd.c"
#fuses HS,NOWDT,NOBROWNOUT,NOPROTECT,PUT
In this example:
HS Clock is a high-speed crystal or resonator
NOWDT W t hd ti
Watchdog timer iis di
disabled
bl d
NOBROWNOUT Brown-out detector is disabled
NOPROTECT Code protect off
PUT Power-on timer is enabled
#use delay(clock=20000000)
#include "lcd.c"
This is
Thi i nott particularly
ti l l efficient
ffi i t (the
(th library
lib file
fil iis compiled
il d every
time) - however typical PIC programs compile in a few seconds
Lecture 3
Data Ports
D Q
Tri-state
s a e write
e Q
Data read
Data write - this latches the data written to the pin which
should be configured as an output
Tri-state write - this latches the data direction for the pin
(0 = output, 1 = input)
Data read - this reads the current value of the pin which
should
h ld bbe configured
fi d as an iinputt
Example:
a pe a an 8
8-bit
b t input
put po
portt memory-mapped
e o y apped to location
ocat o
0xF81:
#d fi
#define portb
tb (int
(i t *) 0xF81
0 F81
Th portt is
The i accessed
d by
b the
th use off the
th indirection
i di ti operator
t **:
int p;
p = *portb;
void main()
{
*trisb = 0x00;
for (;;) {
*portb = ~*portb;
delay_ms(100);
}
}
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 58
Accessing the Data Ports
Or more elegantly using functions:
void set_portb_output()
_p _ p () void main()
()
{ {
*trisb = 0x00; int q = 0x0F;
} set_portb_output();
t tb t t()
for (;;) {
void write_portb(int
_p ( p) write_portb(q
_p (q = ~q);
q);
{ delay_ms(100);
*portb = p; }
} }
Although
Alth h thi
this code
d iis llonger th
than th
the previous
i example
l it iis
better structured
Comprehensive
C h i supportt iis provided
id d iin CCS C ffor accessing
i
data ports and individual pins of the ports
Thee sta
standard
da d method
et od oof I/O
/O will cause tthe
e co
compiler
p e to
generate code to set the direction register for each I/O
operation
p
The
e fast
ast method
et od of
o doing
do g I/O
/O will cause tthe
e co
compiler
p e to
perform I/O without programming of the direction register
The user must ensure the direction register is set correctly via
set_tris_X() .
#use standard
standard_io(b)
io(b)
void main()
{
int q;
for (q = 0b00000001;; q ^
^= 0b00000101) {
output_b(q);
delay_ms(100);
y
}
}
#use fast_io(b)
fast io(b)
void main()
{
int q;
set tris b(0b11111010);
set_tris_b(0b11111010);
for (q = 0b00000001;; q ^= 0b00000101) {
output_b(q);
p q
delay_ms(100);
}
}
output_b(q);
MOVFF 0x6, 0xf8a Write port
#use fixed
fixed_io(b_outputs=pin_b2,pin_b0)
io(b outputs pin b2 pin b0)
void main()
{
int q;
for (q = 0b00000001;; q ^
^= 0b00000101) {
output_b(q);
delay_ms(100);
y
}
}
output_b(q);
MOVLW 0xfa Set DDR
MOVWF 0xf93
MOVFF 0x6, 0xf8a Write port
void main()
{
boolean q;
for (q = false;; q = !q) {
if (q)
output_high(pin_b2);
else
output_low(pin_b2);
delay_ms(100);
}
}
output_high(pin_b2);
output high(pin b2); S t DDR
Set
BCF 0xf93, 0x2
BSF 0xf8a,
, 0x2 Write pin
void main()
{
boolean q;
set_tris_b(0b11111010);
for (q = false;; q = !q) {
if (q)
output_high(pin_b2);
else
output_low(pin_b2);
delay ms(100);
delay_ms(100);
}
}
output_high(pin_b2);
BSF 0xf8a, 0x2 Write pin
void main()
{
boolean q;
for (q = false;; q = !q) {
if (q)
output_high(pin_b2);
else
output low(pin b2);
output_low(pin_b2);
delay_ms(100);
}
}
p g (p );
output_high(pin_b2);
MOVLW 0xfa S t DDR
Set
MOVWF 0xf93
BSF 0xf8a,
0xf8a 0x2 Write pin
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 72
More Efficient Program
#use fast_io(b)
fast io(b)
void main()
{
set_tris_b(0b11111010);
for (;;) {
output_toggle(pin_b2);
delay_ms(100);
y
}
}
output_toggle(pin_b2);
output toggle(pin b2);
BTG 0xf8a, 0x2 Toggle pin
A switch used as input can pull the line low (against the weak
pull-ups) and no further hardware is required
Lecture 4
Timer/Counter/PWM
Fosc/4 0
0 Timer/
1
counter
I/O pin Pre-scaler 1
T0SE T0CS
PSA
D-bus
void main()
{
*t0con = 0xE0;
*tmr0l = 0;
lcd_init();
for (;;) {
printf(lcd_putc, "\f%d", *tmr0l);
delay_ms(200);
}
}
One constant may be used from each group ORed together with
the | operator
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 80
Counters
To set the counter:
set_timer0(value)
set_timer1(value)
( )
. . . . . . . . .
void main()
{
setup_timer_0(RTCC_EXT_L_TO_H | RTCC_8_BIT);
set_timer0(0);
lcd init();
lcd_init();
for (;;) {
printf(lcd_putc,
p ( p , "\f%d",
\ , (
(int)
) get_timer0());
g ());
delay_ms(200);
}
}
clock
l k frequency
f
interrupt rate =
4 65536 prescaler
Suppose that
S th t the
th clock
l k frequency
f is
i 20 M
Mz and
d a pre-scaler
l
ratio of 16 is used:
20000000
interrupt rate =
4 65536 16
20000000
=
4194304
= 4.768 Hz
INT_TIMER0
INT TIMER0 #INT_TIMER0
#INT TIMER0 Counter/timer 0 oflo
INT_AD #INT_AD A/D conversion complete
INT RB
INT_RB #INT RB
#INT_RB Change on B port
INT_SSP #INT_SSP I2C Activity
. . . . . . . . . . . . . . . . . . . . . . . .
#INT_TIMER0
# 0
void timer_irq()
{
output_toggle(pin_b1);
}
void main()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
bl i ( )
for (;;) {
}
}
A pre-scaler
l ratio
ti off 128 gives:
i
20000000
interrupt rate =
4 65536 128
= 0.59605
clock frequency
p rate =
interrupt
4 (65536 n ) prescaler
l
To generate
T t a 1 Hz
H iinterrupt
t t with
ith a clock
l k ffrequency off 20 MH
MHz
and a pre-scaler ratio of 128:
20000000
1=
4 (65536 n ) 128
20000000
n = 65536
4 128
= 26474
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 89
1 Hz Timer Interrupts
#INT_TIMER0
# 0
void timer_irq()
{
set_timer0(26474);
output_toggle(pin_b1);
}
void main()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128);
enable_interrupts(INT_TIMER0);
bl i ( 0)
enable_interrupts(GLOBAL);
for (;;) {
}
}
A rectangular
t l wave with ith a given
i mark-space
k ratio
ti (d
(duty
t cycle)
l ) iis
generated and this is applied to a 1-bit DAC
Duty-cycle
Duty cycle register
Comparator R Q
reset RC2
Counter/timer S
Comparator
P i d register
Period i t
D-bus
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 92
Pulse-Width
Pulse Width Modulation
PWM waveform:
void main()
{
int q;
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_4,period,1);
for(;;) {
if (++q >= period)
q = 0;
set_pwm1_duty(q);
delay_ms(100);
}
}
20000000
PWM frequency = = 12.38 kHz
4 4 (1 + 100)
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 95
Programming PIC Microcontrollers
Lecture 5
A 2-line
2 li 1616-character
h t LCD iis provided
id d on th
the Pi
PicDem2
D 2b board
d
R ti
Routines tto d
drive
i ththe LCD are available
il bl iin a fil
file lcd.c:
l d
#include "lcd.c"
void main()
{
long int q;
float p;
lcd_init();
for (;;) {
q = read_adc();
p = 5.0 * q / 1024.0;
;
printf(lcd_putc, "\fADC = %4ld", q);
printf(lcd_putc, "\nVoltage = %01.2fV", p);
delay ms(100);
delay_ms(100);
}
}
The
e 5 V logic-level
og c e e receive
ece e a
and
d ttransmit
a s t ssignals
g aso of tthe
e PIC
Caare
e
converted to RS232 levels by a MAX232 device
void main()
{
float p;
lcd_init();
for (;;) {
p = 5.0 * read_adc() / 1024.0;
printf("\n\rVoltage
p ( \ \ g = %01.2fV",, p);
if (kbhit())
printf(lcd_putc, "%c", fgetc());
delay ms(100);
delay_ms(100);
}
}
AN7
AN6 Vin
AN5
AN4 10-bit
VDD ADC
AN3
AN2 Vref
AN1
AN0 Db
D-bus
CCS C provides
id the
th following
f ll i functions
f ti tto control
t l th
the ADC
ADC:
setup_adc(mode) set the clock source
setup_adc_ports(value) set which pins are analogue
set_adc_channel(channel) set current input channel
read_adc() perform conversion
where
h xx can bbe 8 or 10 ((when
h sett tto 8 th
the ADC will
ill return
t th
the
most significant byte)
SPI is
i a synchronous
h serial
i l protocol
t l th
thatt uses 3 wires:
i SDO
SDO,
SDI and SCK
This directive also assigns the SDA and SCL pins used for the
I2C interface
It has
h been
b developed
d l d ffor advanced,
d d llow-power applications
li ti
such as personal communications or data acquisition
Then the master generates a Start with R/W=1 and reads the
data
int read_ext_eeprom(long
i d (l int
i i)
{
int q;
i2c_start();
i2c_write(eeprom_addr & 0xfe);
i2
i2c_write(i
i (i >> 8);
8)
i2c_write(i & 0xff);
i2c start();
i2c_start();
i2c_write(eeprom_addr | 0x01);
q = i2c_read(0);
i2
i2c_stop();
()
return q;
}
James Grimbleby School of Systems Engineering - Electronic Engineering Slide 114
24LC256 EEPROM
To p
perform a write operation
p the master g
generates a Start with
R/W=0 and sends the word address (MS byte first) and data