1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

SETUP AN INTERRUPT IN 16f690

Discussion in 'Microcontrollers' started by c36041254, May 16, 2008.

  1. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    I haven't tried on the hardware because I was considering to make what Eric had suggested but, now it seems you have an easier idia but, I don't understand what do you mean by WPUs (WPUA=2 and OPTION.7 = 0)
     
  2. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    You can enable internal resistor on the pic chip, these are referred to as weak pullups (WPU). You turn them on by clearing bit 7 of the OPTION (0x81) register and setting the appropriate bit in the WPUA (0x95) register.

    Mike.
     
  3. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Well, I tried what you have suggested check the codes:

    Code (text):
            list    p=16f690
            #include <p16f690.inc>
            __CONFIG -_MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL -302

        cblock  0x20
            temp   
            display
            count  
        endc

    ;**************************STEUP THE CONSTANTS*******************************  

            org 0x00        ;this is where we come on power up and reset
            goto    Main

    ;**************************INTRUPT ROUTINE************************************  

            org 0x04

            movwf   temp        ;this and the lable Loop will run simultenously
                        ;move w into f in case to there was someting in  
                        ;count(see first step of Loop)

            incf    count,f     ;increase count by 1 and put result in count
            movlw   .10         ;load w with decimal 10
            subwf   count,w     ;subtract count from w and place result in w
            btfss   STATUS,C    ;if in above operation count<= w then carry bit
                        ;is set, so check for that and skip next step
                        ;if it is set
            goto    carry_on
            goto    clear

    carry_on:
            bcf INTCON,0x01     ;clear the INTF, just in case(read tuto. 11)
            movfw   temp        ;move temp to w
            retfie          ;get out of intrupt loop (this will start over
                        ; the whole INTRUPT LOOP again
    clear:
            clrf    count       ;set count to 0
            bcf INTCON,0x01     ;clear INTF
            retfie
    ;*****************************MAIN PROGRAMME************************  
    Main:

    ;*****************************SET UP THE INTRUP REGISTERS***********  

            bsf INTCON,0x07     ; set globel intrupt (tell PIC that we will use intrupts)
            bsf INTCON,0x04     ;
            bcf INTCON,0x01

    ;******************************SET UP THE PORTS**********************  
            bsf STATUS,RP0
            movlw   b'10000000'
            movwf   TRISC
            movlw   b'00000100'
            movwf   TRISA   ;set RA2 as input (for interrupt)
            bcf     STATUS,RP0
            bsf STATUS,RP1
            [COLOR="Red"]bcf    OPTION_REG,0x07
            bsf WPUA,0x02[/COLOR]                    
                             clrf        ANSEL
                     bcf           STATUS,RP1
    ;******************************NOW SEND THE VALUE OF COUNT TO PORTC**  

    Loop:
            movf    count,w
            movwf   PORTC
            goto    Loop
            END
    but, that is also not working I think something wrong with hardware, any way I have a spare16f628 and will try some simpler code on that, there is just one problem with 16f628 and that is it does'nt have any ANSEL register so how can I set the PORTS to work for digital ckt?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE

    The 628 doesn't have an ADC module and so no ANSEL. It does have comparators and these have to be turned of by writing 0x07 to CMCON. You turn the WPUs on by just clearing bit 7 of the OPTION register and the int pin is RB0.

    Mike.
     
  6. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Here is the code for 628, pin 0 of port a will be HIGH and on interrupt pin 7 will also be high, running it in simmulation with F9 still hangs MPLAB and animation takes too much time, kindly check the code and tell me it is right or not then I'll move to hardware.

    Code (text):
    list p=16f628
            #include<p16f628.inc>
            __CONFIG  _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL   -302
            cblock  0x20
                temp      
            endc
    ;******************************************************************
        org 0x00
        goto main
    ;***********************************INTERRUPT LOOP*****************
        org 0X04
    inter:
        movlw b'10000000'
        movwf PORTA             ;set pin 7 of port a HIGH
        goto    inter
    main:
        bsf INTCON,0x07
        bsf INTCON,0x03
        bcf INTCON,0x00
    ;**********************************SET UP THE PORTS *****************
        bsf STATUS,RP0          ;switch to BANK 1
        movlw b'00000001'  
        movwf TRISB             ;set RB0 as input
        movlw b'00000000'
        movwf TRISA                                               ;set PORT A all output
        bcf OPTION_REG,0x07        
        bcf STATUS,RP0          ;back to BANK 0
        movlw 0x07
        movwf CMCON            

    Loop:
        movlw b'00000001'      
        movwf PORTA             ;set pin 0 of port a HIGH
        goto Loop
        END
    thanks a lot for all help!:)
     

    Attached Files:

    Last edited: May 18, 2008
  7. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    I just noticed that your accessing Option_reg and WPUA in bank 2, they are in bank 1.

    Edit, in reference to 690 code.

    Mike.
     
    Last edited: May 18, 2008
  8. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    The RB0 interrupt is enabled by setting INTCON,4 not 3.

    Edit, in reference to 628 code.

    Mike.
     
  9. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    :)Thank you so much it works on hardware for 628 but only it responds to interuupt only one time. First when I turn on the power LED #1 lights up and then when I close the switch LED # 2 lights up (LED # 1 turns off), this happen even when I don't close the switch and just touch the RB0 side of the resistor lead, now again when I open the switch or remove my fingure from RB0 side of thr resistor lead LED # 1 should light up and LED # 2 should be turned off but this doen't happen, I tried resetting the INTCON,0x01 bit but, that did'nt work, though I think now I'm not too far.


    Code (text):
        list p=16f628
            #include<p16f628.inc>
            __CONFIG  _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL   -302
            cblock  0x20
                temp      
            endc
    ;******************************************************************
        org 0x00
        goto main
    ;***********************************INTERRUPT LOOP*****************
        org 0X04
    inter:
        movlw b'10000000'
        movwf PORTA             ;set pin 7 of port a HIGH
        goto    inter
    main:
        bsf INTCON,0x07
        bsf INTCON,0x04
        bcf INTCON,0x01
    ;**********************************SET UP THE PORTS *****************
        bsf STATUS,RP0          ;switch to BANK 1
        movlw b'00000001'  
        movwf TRISB             ;set RB0 as input
        movlw b'00000000'
        movwf TRISA             ;setPORT A all output
        bcf OPTION_REG,0x07
        bsf OPTION_REG,0x06    
        bcf STATUS,RP0          ;back to BANK  0
        movlw 0x07
        movwf CMCON            

    Loop:
        bcf INTCON,0x01
        movlw b'00000001'      
        movwf PORTA             ;set pin 0 of port a HIGH
        goto Loop
        END
     

    Attached Files:

  10. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    Your interrupt cannot end with goto inter. Try changing it to,

    Code (text):

            list    p=16f628
            #include<p16f628.inc>
            __CONFIG _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL -302
            cblock  0x20
            temp     
            endc
    ;******************************************************************  
            org 0x00
            goto    main
    ;***********************************INTERRUPT LOOP*****************  
            org 0X04
    inter:     
            btfss   PORTA,7
            goto    TurnOn
            bcf PORTA,7
            bsf PORTA,0
            goto    ExitISR
    TurnOn      bsf PORTA,7
            bcf PORTA,0
    ExitISR     bcf INTCON,1
            retfie


    main:
            bsf INTCON,0x07
            bsf INTCON,0x04
    ;**********************************SET UP THE PORTS *****************  
            bsf STATUS,RP0      ;switch to BANK 1
            movlw   b'00000001'
            movwf   TRISB       ;set RB0 as input
            movlw   b'00000000'
            movwf   TRISA           ;set PORT A all output
            bcf OPTION_REG,0x07
            bcf STATUS,RP0      ;back to BANK 0
            movlw   0x07
            movwf   CMCON

    Loop:
            goto    Loop
            END
     
    The above toggles bit 7 whenever an interrupt occurs. Edit, made it toggle between 7 and 0.

    Note, this is not very good code. If the main program happened to be in bank 1 when the interrupt occurs then it wouldn't work correctly. The normal way to start and end an interrupt service routine is,
    Code (text):

            ORG 0x004           ; interrupt vector location
            movwf   w_temp          ; save off current W register contents
            movf    STATUS,w        ; move status register into W register
            movwf   status_temp     ; save off contents of STATUS register


    ; isr code can go here or be located as a call subroutine elsewhere  


            movf    status_temp,w   ; retrieve copy of STATUS register
            movwf   STATUS          ; restore pre-isr STATUS register contents
            swapf   w_temp,f
            swapf   w_temp,w        ; restore pre-isr W register contents
            retfie          ; return from interrupt
     
    The above is out of the template file supplied by Microchip. You can find it at C:\Program Files\Microchip\MPASM Suite\Template\Code and it's called 16F628temp.asm

    Mike.
     
    Last edited: May 19, 2008
  11. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    I don't want to toggle the 7th bit but, I want to make it constant HIGH when interrupt occur and 1st bit to be LOW during that period and as the interrupt is removed 1st bit should be constant HIGH and 7th bit should be constant LOW.I mean the whole programme completely stoped (not halted or paused )and an LED indicates that an interrupt has occured.Thank you for correcting "retfie" mistake.:)
     
  12. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    I think you are confused about how interrupts work. The int0 interrupt is triggered whenever RB0 goes from 0 to 1. It then executes the Interrupt Service Routine (ISR) before returning to the previous task. Your ISR took approx 3uS to execute before it returned to the previous task (assuming you removed the goto). The LED on RA7 will have been illuminated for around 10uS before your main code changed it again. The human eye cannot see 10uS.

    I posted the code above as an example for you to learn from. You should study it and work out how it operates. You should then be able to make it do anything you like.

    Mike.
     
  13. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Thank you Mike you have tought me so much very patiently, I realy appreciate that. As you said the delay is very small for human eyes to realize now I understand that why I can't see RA0 being LOW, I will follow your advice of studying you code and try to make my own.
    Edit: I don't understand why you said this:

    Note, this is not very good code. If the main program happened to be in bank 1 when the interrupt occurs then it wouldn't work correctly.

    Why so ?
     
    Last edited: May 20, 2008
  14. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    When an interrupt comes along we have to ensure two things:

    First, when the interrupt finishes we need to make sure the processor is in the same state as when it started. We do this by saving the value that is in W, STATUS and when we have more complex code FSR, PCLATH and any other special function registers that may be altered by the ISR.

    Second, we have to ensure that the code in the ISR executes correctly and so we have to ensure that various things are correct, the bank selection bits, the indirect register bit, PCLATH etc.

    In the example above, if an interrupt came along while the main code was in bank 1 then instead of testing and changing PORTA it would test and change TRISA.

    Mike.
     
  15. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Thanks Mike! now the PIC is doing exactly what I wanted, now I'll try my hands on a line follower, Thanks again for all help:)

    Edit:

    Is this now O.K. ?

    Code (text):
    list p=16f628
            #include<p16f628.inc>
            __CONFIG  _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL   -302
            cblock  0x20
                temp
                temp_s      
            endc
    ;******************************************************************
        org 0x00
        goto main
    ;***********************************INTERRUPT LOOP*****************
        org 0X04
    inter:
            [COLOR="Red"]movwf temp
            movf STATUS,w
            movwf temp_s
            movlw b'10000000'
            movwf PORTA
            btfsc PORTB,0x00
            goto inter
            bcf INTCON,0x01
            movf temp_s,w
            movwf STATUS
            movf temp,w
            retfie[/COLOR]
    main:
        bsf INTCON,0x07
        bsf INTCON,0x04
        bcf INTCON,0x01
    ;**********************************SET UP THE PORTS *****************
        bsf STATUS,RP0          ;switch to BANK 1
        movlw b'00000001'  
        movwf TRISB             ;set RB0 as input
        movlw b'00000000'
        movwf TRISA             ;setPORT A all output
        bcf OPTION_REG,0x07
        bsf OPTION_REG,0x06    
        bcf STATUS,RP0          ;back to BANK  0
        movlw 0x07
        movwf CMCON            

    Loop:

        movlw b'00000001'      
        movwf PORTA             ;set pin 0 of port a HIGH
        goto Loop
        END
     
    Last edited: May 20, 2008
  16. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    As 628 has only one external interrupt (RB0) how can I use it for two phototransistors for a line follower ?
     
    Last edited: May 20, 2008
  17. geko

    geko Active Member

    Joined:
    Mar 2, 2006
    Messages:
    411
    Likes:
    28
    Location:
    Rutland, England, UK
    The way you are restoring the W register at the end of the interrupt will cause it to set/clear the Zero flag in the status register. If your main code is about to test the Zero flag when an interrupt occurs, it may end up being set incorrectly when it returns from the interrupt - this is a bad thing that you don't want to do.

    Code (text):
     
    org 0X04
    inter:
             movwf temp
             movf STATUS,w
             movwf temp_s
             movlw b'10000000'
             movwf PORTA
             btfsc PORTB,0x00
             goto inter
             bcf INTCON,0x01
             movf temp_s,w
             movwf STATUS
             [COLOR=red]movf temp,w     ;<- This will affect the Z flag in the status register[/COLOR]
             retfie
     



    You need to do it like this. The swapf instructions restore the value into W without affecting the Z flag in the status register

    Code (text):
     
    org 0X04
    inter:
              movwf        temp
              swapf        STATUS,W
              clrf           STATUS
              movwf        temp_s
     
              movlw b'10000000'
              movwf PORTA
              btfsc PORTB,0x00
              goto inter
              bcf INTCON,0x01
     
              swapf         temp_s,W
              movwf         STATUS
              swapf         temp,F
              swapf         temp,W
              retfie
     
     
    Last edited: May 21, 2008
  18. geko

    geko Active Member

    Joined:
    Mar 2, 2006
    Messages:
    411
    Likes:
    28
    Location:
    Rutland, England, UK
    I/O pins RB4,RB5,RB6,RB7 have an 'interrupt on change' function. Described on page 36 (section5.2) of the data sheet for the 16F628
     
  19. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Thanks Mike and Pete !
    edit:
    Mike why it is :

    swapf temp,F ; move whatever in temp to temp ???????
    swapf temp,W ; move whatever in temp to W
     
    Last edited: May 21, 2008
  20. geko

    geko Active Member

    Joined:
    Mar 2, 2006
    Messages:
    411
    Likes:
    28
    Location:
    Rutland, England, UK

    If you use a MOVF instruction to get the value in temp back into W it will always set/clear the Zero flag in the STATUS register so you need a way to do that without affecting the flags.

    SWAPF doesn't affect any flags in the STATUS register however it does swap the high and low nibbles in the byte so you need to do a "double swap" to recover the W register without affecting the STATUS register and with the nibbles the right way round.

    SWAPF temp,F ; swaps the high and low nibbles in temp
    SWAPF temp,W ; swaps the high and low nibbles back the right way and puts the result into W
     
    Last edited: May 21, 2008
  21. c36041254

    c36041254 Member

    Joined:
    Apr 1, 2008
    Messages:
    154
    Likes:
    1
    Location:
    Newzealand, Auckland
    Thanks Pete ! I tried your advice of using RB4-7 as interrupts but, that's not working here is the code:

    Code (text):
        list p=16f628
            #include<p16f628.inc>
            __CONFIG  _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
            ERRORLEVEL   -302
            cblock  0x20
                temp
                temp_s      
            endc
    ;******************************************************************
        org 0x00
        goto main
    ;***********************************INTERRUPT LOOP*****************
        org 0X04
    inter:
            movwf temp
            swapf STATUS,w
            clrf  STATUS
            movwf   temp_s     
            movlw b'10000000'
            movwf PORTA
            btfsc PORTB,0x04
            goto inter
            bcf INTCON,0x01
            swapf temp_s,w
            movwf STATUS
            swapf temp,w
            retfie

    main:
        bsf INTCON,0x07         ;Globel interrupt enable(we are using interr.)
        bsf INTCON,0x04         ;RB0 enabled as external interrupt
        bsf INTCON,0x03         ;RB4-RB7 interrupt on change is enabled/ in other words these pins will also work as
                                ;interrupts and interrupt will occur every time any of these pin changes state
                                ; i.e.:HIGH to LOW or LOW to HIGH, we can not set it to be on eather one state change      
        bcf INTCON,0x01         ;Clear RB0 interuupt flag, in case it is set so
                                ; that another interrupt can occur
        bcf INTCON, 0x00        ;Clear RB4-RB7 interrupt flag so, that another interr. can occur.
    ;**********************************SET UP THE PORTS *****************
        bsf STATUS,RP0          ;switch to BANK 1
        movlw b'00010001'  
        movwf TRISB             ;set RB0 & RB4 as input
        movlw b'00000000'
        movwf TRISA             ;setPORT A all output
        bcf OPTION_REG,0x07     ; enable weak pull ups on port b/ pull ups mean internal resistors
        bsf OPTION_REG,0x06     ;interuupt on rising age/this is by defoult set
        bcf STATUS,RP0          ;back to BANK  0
        movlw 0x07              ;turn comparators off, so HIGH will be simple
                                ; HIGH rather than +5V (compared to supply) so with the LOW
        movwf CMCON            

    Loop:

        movlw b'00000001'      
        movwf PORTA             ;set pin 0 of port a HIGH
        goto Loop
        END
    What I want to do is to light LED # 1 and when interr. occur LED # 1 turns off and LED # 2 lights up and these remains so until interr. presents, it did work with RB0 but not working with RB4-7. Please help me.


    EDIT: IN CKT DIAGRAM IGNORE THAT IT RB0, TAKE IT AS RB4
     

    Attached Files:

    Last edited: May 21, 2008

Share This Page