Sleep command

Discussion in 'Embedded Systems and Microcontrollers' started by mr boss, Jul 2, 2009.

  1. mr boss

    Thread Starter Member

    Jun 3, 2009

    I have just worked through a interrupt tutorial, and have a question.

    Here is sample code of a interrupt on RB0

    My question is, can I make the pic sleep, while it waits for the interrupt. If I can where should I put the sleep command? Also can a pic sleep, with say a certain bit on Port A still high?


    Code ( (Unknown Language)):
    3. ; Starting Point
    5. org     0x00
    7. ; Set up the varibles
    9. trisha  equ 0x85
    10. trishb  equ 0x86
    11. porta   equ 0x05
    12. portb   equ 0x06
    13. count   equ 0x20
    14. temp    equ 0x23
    15. status  equ 0x03
    16. intcon  equ 0x0B
    18. goto    start
    20. ; Interrupt routine
    22. org     0x04
    24. movwf   temp
    26. incf    count,1
    28. movlw   d'10'
    29. subwf   count,0
    31. btfss   status,0
    32. goto    carry_on
    33. goto    clear
    35. carry_on
    37. bcf     intcon,0x01
    38. movfw   temp
    40. retfie
    42. clear
    44. clrf    count
    45. bcf     intcon,1
    47. retfie
    49. ; Set up inerrupt Registers
    52. start
    54. bsf     intcon,7
    55. bsf     intcon,4
    56. bcf     intcon,1
    58. ; Set up the ports, as i/o
    60. bsf     status,5
    61. movlw   0x01
    62. movwf   trishb
    63. movlw   0x10
    64. movwf   trisha
    65. bcf     status,5
    67. ; Main Program
    69. loop
    71. movf    count,0
    72. movwf   porta
    74. goto    loop
    76. end
  2. Vaughanabe13

    Active Member

    May 4, 2009
    I have a few suggestions for you. First thing is you should separate your interrupt code from the interrupt vector. For example, after the "org 0x04" line you should put a goto statement and point toward your interrupt service routine, and then move all of your intterupt code to the service routine section. Example: "goto ISR" and then use "ISR" as your interrupt label.
    Then at the end of your ISR you need to clear the interrupt flag bit, so that the interrupt does not immediately get called again upon exit. For example, if you are using the INT0 transition interrupt, you need to clear the INT0IF bit of the INTCON register. It is also a good idea to disable all interrupts as soon as you start the service routine so that the interrupt will not trigger again until you are done. Finally, you need to use a "retfie" command at the end of your service routine to tell the PIC you are returning from the interrupt.

    Most of your questions about SLEEP can be answered by searching the Microchip datasheet for your micro. I can tell you that the PIC will keep its output state when it goes into sleep, so if you have an LED turned on the sleep command will not turn it off and vice versa. Everything should be kept the same. The way you use the sleep command is to put it at the end of a chunk of code, followed by a "goto" statement. What happens is when the PIC sees your sleep command it will automatically prefetch the next instruction after it, so that when something triggers it to wake up it will execute that instruction to resume program operation. Therefore you need to use a goto statement to branch to whatever part of code you want to happen after the PIC wakes up from sleep. Some interrupts on the PIC will allow the PIC to wake up from sleep (such as the INT0 interrupt or an ADC conversion that has finished), and the datasheet will describe which ones do and do not. You should be fine using INT0, as it is the easiest to use and most straight forward. Read the section of the datasheet about SLEEP and it will start to make more sense.

    Hopefully I answered some of your questions. Good luck!
  3. eblc1388

    Senior Member

    Nov 28, 2008
    What is the reason/advantage of this recommendation?

    I always put my insterrupt handling code at 0x0004 and I have no problem so far.

    A GOTO instruction at 0x0004 increases the overall handling time of ISR by 2 more instruction cycles(that's 8 more crystal clocks). One should only do so if there are very good reasons and advantages.

    IIRC, for 12F and 16F PICs, no interrupt will be triggered again inside an ISR unless the programmer tell the PIC otherwise by enabling the GIE flag before finishing the ISR. Don't know about the situation in 18Fxxxx.

    Are you sure that other interrupts will triggered if one does not disable all interrupts as soon as one is inside the ISR?
  4. Vaughanabe13

    Active Member

    May 4, 2009
    For 18F pics you can certainly trigger an interrupt while inside the service routine. I guess I can't vouch for 12F but disabling interrupts is generally considered good programming practice if there is any chance of another interrupt occurring (example: switch bounce).

    As for using a label after the interrupt vector, it isn't required but it generally improves code readability, especially when you have multiple-priority interrupts at different vectors. That is always how I have been taught. There are VERY few applications that will benefit from the extra 2 instruction cycles, especially if you are running at a decently fast FOSC.
    For beginners I would definitely recommend it.
  5. mr boss

    Thread Starter Member

    Jun 3, 2009
    In my circuit I've added a capacitor and resistor for debounce. I don't use a 18F either, they're too complicated.
  6. AlexR

    Well-Known Member

    Jan 16, 2008
    PIC18s have 2 levels of interrupt. While the low priority interrupt is being serviced no further low priority interrupts can occur but a high priority interrupt will cause the program to jump to the high priority ISR. While the high priorty interrupt is being serviced no further interrupts can occur.

    The PIC16 has only one level of interrupts and while in the ISR no further interrupts can occur. Interrupts are automatically re-enabled when you perform a RETFIE instruction.

    It is important to clear the relevant interrupt flag before exiting the ISR otherwise on exit the program will see the flag as a new interrupt and jump back to the ISR.
  7. eblc1388

    Senior Member

    Nov 28, 2008
    Two levels of interrupts, so far so good.

    If while servicing a low level interrupt one disables the high level interrupt, I have to ask why places that interrupt into the high level category in the first place.

    A high level interrupt, by definition, is the ability to interrupt lower level interrupts such that more important or time critical task can be done.

    Do user have a choice of which level category to place an interrupt request in?
  8. binzer

    New Member

    Jun 17, 2009
    I think you need to disable interrupts when you enter your interrupt service routine so you can actually finish before it happens again. You need to clear the interrupt before you exit, and enable it, routine needs to be short in case your interrupt happens fast.
  9. AlexR

    Well-Known Member

    Jan 16, 2008
    Yes the user can define what is a low and what is a high level interrupt.

    The processor does this automatically.
    When it jumps to the interrupt routine it disables further interrupts. When it returns from the interrupt routine it re-enables interrupts. The only thing you must do is clear the interrupt flag before issuing a return from interrupt.
    Read the data sheet!
  10. Vaughanabe13

    Active Member

    May 4, 2009
    How are 18F chips too complicated? Having to go to a 16F micro after using an 18F was torture for me. 18F's are a little more expensive but they do pretty much everything better, and they are supported by the C18 compiler, so you can move out of the assembly dark ages. Most (I say most because I haven't checked every data sheet) 16F's don't even have a negative status bit!
  11. mr boss

    Thread Starter Member

    Jun 3, 2009
    I said they are compilacted becuase, I'm still new to mcu. For me 18F have to many features. I am still playing with the basics of 16F. Once I have enough experience ( and money ) I will look into the 18F range