Question about DT's Interrupts


Closed Thread
Results 1 to 7 of 7
  1. #1

    Default Question about DT's Interrupts

    I am trying out Darryl Taylors Interrupts but I have a few questions, I am using a 16F628A, and Interrupt on change of Portb pins 7-4.

    The first question is do I still need to set up the INTCON=%00001000, or does DT's Interrupt's take care of that.

    The second question is in the main program I am trying to get the processor to sleep until there is a change on portb.

    @ INT_ENABLE RBC_INT ; enable external (INT) interrupts
    siesta:
    @ Sleep
    @ nop
    GoTo siesta

    After spending the last week searching the forum for some clarifications, one mentioned that portb needed to be read to see if a change occurred. How do I go about just reading the port to detect a change? What I mean is, yes I can read portb and store it as a variable but if I am constantly comparing then I won't be sleeping right? Or is there another way?

    From what I gathered through the PBP manual and the forum, I need to clear the interrupt flag, intcon.1=0 but from what I can tell from DT's Interrupt's it resets the flag. Is this correct?

    According to the 16F628A datasheet I only see the use of one NOP so I believe this is correct if not please correct me.

    Another question is regarding the enabling the interrupt before the label. This is puzzling to me how when the interrupt is serviced then returning to the main program how would the interrupt be re-enabled. So I was thinking this:

    ISR:
    'go do something
    trisb = $f0
    portb = $1
    @ INT_ENABLE RBC_INT ; enable external (INT) interrupts
    @ INT_RETURN

    Is this right?

    And my last question is if my program is to start with let say loop: and my main will be the one called Siesta, always keeping it sleeping until a change on portb 7-4, then should I change @ INT_RETURN to @ INT_RETURN siesta?

    Thanks for the help

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default

    Hi,
    1) You don't need to enable the interrupt thru the INTCON register - DTInts does that for you.

    2) You must read PortB in the interrupt handler to end the mismatch condition. If you DON'T read the port in the handler the interrupt will fire again as soon you exit the handler you're stuck in an endless loop. Constantly reading and comparing it in the main routine would defeat the whole purpose of interrupts ;-)

    3) If you, when you "declare" the interrupts set the clear flag parameter to YES then you don't need to clear the interrupt request flag "manually" in the ISR.

    Once in the interrupt handler you don't need to do anything in particular (when using DT-Ints). The @ INT_ENABLE RBC_INT is used to enable the interrupts at the beginning (ie. setting the appropriate interrupt enable bit in the INTCON register etc) and again IF you've manually disabled the interrupts.

    As for the last question I don't think it matters much, it will either return to the beginning or it will end up at the NOP and then goto to the beginning which puts it to sleep.

    Hope I got that right, and that it helps.
    /Henrik.

  3. #3
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,614


    Did you find this post helpful? Yes | No

    Default

    Hi,Tazntex

    Sleep can work in two manners ...

    1) whithout interrupts

    ahaaaaa ... here, you just have to re-arm the interrupt flag (RBIF )- but not valid IOC interrupt ( RBIE )

    in this case, the program stops @ sleep line and, when awaken, continue from there. here, the NOP added is necessary ...

    2) With interrupts enabled ( RBIE valid )

    the program stops @ sleep, but jumps to location 4 ( interrupt header ) when awaken ...

    so, both cases can be used ... and you can choose the one you have better !!!

    just depends on what you want to do.


    For the example you show ... interrupts are not necessary at all ...

    just place the sleep command at the beginning of the program ..., and if awaken, program will continue with treating your input ...

    then a " GoTo siesta " will re-enter sleep ...

    can be placed in a whole " While -wend " infinite loop too ...

    Alain
    Last edited by Acetronics2; - 22nd May 2010 at 21:42.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Here's an example of wake up from sleep on change without global interrupts enabled - or an interrupt handler.

    Without global interrupts enabled, and an interrupt handler, the response time is a LOT faster since there's no context save/restore needed.
    Code:
    @ DEVICE INTRC_OSC,MCLR_OFF,LVP_OFF,WDT_OFF
     
    DEFINE OSC 4
    DEFINE NO_CLRWDT 1   ' don't need it cleared when it's disabled in config
     
    PortVal VAR BYTE
    LED VAR PORTB.0      ' alias LED on RB0
    IntFlag VAR INTCON.0 ' alias RBIF interrupt flag bit
     
    PORTB = 0          ' LEDs off
    TRISB = $F0        ' upper 4-bits inputs, lower 4-bits outputs
    OPTION_REG.7 = 0   ' internal pull-ups on
    INTCON = %00001000 ' global ints disabled, int-on-change enabled for wake up
     
    ' PORTB should always = %1111xxxx when no switch is pressed
    ' the lower 4-bits can be anything since these are outputs.
     
    Main: 
      GOSUB CheckState   ' check for switch press before sleeping
                         ' and clear interrupt flag bit
     
      @ SLEEP            ' sleep until switch is pressed
     
      TOGGLE LED         ' do stuff here immediately on wake up
      PAUSE 250
      TOGGLE LED
      PAUSE 250
      GOTO Main
     
    CheckState:
      WHILE (PORTB >> 4) != 15 ' read port & wait for switch release
         PAUSE 20        ' short debounce period
      WEND
     
      IntFlag = 0        ' clear int-on-change flag bit
     
      RETURN
     
      END
    And if you do use interrupts, having something similar to CheckState in the beginning of your interrupt handler helps avoid another interrupt when a switch is released.

    I still recommend you learn to use DT_INTS though. It's pretty cool stuff...
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Awaken from sleep when USB connected?

    Quote Originally Posted by Bruce View Post
    Here's an example of wake up from sleep on change without global interrupts enabled - or an interrupt handler......
    And if you do use interrupts, having something similar to CheckState in the beginning of your interrupt handler helps avoid another interrupt when a switch is released.

    I still recommend you learn to use DT_INTS though. It's pretty cool stuff...
    Bruce, an application I am working on needs to awaken from sleep mode when a USB cable is connected. I was using the Darrel's INT_Handler/USB_Handler from his DT_INTS-18 for servicing the USB interrupt to try to do this. However, DT told me in one post that you can't use his USB_Handler to awaken from sleep mode and I should sense the connection of the USB cable with an RB change interrupt and then in the ISR for the RB change do an @RESET to somehow start the USB service. I think I know how to use the RBC_INT from the DT_INS-18 to sense the USB connection but I don't understand how to setup my code to then start the USB service on the sense of the USB connection. If I place the @RESET statement in the RBC_INT handler, what do I have to have in my Main Loop to get the USB service going (application must then dump EEPROM data that has previously been logged over the USB interface to PC which I already have working) and then have it return to sleep mode after the USB is disconnected??

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by jellis00 View Post
    However, DT told me in one post that you can't use his USB_Handler to awaken from sleep mode and I should sense the connection of the USB cable with an RB change interrupt and then in the ISR for the RB change do an @RESET to somehow start the USB service.
    Yes I did.
    But let's pretend I didn't.

    You can put the PIC to sleep, and it will re-enumerate when re-connected.
    The main oscillator is stopped in sleep mode, so the USB module's clock also stops.
    You can also place the USB module in SUSPEND mode to reduce the current from the USB module. That's done in response to an IDLEIF, currently used to determine un-plugged state in DT_HID.

    When the USB cable is plugged in, you'll get ACTVIF interrupts (a signal to RESUME from SUSPEND mode).

    So you don't even need to connect USB +5V to an INT pin.
    The USB module can detect the changes.

    It's just that you have to do it. Nothings automatic.
    DT

  7. #7
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Is this right?

    Quote Originally Posted by Darrel Taylor View Post
    You can put the PIC to sleep, and it will re-enumerate when re-connected.
    The main oscillator is stopped in sleep mode, so the USB module's clock also stops.
    You can also place the USB module in SUSPEND mode to reduce the current from the USB module. That's done in response to an IDLEIF, currently used to determine un-plugged state in DT_HID.
    When the USB cable is plugged in, you'll get ACTVIF interrupts (a signal to RESUME from SUSPEND mode).
    Darrel, I thought I understood how to do this, but am getting all kinds of assembler errors when I try to compile. Here are the applicable excerpts of code I created to try to follow your suggestion. Can you please tell me where this went wrong??

    First I set up my DT_INTS as follows with intention of using a USB_ACTV_INT from your DT_INTS to wake up the MCU and run the USB interface when connected.
    Code:
    ASM
    INT_LIST  macro      ; IntSource,            Label,  Type, ResetFlag?
            INT_Handler   USB_Handler 
            INT_Handler   USB_ACTV_INT  _ACTVIFhandler,   PBP,  yes
            INT_Handler   INT2_INT,             _Range,   PBP,  yes
            INT_Handler   HLVD_INT,           _LowVolt,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    endasm
    Then I created this handler for the USB_ACTV_INT.
    Code:
    ACTVIFhandler:
        IF LCD_Flag = 1 Then ' This code block FOR TESTING ONLY 
            LCDOut $fe,1' Clear Display                                       
            LCDOUT $fe,Line1,"USBPlugged"
            LCDOUT $fe,Line2,"interrupt"
        ENDIF
        ; put code here to process USB interrupt
         FOR X = 0 to 1000       ; Check for incomming USB data while waiting
    @       ON_USBRX_GOSUB  _HandleRX
            PAUSE 1
                New_PORTB2 = PORTB.2         ; Check PORTB.2 pin for change              
                IF New_PORTb2 != Old_PORTB2 THEN  ' PortB.2 changed
                    Old_PORTb2 = New_PORTb2
                    ' NEXT STATEMENT NOT WORKING...CHECK WHY!!
                    ARRAYWRITE USBTXBuffer, ["USBDemo"]
                    GOSUB WaitToSend     ' Send data set about one/sec
                    ' Send device ID to PC
                    ' Send current Date/Time to PC
                    ' Send each EEPROM stored date stamped range measurement to PC
                    ' Send current BATTLOW indicator to PC                    
                    ARRAYWRITE USBTXBuffer,[0,deviceID1,deviceID2,Mon,date,Yr, _
                                       hr,MINs,sec,stamp,rng0,rng1,BATTLOW,0,0,0]
                    GOSUB WaitToSend
                ENDIF 
        NEXT X
             
        IF J > 222 THEN     ' If reached maximum EEPROM usage location...
            J = 16            ' ..reset pointer to start of range data
        Endif
        READ j, stamp       ' Read date stamp of measurment
        READ J+1, rng0      ' Read range measurement from EEPROM
        READ J+2, rng1
        Pause 10
        J = J + 3
        
        ' Send Data to PC
            ' Send device ID to PC
            ' Send current Date/Time to PC
            ' Send each EEPROM stored range measurement to PC
            ' Send current BATTLOW indicator to PC                     
            ARRAYWRITE USBTXBuffer,[0,deviceID1,deviceID2,mon,date,yr, _
                               hr,MINs,sec,stamp,rng0,rng1,BATTLOW,0,0,0]
        GOSUB SendIfReady
    
        Pause 500      ' Delay for user to view LCD   
    @ INT_RETURN
    Then I modified my Main loop per follows to put MCU in sleep mode whenever not plugged in to USB or not receiving an external interrupt from the Real-time-clock (INT2).
    Code:
    @    INT_ENABLE   USB_ACTV_INT ; enable USB activity interrupt on plug-in
    @    INT_ENABLE   INT2_INT     ; enable external (INT) interrupts
    ENABLE DEBUG
    '--------------------[ Begin Main Program Loop ]-------------------------
    ;@ StartSize(MainLoop)    ; FOR TEST ONLY
    Main:
         PAUSE 100 ' Without this Pause, there's nothing to keep the WDT clear.
                   ' HIGH, LOW & GOTO don't generate CLRWDT instuctions.
         IF LCD_Flag = 1 Then ' This code block FOR TESTING ONLY                                       
            GOSUB DisplayDateTime
         ENDIF
         ' Store current date/time in EEPROM  
            WRITE 242, Mon
            WRITE 243, Date
            WRITE 244, Yr
            WRITE 245, hr                
            WRITE 246, MINs
            Write 247, sec               
                                                                              
        ' Place code here to put MCU and Ultrasonic Ranger in SLEEP mode.
        ' while waiting for clock or USB interrupt to wakeup from SLEEP mode.  
               
        ' IDLEIF is used in the DT_HID code to detect unplugged state. If unplugged,
        ' per DT, it is safe to put the USB module in suspend mode before sleep
            IF IDLEIF THEN     ' USB is in unplugged state..
               UCON.1 = 1      ' puts USB module in suspend mode to save power
            ENDIF
        ' Enable the USB ACTVIF interrupt to awaken MCU when USB connected
            UIE.2 = 1
        ' Perform following steps to save power during Sleep mode
            CVRCON = %00000000 ' Set Voltage Reference for minimum power consumption
                               ' Disable CVref during Sleep to save power        
            ADCON1= %00000000  ' Set PortA to Analog I/O to save power during Sleep.                   
            CMCON = %00000111  ' Disable comparators
            HLVDCON = %00000000' Disable HLDV register
            TRISB = %11111111  ' Set all PORTB pins to inputs
            TRISC = %11111111  ' Set all PORTC pins to inputs
            PortA = %11111111  ' Set TOCK1, MCLR & all PortA pins High before Sleep 
                               ' to save power
            PortB = %11101111  ' Set all Port B & C pins High to save power
            PortC = %11111101  ' except RB4 & RC2.
            @ sleep
            @ NOP
        ' Microcontroller is in Sleep State awaiting next INT2 or USB plug-in
        
        ' INT2 interrupt from RTC will log a range measurement and go back to sleep     
      
        ' ACTVIF interrupt from USB senses that USB connector is plugged in 
        ' and will dump data logged in EEPROM to PC via USB interface and then go
        ' back to sleep when the USB cable is disconnected.
    
    GOTO Main
    Here are the assembler errors I get when I attempt to compile with above code:
    Attached Images Attached Images  
    Last edited by jellis00; - 15th June 2010 at 02:11. Reason: Add asm errors

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts