Home     Contact     Forum     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science     RSS     Terms of services     Privacy policy  
   
 Home     Forum     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science   

Author Topic: Interupts!!!!  (Read 17702 times)

0 Members and 1 Guest are viewing this topic.

_pike

  • Administrator
  • Full Member
  • *****
  • Posts: 182
Interupts!!!!
« on: March 21, 2011, 01:59:55 AM »
Hello George!!!.Well i would like to speak about interupts.....I find them very useful but you haven't included them yet in detail.
So the first thing that i would like to ask you is, let's say that we want to enable an interupt from an outside event, a switch for example....When this happens then the pic will look into the program for the  org 0x04 and will continue from where it stopped?

org 0x04
.....
.....
return

Second how do we enable the external interrupt?That's for start..... ;D ;D

Thank you!!!!!!

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Interupts!!!!
« Reply #1 on: March 21, 2011, 09:02:57 AM »
that is correct, when interrupt occurs, the program continues from origin 0x04. From there, there are 3 ways to continue:
1. With RETURN: this will return the program flow to the position is was before and continue
2. With RETFIE: This will act as RETURN, but also will set the GIE flag to re-enable interrupts
3. With GOTO: This will go to the specified label.

To enable one interrupt, like the RB0/INT. you need to follow 3 steps:
1. Enable the interrupt itself from INTCON:
Code: [Select]
bsf INT0IE,INTCON
2.Clear interrupt flag
Code: [Select]
bcf INTCON,INT0IF
3.Enable global interrupt
Code: [Select]
bsf INTCON,GIE
This is mainly the procedure, and this is a good point to start with interrupts.

Regarding the interrupt flag: This is a bit on the INTCON register (we are not talking about peripheral interrupts yet) which is automatically set to 1 whenever the corresponding interrupt occurs. So for example, the RB0 INT interrupt, sets the INT0IF bit. This is done for 2 reasons:
1. First, this avoids to call the same interrupt over and over again. If one interrupt occurs and the corresponding flag bit is set, then the same interrupt cannot re-occur, unless the bit is cleared in software. Imagine a situation, where pulses are driven to the RB0 pin with the RB0/INT enabled, and those pulses are faster than the fosc/4. The interrupt will occur over and over again, but NO instruction will ever be executed, (infinite cycle).
2. The other reason is to identify which interrupt occurred... Suppose that you have the RB0/INT interrupt enabled and the TMR0 INT enabled, and in origin 0x04 you have 2 separated routines, one for RB0 interrupt (labeled as RB0_ISR) and one for the TMR0 (labeled as TMR0_ISR). You can identify which interrupt occurred with the help of its flag:

Code: [Select]
org 0x04
btfsc intcon,TMR0IF
goto TMR0_ISR         ;if TMR0IF is set, then go to TMR0_ISR routine
btfsc intcon,INT0IF
goto RB0_ISR         ;if INT0IF is set, then go to RB0_ISR routine


Keep also in mind, that there is NO instruction to clear an interrupt flag automatically, and this has to be done by your software, otherwise it will not re-enable the interrupt. So, before you run the RETFIE, remember to reset the flag...

« Last Edit: March 21, 2011, 09:05:22 AM by kam »

_pike

  • Administrator
  • Full Member
  • *****
  • Posts: 182
Re: Interupts!!!!
« Reply #2 on: March 22, 2011, 10:22:40 AM »
Ok Let's make it work!!!!!!!!! ;D
I am sure that i have used the instructions wrong but it's the beginning...... :-[   
This code is supposed to flashing a led and when i close the switch, then the red led should stop flashing and then the green will lit up for 2sec and then to return to the flashing sequence........(this will happen when i release the switch if i am right???)(What will happen if i leave it always connected???? The software will be waiting for the release of the switch????)
Code: [Select]
LIST p=16F88
#include "P16F88.inc"

CBLOCK 0x20
DELAYGPR1
DELAYGPR2
ENDC



MOVLW 0x07
MOVWF CMCON

    BSF STATUS, RP0
    MOVLW b'00000001'
    MOVWF TRISB
bsf INTCON,GIE
BCF STATUS, RP0

GOTO START

ORG 0X04
btfsS intcon,INT0IF
GOTO LED_GREEN         


ORG 0X00
START

BSF PORTB,1
CALL DELAY_250mS
BCF PORTB,1
GOTO START


LED_GREEN
    BSF PORTB,2
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
CALL DELAY_250mS
BCF PORTB,2
RETFIE



DELAY_250mS                   
        DECFSZ   DELAYGPR1, f       
        GOTO     $+2                 
        DECFSZ   DELAYGPR2, f       
        GOTO     DELAY_250mS_0       
        GOTO     $+1                 
        NOP                         
        RETURN   
« Last Edit: March 22, 2011, 10:26:28 AM by _pike »

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Interupts!!!!
« Reply #3 on: March 22, 2011, 10:49:37 AM »
first of all, your code is a little bit messy. I suggest you make some kind of a template to start with, like the one i post in this page: PIC program template

Then, an advice: I really discourage you start working with interrupts, for they can be very frustrating if you do not know how the whole thing works. For example, the software that you have just described can be very easily implemented without interrupts. I use interrupts only when necessary.

Now, regarding you code. It will not work. Have you upload it on a PIC? Watch here:

Code: [Select]
list       F=inhx8m, P=16F88, R=hex, N=0
#include  ; PIC definitions
 __config _config1,_HS_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _MCLR_OFF & _BODEN_ON & _LVP_OFF & _CPD_OFF & _WRT_PROTECT_OFF & _CCP1_RB0 & _CP_OFF
 __config _config2,_IESO_OFF & _FCMEN_OFF
 Errorlevel -302      ; switches off Message [302]: Register in operand not in bank 0.
; Definitions -------------------------------------------------------------
; RAM preserved -----------------------------------------------------------
; Conastants --------------------------------------------------------------
; Program Memory ----------------------------------------------------------
                org     0
                goto    Init
; Interrupt Service Routine -----------------------------------------------
                org     4               ; ISR beginning
              ; -------------------------------------------------------------------------
; Microcontroller initialization
Init           
; Main Program ------------------------------------------------------------
Start           
Fins           
                end             ; end of program

This is the template that i suggest you use. If it looks too complicated, then just remove the comment (;....) :
Code: [Select]
list       F=inhx8m, P=16F88, R=hex, N=0
#include  ; PIC definitions
 __config _config1,_HS_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _MCLR_OFF & _BODEN_ON & _LVP_OFF & _CPD_OFF & _WRT_PROTECT_OFF & _CCP1_RB0 & _CP_OFF
 __config _config2,_IESO_OFF & _FCMEN_OFF
 Errorlevel -302      ; switches off Message [302]: Register in operand not in bank 0.
                org     0
                goto    Init
                org     4               ; ISR beginning
Init           

Start           
Fins           
                end             ; end of program

It is not that complicated now, is it? But prefer the previous version with the commented lines. Your code should start from the "Start" label. Also, you should avoid having backward origins. You have org 0x00 lower than org 0x04 and this will cause an overlap. In your code, everything that exists above line "START" will be overlapped with those that are bellow line "START". Also, after the CBLOCK, you have instructions but without an origin point (org...). In a word: your example is not executable nor readable. You really need to start with very very simple things, that may look boring, but believe me they are not. Nothing is boring in assembly, you will see this yourself.

So first, i really really suggest you learn how to light LEDs by reading inputs. You need to feel comfortable with assembly first. It is very powerful low level language, but -as you will see in the future- it can be seriously frustrating. Take my word and make only small steps.

_pike

  • Administrator
  • Full Member
  • *****
  • Posts: 182
Re: Interupts!!!!
« Reply #4 on: March 22, 2011, 13:52:09 PM »
Well the code is indeed very rough because i didn't include comments and fuse settings.....I know that this can be done in another way, but i put this code because it is fast and small to create in order to see how an interupt is working.....I agree with you that i must do small steps but sometimes you need to go further.....I mean that by now i have managed to make a led that blinks,a led that blinks with delays,a led that blinks with delay from a pushbutton,reading inputs,an lcd interfacing with pic in 8-bit mode and in a 4-bit mode with displaying message or menu,a simple gsm alarm notification,a keycode matrix keyboard with password (but more simplier than yours)etc.....(that i would like to post some of them that are really useful if you agree of course)
But still i have a lot of GAPS and miss LOT OF THINGS THAT I SHOULD LEARN!!!!!I am still rookie....... ;D
So i want to learn interupts because i will need them to a house alarm project that i am going to upgrade......

So please Help me (us) understand the magic world of MCUs!!!!!!! :'(

Ps.
"Also, after the CBLOCK, you have instructions but without an origin point (org...)"
You Are right i diid this mistake by accident.....Also i haven't uploaded this to any pic nor mplab i just compiled it in a few minutes with the text document editor.Also could you please answer me to my schematic questions????

Thanks a lot!!!!!!!
« Last Edit: March 22, 2011, 13:56:44 PM by _pike »

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Interupts!!!!
« Reply #5 on: March 23, 2011, 14:23:11 PM »
i did not see the image attached :D

so, first, the MCLR. There are 2 things that you can do with this pin. Either you use it as reset pin, or you use it as digital input pin. Most often, this is used as digital input, especially in 8-pins PIC where each input is critical. But there is a catch (not clearly explained in all datasheets): There are some PICs (NOT ALL) that can also use this as digital output (I/O pin). Most of them, if you see, have this ONLY as input, and there is a really good reason for this. IF the pin is used as general I/O and it is defined as output from the software, then the PIC cannot be re-programmed. Remember that the programming begins with the Vpp that arrives at the MCLR pin... So if this pin is an output, this Vpp never arrives. Funny?
So, "big" PICs have this only as input, and "small" PICs may have this as I/O, but take into account that this could permanently lock your PIC. In case that you set the fuse for the pin to be MCLR, then you need to keep it HIGH for the code to run all the time. I usually put a 10K resistor to connect it to HIGH. This way, i can simply pull it LOW and generate a reset event.

Regarding the pull-up resistors. Most PICs have an internal weak pull-up resistor for  RB ports, exactly for this reason: to avoid external pull-ups. But this is software-selectable from the registers. If you enable the internal weak pull-ups, then you do not need external resistors. If you don't, you certainly do want.




Regarding the interrupts: Start with this. (i will tell you what to do and you make it). Set the PIC with internal oscillator 32KHz. Then set the timer module to take counts from fosc/4 through the prescaller. The prescaller should be 1:32. Then enable only the tmr0 interrupt. Then, make an infinite loop like this:

nop
Goto $-1

Connect an LED through a 330 resistor to RA0, and set TRISA,0 as output. And finally, in the ISR routine, do what you have to do (that is what you need to find yourself) and do also this:

movlw b'00000001'
xorwf PORTA,f

What this does is toggle the output of PORTA,0 every time that it is called.

If you make the above simple program correct, then you should expect the LED to flash approximately every 2 seconds. That is because, the program will only loop in the infinite loop. But the TMR0 increases independently with the Fosc/4, that is 32000/4 = 8000Hz. Because TMR0 is 8 bit, it overflows every 8000/256 = 32.25 Hz, and because the pulses ho through the prescaller which is 1:32, the TMR0 will overflow once every  0.9765625 Hz. Whenever the TMR0 overflows, the TMR0 interrupt is called (remember to set everything needed to enable this interrupts). After doing all necessary staff to re-enable the interrupt, the program flow returns to the infinite loop to re-start counting.
Give it a shot. Remember that you must not use any other means of delay. Nothing but the interrupt.












_pike

  • Administrator
  • Full Member
  • *****
  • Posts: 182
Re: Interupts!!!!
« Reply #6 on: March 26, 2011, 13:30:49 PM »
 :) its too difficult for me to compile the complete code you described me to follow :-[ :-[ :-[...(Rookie).You speak for internal interupt by counter overflow.If we start from an outside interupt a switch for example wouldn't be more simplier for me as rookie?I will read today the chapter of your book concerning the timer modules....

Also i liked this part.....
(i will tell you what to do and you make it)
That's how i would like to teach us... ;)

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Interupts!!!!
« Reply #7 on: March 26, 2011, 14:32:57 PM »
if you do not know about timer modules, then do learn. There are only few situations where you will not need to use at least one timer module in the future. Better to the example i told you. Do learn timer modules, especially timer0 (and timer 1 as well :D). The example i told you is not as simple as using RB0/INT... it is more useful though.