Sleep command

Thread Starter

mr boss

Joined Jun 3, 2009
11
Hi

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?

Thanks

Rich (BB code):
; Starting Point

org		0x00

; Set up the varibles

trisha	equ	0x85
trishb	equ	0x86
porta	equ	0x05
portb	equ	0x06
count	equ	0x20
temp	equ	0x23
status	equ	0x03
intcon	equ	0x0B

goto	start

; Interrupt routine

org		0x04

movwf	temp

incf	count,1

movlw	d'10'
subwf	count,0

btfss	status,0
goto	carry_on
goto	clear

carry_on

bcf		intcon,0x01
movfw	temp

retfie

clear

clrf	count
bcf		intcon,1

retfie

; Set up inerrupt Registers


start

bsf		intcon,7
bsf		intcon,4
bcf		intcon,1

; Set up the ports, as i/o

bsf		status,5
movlw	0x01
movwf	trishb
movlw	0x10
movwf	trisha
bcf		status,5

; Main Program

loop

movf	count,0
movwf	porta

goto	loop

end
 

Vaughanabe13

Joined May 4, 2009
102
Hi

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?

Thanks

Rich (BB code):
; Starting Point

org        0x00

; Set up the varibles

trisha    equ    0x85
trishb    equ    0x86
porta    equ    0x05
portb    equ    0x06
count    equ    0x20
temp    equ    0x23
status    equ    0x03
intcon    equ    0x0B

goto    start

; Interrupt routine

org        0x04

movwf    temp

incf    count,1

movlw    d'10'
subwf    count,0

btfss    status,0
goto    carry_on
goto    clear

carry_on

bcf        intcon,0x01
movfw    temp

retfie

clear

clrf    count
bcf        intcon,1

retfie

; Set up inerrupt Registers


start

bsf        intcon,7
bsf        intcon,4
bcf        intcon,1

; Set up the ports, as i/o

bsf        status,5
movlw    0x01
movwf    trishb
movlw    0x10
movwf    trisha
bcf        status,5

; Main Program

loop

movf    count,0
movwf    porta

goto    loop

end
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!
 

eblc1388

Joined Nov 28, 2008
1,542
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.
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.

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.
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?
 

Vaughanabe13

Joined May 4, 2009
102
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.
 

Thread Starter

mr boss

Joined Jun 3, 2009
11
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).
In my circuit I've added a capacitor and resistor for debounce. I don't use a 18F either, they're too complicated.
 

AlexR

Joined Jan 16, 2008
732
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.
 

eblc1388

Joined Nov 28, 2008
1,542
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?
 

binzer

Joined Jun 17, 2009
1
In my circuit I've added a capacitor and resistor for debounce. I don't use a 18F either, they're too complicated.
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.
 

AlexR

Joined Jan 16, 2008
732
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?
Yes the user can define what is a low and what is a high level interrupt.

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.
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!
 

Vaughanabe13

Joined May 4, 2009
102
In my circuit I've added a capacitor and resistor for debounce. I don't use a 18F either, they're too complicated.
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!
 

Thread Starter

mr boss

Joined Jun 3, 2009
11
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
 
Top