elektra

Microcontrollers, pic


    Reading from the I/O ports

    Share

    thaers3d

    عدد المساهمات : 23
    تاريخ التسجيل : 2009-03-12

    Reading from the I/O ports

    Post  thaers3d on Fri May 01, 2009 3:36 am

    [left] Up to now, we have been writing to Port A so that we can turn an LED on and off. Now, we are going to look at how we can read the I/O pins on the ports. This is so that we can connect an external circuit, and act on any outputs it gives.

    If you recall from our previous tutorials, in order to set up the I/O ports, we had to switch from Bank 0 to Bank 1. Let us do that first:



    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
    bsf STATUS,5 ;Switch to Bank 1

    Now, to set up the port to be an output, we sent a 0 to the TrisA register. To set a pin on a port to be an input, we send a 1 to the TisA register.

    movlw 01h ;Set the Port A pins
    movwf TRISA ;to input.
    bcf STATUS,5 ;Switch back to Bank 0

    Now we have set bit 0 of Port A to input. What we need to do now is to check if the pin is high or low. For this, we can use one of two instructions: BTFSC and BTFSS.

    The BTFSC instruction means ‘Do a bit test on the register and bit we specify. If it is a 0, then we skip the next instruction’. BTFSS means ‘Do a bit test in the register and bit we specify. If it is set to a 1, then we skip the next instruction.’

    Which one we use, depends on how we want our program to react when we read the input. For example, if we are simply waiting for the input to be a 1, then we could use the BTFSS instruction like this:

    Code here
    :
    BTFSS PortA,0
    Goto start
    Carry on here
    :
    :

    The program will only move onto ‘Carry on here’ only if bit 0 on PortA is set to a 1.

    Let us now write a program which will flash an LED at one speed, but if a switch is closed it will flash the LED twice as slow. You can probably work this program out for yourself, but I have included the listing anyway. You could try and write the whole program, just to see if you have grasped the concepts. We are using the same circuit as before, with the addition of a switch connected RA0 of the PIC and the positive rail of our supply.

    ;*****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

    ;****Turn the LED on****

    Start movlw 02h ;Turn the LED on by first putting it
    movwf PORTA ;into the w register and then on the port


    ;****Check if the switch is closed


    BTFSC PORTA,0 ;Get the value from PORT A
    ;BIT 0. If it is a zero
    call Delay ;a zero, carry on as normal.
    ;If is is a 1, then add an
    ;extra delay routine

    ;****Add a delay

    call Delay

    ;****Delay finished, now turn the LED off****

    movlw 00h ;Turn the LED off by first putting it
    movwf PORTA ;into the w register and then on the port

    ;****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.

    What I have done here is to turn the LED on. I then check to see if the switch is closed. If it is closed, then I make a call to our delay subroutine. This gives us the same delay as before, but we are now calling it twice. The same goes for when the LED is off. If the switch is not closed, then we have our old on and off times.

    You can compile and run this program. However a word of warning. The final circuit and code will look un-impressive to someone who is not interested in programming microcontrollers. So, don’t be upset if, when you show your family and friends how you can change the speed of a flashing LED with a switch, they show very little interest – I am talking from personal experience, here!

    If you have been following these tutorials from the start, then you may be interested to know that you have now learnt 10 of the 35 instructions for the PIC 16F84! And all of these have been learnt just by simply turning an LED on and off.

    thaers3d

    عدد المساهمات : 23
    تاريخ التسجيل : 2009-03-12

    Re: Reading from the I/O ports

    Post  thaers3d on Fri May 01, 2009 3:38 am

    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 I was introducing the commands for 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. I think I 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

      Current date/time is Wed Jun 20, 2018 6:28 pm