Electronic Circuits - Electronic Tutorials - Electronic Hobby Projects - A Complete Electronic Resource Centre
Electronic,  Microprocessor,  Mircro Controller and PC  based Projects / Circuits for Engineering Students, Hobbyiest and R&D persons

MICROCONTROLLER TUTORIALS - PIC

Tutorials

 

Circuits


Cybot Page

Introduction to PIC

Connect to
the PIC

Tutorial 1

Tutorial 2

Tutorial 3

Tutorial 4

Tutorial 5

Tutorial 6

Tutorial 7

Tutorial 8

Tutorial 9

Tutorial 10

Tutorial 11

Tutorial 12

Tutorial 13

 

Google
 
Web Hobbyprojects.com

PIC Tutorial 12

Interrupts - Writing The Code
 

We covered quite a bit of ground in the last tutorial, and so we think it is time that we wrote our first program.  The program we are going to write will count the number of times we turn a switch on, and then display the number.  The program will count from 0 to 9, displayed on 4 LEDs in binary form, and the input or interrupt will be on RB0. 

The first thing we need to do is tell the PIC to jump over the address where the Program Counter points to when an interrupt occurs.  You will notice that We are using a different way of expressing hexadecimal numbers.  Before We used to use F9h where h denoted hexadecimal.  We can write this as 0xF9, and this is the format we are going to use from now on.

org            0x00            ;This is where the PC points to on power up and reset 
goto           main           ;Goto our main program 

org            0x04            ;This is where our interrupt routine will start 

retfie                           ;This tells the PIC that the interrupt routine has
                                  ;finished and the PC will point back to the main
                                  ;program 

 main                           ;This is the start of our main program

Now we need to tell the PIC that we are going to use interrupts, and we are using RB0 pin 6 as an interrupt pin:

bsf                    INTCON,7      ;GIE – Global interrupt enable (1=enable)
bsf                    INTCON,4      ;INTE - RB0 interrupt enable (1=enable)

We are going to clear the interrupt flag just in case (We never trust anything!)

bcf                   INTCON,1      ;INTF - Clear flag bit just in case

Now we need to set up our two ports.  Remember that as we are using RB0 as an interrupt pin, this must be set up as an input:

  bsf                    STATUS,5       ;Switch to Bank 1

  movw                0x01                ;

  movwf              TRISB             ;Set RB0 as input

  movlw              0x10                ;          

  movwf              TRISA             ;Set the first 4 pins on PortA as output

  bcf                   STATUS,5       ;Come back to Bank 0

 We are going to use a variable called COUNT to store the number of switch counts.  We could just simply increment the value on Port A, but you will see why we are using a variable when we write our interrupt routine.

loop

movf                 COUNT,0         ;Move the contents of COUNT into W

movwf              PORTA             ;Now move it to Port A

goto                 loop                 ;Keep on doing this

          end                                         ;End of our program

So, our main program is written, and now we need to tell the PIC what to do when an interrupt happens.  In this instance, our interrupt is going to be the switch.  What we want the PIC to is add one to the variable COUNT each time the switch is closed.  However, we only want to display the number of times the switch closes from 0 to 9.  Above, We said we could have just simply incremented the value on Port A each time there was an interrupt.  But, Port A has 5 bits, and if we just simply incremented the port, we will have a maximum count of 31.  There are two reasons why we chose not to go up to 31.  First, we are going to use a 7-segment display, which can at the most only go from 0 to 15 (0 to F in hex).  Secondly, We also want to show you some of the arithmetic commands that you came across in the last couple of tutorials.

 So lets get on with our interrupt routine. 

Now the first thing we need to do is temporarily store the contents of our w register, as we are using this to transfer the contents of COUNT to PORTA.  If we don’t store it, then we could send a completely different number as a result of our arithmetic.  So let’s do that first: 

            movwf              TEMP              ;Store w register in a temporary location 

Next we want to add 1 to our variable COUNT: 

incf                   COUNT,1       ;Increment COUNT by 1, and put the result

                                                    ;back into COUNT 

Next we want to do a check on COUNT to se if we have gone past the value of 9.  The way we can do this is to subtract it from 10. 

movlw             0x0A             ;Move the value 10 into w

subwf             COUNT,0        ;Subtract w from COUNT, and put the

                                                  ;result in w

From tutorial 8 we saw that if we subtract a large number from a small number a Carry flag will be set.  This flag will also be set if the numbers are equal, and we subtract them. 

btfss                 STATUS,0    ;Check the Carry flag. It will be set if

                                                   ;COUNT is equal to, or is greater than w,

                                                   ;and will be set as a result of the subwf

                                                   ;instruction

Now we know if the value of COUNT is 9 or more.  What we want to do now is if COUNT is greater than 9, put it back to 0, otherwise go back to the main program so that we can send it to Port A.  The BTFSS command as you know will skip the next instruction if the carry flag is set i.e COUNT = 10:

goto                 carry_on         ;If COUNT is <10, then we can carry on

goto                 clear              ;If COUNT is >9, then we need to clear it carry_on

bcf                   INTCON,0x01   ;We need to clear this flag to enable

                                            ;more interrupts

movfw              TEMP     ;Restore w to the value before the interrupt 

retfie                            ;Come out of the interrupt routine

clear

clrf                   COUNT              ;Set COUNT back to 0

bcf                   INTCON,1          ;We need to clear this flag to enable

;more interrupts

 retfie                         ;Come out of the interrupt routine

All that is left to do now is put everything together and also define values to our constants, which we can do right at the beginning of our program. 

Below is the complete program listing.  The circuit is shown after the program listing.  Every time you turn the switch on, the LEDs will count up in binary from 0000 to 1010 then back to 0000.


 org 0x00                     ;This is where we come on power up and reset

 ;*******************SETUP CONSTANTS*******************

INTCON          EQU 0x0B       ;Interrupt Control Register

PORTB            EQU 0x06       ;Port B register address

PORTA            EQU 0x05       ;Port A register address

TRISA             EQU 0x85       ;TrisA register address

TRISB             EQU 0x86       ;TrisB register address

STATUS          EQU 0X03      ;Status register address

COUNT           EQU 0x0c        ;This will be our counting variable

TEMP              EQU 0x0d      ;Temporary store for w register

  goto    main                       ;Jump over the interrupt address

 
;***************INTERRUPT ROUTINE***************

  org                  0x04              ;This is where PC points on an interrupt

  movwf            TEMP              ;Store the value of w temporarily 

 incf                  COUNT,1       ;Increment COUNT by 1, and put the result

                                           ;back into COUNT 

 movlw 0x0A                           ;Move the value 10 into w

 subwf              COUNT,0       ;Subtract w from COUNT, and put the result in w

 btfss                STATUS,0       ;Check the Carry flag. It will be set if

                                            ;COUNT is equal to, or is greater than w,

                                            ;and will be set as a result of the subwf

                                            ;instruction

 goto                carry_on           ;If COUNT is <10, then we can carry on

 goto                clear                 ;If COUNT is >9, then we need to clear it

 carry_on

 bcf                  INTCON,0x01    ;We need to clear this flag to enable

                                             ;more interrupts

 movfw            TEMP              ;Restore w to the value before the interrupt

  retfie                                      ;Come out of the interrupt routine

 
clear

 clrf                  COUNT          ;Set COUNT back to 0

 bcf                  INTCON,1      ;We need to clear this flag to enable

                                                ;more interrupts 

retfie                                       ;Come out of the interrupt routine

  

;*******************Main Program*********************

 main

 ;*******************Set Up The Interrupt Registers****

 bsf                   INTCON,7      ;GIE – Global interrupt enable (1=enable)

 bsf                   INTCON,4      ;INTE - RB0 Interrupt Enable (1=enable)

 bcf                  INTCON,1      ;INTF - Clear FLag Bit Just In Case

 ;*******************Set Up The Ports******************

  bsf                STATUS,5     ;Switch to Bank 1

 movlw 0x01            

 movwf TRISB                      ;Set RB0 as input 

 movlw 0x10                       

 movwf TRISA                      ;Set R 0 to RA3 on PortA as output

  bcf                  STATUS,5  ;Come back to Bank 0

 ;*******************Now Send The Value Of COUNT To Port A           

 loop

movf                 COUNT,0       ;Move the contents of Count into W

movwf              PORTA           ;Now move it to Port A

goto                 loop              ;Keep on doing this

 end                                     ;End Of Program

 
The Circuit Diagram

Below is the circuit diagram that will work for the code above.  There are two things in the diagram that may throw you.  First, We have not included a timing capacitor in the oscillator circuit.  This is a clever little trick that you can try if you run out of capacitors.  The capacitance comes from the stray capacitance between the oscillator pin and ground.  so, with the resistor and the stray capacitance, we have an RC oscillator.  Okay, this is not an accurate way of doing it, as the stray capacitance will vary from circuit to circuit.  But, We thought you may be interested in seeing this sort of thing.  Secondly, We have included a de-bouncing circuit across the switch.  This is needed because every time you flick a switch, the contacts will bounce.  This will make the PIC think there have been more than one switches.  With the de-bouncing circuit, when the switch goes high, the capacitor charges up.  no matter how many times the switch goes to +5V, the capacitor will only charge once.  The capacitor is discharged when the switch is thrown the other way.  If you want to see the effects of switch bounce, then disconnect the capacitor and resistor across the switch.


PIC_Circuit

 

       Click here  >>>>  Tutorial 13

Back to PIC Microcontroller Tutorial