Home > Electronic Tutorials > Microcontroller Tutorials - PIC > PIC Tutorial 7

PIC Microcontroller Tutorial

PIC Tutorial 7

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 exclusive 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

Note: To report broken links or to submit your projects please send email to Webmaster

Discover

     more......