Interrupt on timer

Discussion in 'Embedded Systems and Microcontrollers' started by sakishrist, Dec 10, 2009.

  1. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    Hello,

    I have been trying for days now to understand the interrupts but with no luck. I have been looking for sample code on the net but I didn't find anything useful. What seems to be working for others is not working for me. For example, I found this code:
    Code ( (Unknown Language)):
    1. #include <p18f14k50.h>
    2.  
    3. //pragma codes
    4. #pragma code high_vector=0x08
    5. #pragma config FOSC = IRC //enable the internal oscillator
    6.  
    7.  
    8.  
    9.  
    10. //function prototypes
    11. void oscillator(void);
    12. void timer(void);
    13. void high_isr(void);
    14.  
    15. void interrupt_at_high_vector(void)
    16. {
    17.    _asm goto high_isr _endasm
    18. }
    19.  
    20. /*******Oscillator function - This function will set the oscillator to 31 kHz***********/
    21. void oscillator(void)
    22. {
    23. //Set oscillator to 31 kHz
    24. OSCCONbits.IRCF2 = 0;
    25. OSCCONbits.IRCF1 = 0;
    26. OSCCONbits.IRCF0 = 0;
    27.  
    28. //Device clock derived directly from the LFINTOSC internal oscillator
    29. OSCTUNEbits.INTSRC = 0;
    30. }
    31. /*******End Oscillator Function********************************************************/
    32.  
    33.  
    34. /*******Timer function - Will start the timer and set pre-scalar to 1:128**********/
    35. void timer(void)
    36. {
    37. //Pre-scalar value of 1:128. This should give about 4 seconds for the timer0 interrupt flag to go high
    38. T0CONbits.T0PS2 = 1;
    39. T0CONbits.T0PS1 = 1;
    40. T0CONbits.T0PS0 = 0;
    41.  
    42. T0CONbits.TMR0ON = 1; //Enables Timer0
    43. }
    44. /*******End Timer Function********************************************************/
    45.  
    46. void main(void)
    47. {
    48.         INTCONbits.GIE = 1; //enable high priority global interrupts
    49.         RCONbits.IPEN = 1; //enable priority levels on interrupts
    50.        
    51.         INTCONbits.TMR0IF = 0; //clears timer interrupt flag
    52.         INTCONbits.TMR0IE = 1; //enable Timer0 interrupt bit
    53.         T0CONbits.T08BIT = 1; //Set Timer0 as an 8-bit timer
    54.         INTCON2bits.TMR0IP = 1; //Timer0 Interrupt bit set to high priority
    55.        
    56.         TRISC = 0x00; //set all PORTC bits as an output
    57.        
    58.         oscillator();
    59.         timer();
    60. }    
    61.  
    62.        
    63. //High Interrupt Vector function
    64. #pragma interrupt high_isr            // declare function as high priority isr
    65. void high_isr(void)
    66. {
    67.     if(INTCONbits.TMR0IF = 1)
    68.         {
    69.             LATCbits.LATC0=1 //Turn on LED at RC0
    70.         }
    71. }
    I changed the header file for my microcontroller (18F4620) and tried to build the code but I got this error: section 'high_vector' can not fit the absolute section. Section 'high_vector' start=0x00000008, length=0x0000004a
    I am not quite sure if I really understand what that means. So could you explain to me what I am doing wrong.

    Could you provide some other links to any sample code about interrupts on timer?

    I am using MPLAB IDE with C18
    Thanks
     
  2. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    I was told to add a while(1); loop in my main routine and to make the following changes:
    The thing is I still get this error message when attempting to compile it. I thought I might be getting that error because of the lkr file I use which looks like this:
    I tried to change the values and I got it to compile but now when I execute the code I just get no leds turning on.

    So first of all, can I freely change the values in the lkr file? And what exactly are those values?

    So what could the problem be now that I managed to compile it?

    Thanks
     
  3. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    Please, could you help me or at least tell me where I should look for the answer? If there are any books that might be useful.

    Thanks
     
  4. chat_eur

    New Member

    Dec 30, 2009
    7
    0
  5. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    Thanks a lot. I appreciate it but I just have some difficulty fully understanding this and converting it to c.

    I found some books so I'll see if I can find something there that can either help me convert the sample you provided or write a new one entirely in c.

    I'll post here as soon as I find something useful.

    Thanks again.
     
  6. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,016
  7. dgdfhf

    New Member

    Dec 31, 2009
    1
    0
  8. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hey,
    Just coded this, hope it helps clear your doubts, and it's tested to work.
    Code ( (Unknown Language)):
    1. #include <p18f4620.h>
    2.  
    3. void interrupt_at_high_vector(void);
    4. void high_isr(void);
    5.  
    6. #pragma config OSC = XT //Crystal oscillator
    7. #pragma config WDT = OFF //Watchdog Timer off
    8. #pragma config MCLRE = OFF //Master clear off
    9. #pragma config LVP = OFF //LVP off
    10. #pragma config XINST = OFF //XINST off
    11.  
    12. #pragma code high_vector=0x08
    13. void interrupt_at_high_vector(void)
    14. {
    15.   _asm GOTO high_isr _endasm
    16. }
    17. #pragma code /* return to the default code section */
    18. #pragma interrupt high_isr
    19. void high_isr(void)
    20. {
    21.     LATC = 1; //RC0 HIGH
    22.     INTCONbits.TMR0IF = 0; //CLEAR TMR0 INT FLAG
    23. }
    24.  
    25. void main(void){
    26.     TRISC = 0;
    27.     LATC = 0;
    28.     INTCON = 0xA0; //GIE AND TMR0IE
    29.     T0CON = 0x85; //16-BIT, TMRON, PRESCALER 1:128
    30.     while (1); //wait for interrupt
    31. }
    Hope you understand this and it helps you.
    For any problem, feel free to ask.
    Tahmid.
     
  9. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    Thanks a lot. It works but could you please tell me what the problem was with the other program? I tried to understand what made the difference but I don't really get it.

    Thanks
     
  10. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    I figured out that by setting each T0CON bit separately some of them were set to 1.

    Thanks again.
     
  11. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,016

    Excellent example Tahmid. Nice and simple and easy to understand. The MPLAB sample in the PC18F45K20 is very hard to follow. Your sample makes things easy.

    I have taken what you have done and modified the code to have the interrupt routine toggle RD0 on and off. I also broke out each of the bits to show how they are set and I added code to test for the Timer 0 interrupt. Not really needed here but just to show how to test for the flag. Hopefully this will help others.


    Code (Text):
    1.  
    2. #include <p18f45k20.h>
    3.  
    4. /*
    5.  
    6. The following program deonstrates a method of using an interrupt on the
    7. internal timer for the 8 bit PIC microcontroller.  The code is written for
    8. the 18F45K20 demo board.  This board has a LED at RD0-RD7.  The interrupt
    9. routine will toggle the light at RD0 on and off.
    10. */
    11.  
    12.  
    13.  
    14. void interrupt_at_high_vector(void);
    15. void high_isr(void);
    16.  
    17. #pragma config FOSC = INTIO67
    18. #pragma config MCLRE = OFF //Master clear off
    19. #pragma config WDTEN = OFF, WDTPS = 32768
    20. #pragma config LVP = OFF //LVP off
    21. #pragma config XINST = OFF //XINST off
    22. #pragma code high_vector=0x08
    23.  
    24.  
    25. void interrupt_at_high_vector(void)
    26. {
    27.   _asm GOTO high_isr _endasm
    28. }
    29.  
    30.  
    31. #pragma code /* return to the default code section */
    32. #pragma interrupt high_isr
    33. void high_isr(void)
    34. {
    35.     if (INTCONbits.TMR0IF == 1)    //Check Timer 0 Interrupt Flag tp be sure this is a Timer 0 interrupt.
    36.     {
    37.         if (LATD)
    38.             LATD=0;                //RDO LOW        
    39.         else
    40.             LATD = 1;            //RD0 HIGH
    41.  
    42.         INTCONbits.TMR0IF = 0;     //CLEAR TMR0 INT FLAG
    43.     }
    44. }
    45.  
    46. void main(void){
    47.    
    48.  
    49.     TRISD = 0;
    50.     LATD = 0;
    51.  
    52.     INTCONbits.GIE         = 1;    //Set Global Interrupt Enable
    53.     INTCONbits.TMR0IE     = 1;    //Set Timer 0 Interrupt Enable    
    54.     //The INTCON bits can also be set by using INTCON = 0xA0;    
    55.  
    56.      
    57.     T0CONbits.TMR0ON     = 1;    //Turn on timer 0
    58.     T0CONbits.T08BIT     = 0;    //Disable 8 bit / enable 16 bit
    59.     T0CONbits.T0CS        = 0;    //Use the internal clock
    60.     T0CONbits.T0SE        = 0;    //Increment on low to high transition TOCK pin 1 (not used)
    61.     T0CONbits.PSA        = 0;    //Use timer prescaler
    62.  
    63.    
    64.     //Set prescaler to 1:2
    65.     T0CONbits.T0PS0        = 0;
    66.     T0CONbits.T0PS1        = 0;
    67.     T0CONbits.T0PS2        = 0;
    68.     // The T0CON bits can also be set by using T0CON = 0x85
    69.  
    70.  
    71.     while (1);                     //wait for interrupt
    72. }
    73.  
     
  12. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    in Mplab the latest sample does not work unless I add "#pragma code high_vector=0x08" before "interrupt at high_vector".

    Anyways, although it works fine now, could you explain what is the difference between
    and
    What exactly does each other do? Also can I name them as I want?

    And finally, what exactly is the purpose of "#pragma code high_vector=0x08" and "#pragma code"?

    Thanks a lot
     
  13. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,016
    Yes you can name them anything you want. You just need to remember to change the #pragma code high_vector=0x08 statement. This is the statement that connects your interrupt service routine (ISR) to the interrupt vector.

    Your ISR vector may be at a different place than the chip I am using. You will need to check your datasheet.

    When an interrupt takes place, the MCU looks at the interrupt vector, gets an address and executes the code there.


    I am still new at this myself so I am not sure why there is assembler code there but I suspect that it has to be in a proper code boundary or some such thing, so the easiest way is to use an assembler goto to execute the actual code that you want to execute.

    The second function is probably not really needed, if you wanted to write the first one all in assembler.

    But no matter what you do, as in any ISR you want the code to be as short and as fast as possible.
     
  14. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    So where is "interrupt_at_high_vector" called from?
     
  15. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,016
    It was in my previous post but I was a bit wrong. In interrupt vectors that I have experience, an address is placed at the vector. But is is looking to me like in PICS an instruction is placed there or actually block of instructions. This is the instruction generated by your interrupt_at_high_vector function.

    Apparently I was wrong about having to change the label at #pragma code. Apparently you can give that any label you want. Tha lable is just that a label but you should probably name it the same as your ISR for clarity.


    When the compiler sees #pragma code high_vector=0x08 it assigns all the code generated to a specific location. It will continue assign code to that location until another #pragma code is encountered.

    This must be why the first ISR has to be really short. #08h is the high priority interrupt vector. #18h is the low interrupt vector.

    It looks like each interrupt vector gets 8 bytes. So that is why you need to jump to a second ISR to do any real work.

    The datasheet is not 100% clear on any of this, so it is pretty much what I have figure out on my own so I could be wrong. :)
     
  16. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    The datasheet isn't usually enough. Normally you should take a look at the Reference Manual which helps a lot.
     
  17. sakishrist

    Thread Starter New Member

    Dec 4, 2009
    26
    0
    Hello. I would like ask what the Reference Manual is and where it could be found. Thank you.
     
  18. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    The datasheet only states everything in brief. The reference manual explains all those in details. It is available on the Microchip website for free.
     
  19. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    For those who program in ASM(assembler):
    Code ( (Unknown Language)):
    1.     LIST P=18F4620
    2.     #INCLUDE <P18F4620.INC>
    3.     __CONFIG _CONFIG1H, _OSC_XT_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
    4.     __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOREN_OFF_2L
    5.     __CONFIG _CONFIG2H, _WDT_OFF_2H
    6.     __CONFIG _CONFIG3H, _MCLRE_OFF_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
    7.     __CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
    8.     __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L
    9.     __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
    10.     __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L
    11.     __CONFIG _CONFIG6H, _WRTB_OFF_6H & _WRTC_OFF_6H & _WRTD_OFF_6H
    12.     __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L
    13.     __CONFIG _CONFIG7H, _EBTRB_OFF_7H
    14.  
    15.     ORG 0x00
    16.     GOTO MAIN
    17.  
    18.     ORG 0x08
    19.     GOTO ISRH
    20. ;=================================================================================
    21. ISRH
    22.     BSF        LATC, 0 ;RC0 = 1
    23.     BCF        INTCON, TMR0IF ;CLEAR FLAG
    24.     RETFIE
    25. ;=================================================================================
    26. MAIN
    27.     CLRF    TRISC
    28.     CLRF    LATC
    29.     MOVLW    0xA0
    30.     MOVWF    INTCON ;GIE AND TMR0IE
    31.     MOVLW    0x85
    32.     MOVWF    T0CON ;16-BIT, TMR0 ON, PRESCALER 1:128
    33. WAIT
    34.     GOTO    WAIT
    35. ;=================================================================================
    36.     END
    37. ;=================================================================================
    38.    
    Same program as the one I posted earlier, only in ASM instead of C.
     
  20. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,016
    I'll have to take a look again. I am not sure I saw a reference manual for my PIC (18F45K20). Or is it a general reference manual?


    Was I right on how I described (the second time) how interrupt vectors work in PICs?
     
Loading...