|
So far,
we have
made the
PIC
flash an
LED on
and
off.
Then we
were
able to
interact
with our
PIC by
adding a
switch,
and so
altering
the
flash
rate.
The only
problem
is, the
program
is very
long and
very
wasteful
of
memory.
It was
fine
when we
were
introducing
the
commands
for the
first
time,
but
there
must be
a better
way of
doing
it.
Well
there is
(you
knew
that was
coming,
right?).
Let us
examine
how we
were
actually
turning
the LED
on and
off.
movlw
02h
movwf
PORTA
movlw
00h
movlw
PORTA
First we
loaded
our w
register
with
02h,
then
moved it
to our
PortA
register
to turn
the LED
on. To
turn it
off, we
loaded w
with 00h
and then
moved it
to our
PortA
register.
In
between
these
routines
we had
to call
a
subroutine
so that
we could
see the
LED
flashing.
So, we
had to
move two
sets of
data
twice
(once
into the
w
register
then to
PORTA)
and call
a
subroutine
twice
(once
for on
and once
for
off).
So, how
can we
do this
more
efficiently?
Simple.
We use
another
instruction
called
XORF.
The XORF
instruction
performs
an
Exclusive
OR
function
on the
register
that we
specify
with the
data we
give
it.
We
think we
need to
explain
what on
earth an
Exclusive
OR is
before
we go
on.
If we
have two
inputs,
and one
output,
the
output
will
only be
a 1 if,
and only
if, the
two
inputs
are
different.
If they
are the
same,
then the
output
will be
0. Here
is a
truth
table,
for
those
who
prefer
to look
at
these:
A
B
F
0
0
0
0
1
1
1
0
1
1
1
0
Let us
now look
to what
happens
if we
make B
the same
as our
previous
output,
and just
changing
the
value of
A:
A
B
F
0
0
0
0
0
0
1
0
1
1
1
0
1
0
1
If we
keep the
value of
A equal
to 1,
and we
Exclusive
OR it
with the
output,
the
output
will
toggle.
For those
who
can’t
see this
from the
truth
table,
here it
is using
binary:
0
Current
Output
EX-OR
With 1
1
New
Output
EX-OR
With 1
0
New
Output
Hopefully
you can
see that
by
exlusive
ORing
the
output
with 1,
we are
now toglling
the
output
from 0
to 1 to
0.
So, to
turn our
LED on
and off,
we just
need two
lines:
MOVLW
02h
XORWF
PORTA,1
What we
are
doing is
loading
our w
register
with
02h. We
are then
Exclusive
ORing
this
number
with
whatever
is on
our
PortA.
If bit 1
is a 1,
it will
change
to a 0.
If bit 1
is a 0,
it will
change
to a 1.
Let’s
run
through
this
code a
couple
of
times,
to show
how it
is
working
in
binary:
PORTA
00010
xorwf
00000
xorwf
00010
xorwf
00000
xorwf
00010
We don’t
even
need to
load the
same
value
into our
w
register
each
time, so
we can
do this
once at
the
beginning,
and just
jump
back to
our
toggle
command.
Also, we
don’t
need to
set up a
value on
our
PortA
register.
Why?
Well,
because
if on
power up
it is a
1, we
will
toggle
it.
We,
on the
other
hand it
is a 0
on power
up, we
will
still
toggle
it.
So, let
us now
see our
new
code.
The
first
one is
our
original
flashing
LED, and
the
second
is where
we added
a
switch:
Flashing
LED
;*****Set
up the
Constants****
STATUS equ
03h ;Address
of the
STATUS
register
TRISA
equ
85h ;Address
of the
tristate
register
for port
A
PORTA
equ
05h ;Address
of Port
A
COUNT1
equ
08h ;First
counter
for our
delay
loops
COUNT2
equ
09h ;Second
counter
for our
delay
loops
;****Set
up the
port****
bsf STATUS,5
;Switch
to Bank
1
movlw
00h
;Set the
Port A
pins
movwf TRISA
;to
output.
bcf STATUS,5
;Switch
back to
Bank 0
movlw
02h
;Set
up our w
register
with
02h
;****Turn
the LED
on
and off****
Start
xorwf
PORTA,1
;Toggle
the LED
;****Add
a delay
call
Delay
;****Now
go back
to the
start of
the
program
goto
Start
;go back
to Start
and turn
LED on
again
;****Here
is our
Subroutine
Delay
Loop1 decfsz
COUNT1,1
;This
second
loop
keeps
the LED
goto
Loop1 ;turned
off long
enough
for us
to
decfsz
COUNT2,1
;see
it
turned
off
goto
Loop1
;
return
;****End
of the
program****
end ;Needed
by some
compilers,
and also
;just
in case
we miss
the goto
instruction.
Flashing
LED With
Switch:
;*****Set
up the
Constants****
STATUS equ
03h ;Address
of the
STATUS
register
TRISA
equ
85h ;Address
of the
tristate
register
for port
A
PORTA
equ
05h ;Address
of Port
A
COUNT1
equ
08h ;First
counter
for our
delay
loops
COUNT2
equ
09h ;Second
counter
for our
delay
loops
;****Set
up the
port****
bsf STATUS,5
;Switch
to Bank
1
movlw
01h
;Set the
Port A
pins:
movwf TRISA
;bit 1to
output,
bit 0 to
input.
bcf STATUS,5
;Switch
back to
Bank 0
movlw
02h
; Set up
our w
register
with
02h
;****Turn
the LED
on
and off****
Start
xorwf
PORTA,1
;Toggle
the LED
;****Check
if the
switch
is
closed
BTFSC
PORTA,0
; Get
the
value
from
PORT A
;BIT
0. If
it is a
zero,
call
Delay ;carry
on as
normal.
;If
is a 1,
then add
an
;extra
delay
routine
;****Add
a delay
call
Delay
;****Check
if the
switch
is still
closed
BTFSC
PORTA,0
;Get the
value
from
PORT A
;BIT 0.
If it is
a zero,
call
Delay ;carry
on as
normal.
;If
is a 1,
then add
an
;extra
delay
routine
;****Add
another
delay****
call
Delay
;****Now
go back
to the
start of
the
program
goto
Start
;go back
to Start
and turn
LED on
again
;****Here
is our
Subroutine
Delay
Loop1 decfsz COUNT1,1
;This
second
loop
keeps
the LED
goto
Loop1 ;turned
off long
enough
for us
to
decfsz
COUNT2,1
;see it
turned
off
goto
Loop1 ;
return
;****End
of the
program****
end ;Needed
by some
compilers,
and also
;just
in case
we miss
the goto
instruction.
We hope
you can
see that
by just
using
one
simple
instruction,
we have
reduced
the size
of our
program.
In fact,
just to
show how
much we
have
reduced
our
programs
by, We
have
shown
the two
programs,
what
changes
were
made,
and
their
sizes in
the
table
below:
Program
Change
Size
(Bytes)
Flashing
LED
Original
120
Flashing
LED
Subroutine
Added
103
Flashing
LED
XOR
Function
Used
91
LED With
Switch
Original
132
LED With
Switch
XOR
Function
Used
124.
So, not
only
have we
learnt
some new
instructions,
we have
also
reduced
the size
of our
coding!
Click
here >>>>
Tutorial
8
|