pic18f4550 code example & interrupts

2007-07-16
2013-03-12
  • Francesco Orsenigo

    I'm quite new in the wonderful world of microcontroller programming, and have just recently managed to move the developement environment from MPLAB to linux/sdcc.

    I'm having trouble finding documentation for the very basics.

    When declaring interrupts, how do i find out which number X corresponds to each interrupt?
    For example: "void timerISR() __interrupt (X) {}" what do i put as "X"?
    The sdccman.pdf tells me the numbers for some CPUs, but not for pic18.

    Where do i get information about how to use all those "code char at __CONFIG1H _conf0 = ..." in a pic18?

    Could someone point me to some code sample where interrupts are used?

    Thanks a lot!
    Francesco

     
    • Raphael Neider

      Raphael Neider - 2007-07-16

      From sdcc.sf.net, Dokumentation / SDCC Manual (.pdf), i.e. http://sdcc.sourceforge.net/doc/sdccman.pdf, see Section 4.6.14, p. 67.
      The PIC18 port offers 3 interrupt numbers:
      0 RESET handler
      1 HIGH priority interrupts
      2 LOW priority interrupts

      HIGH and LOW refer to the setup of the device; you need to assign each interrupt source to one of HIGH of LOW using the <source>IP bit (e.g., TMR0IP).

      Individual signal handlers (i.e., handlers for a particular interrupt source such as a timer or the UART), you can use the macros defined in signals.h (see Manual, Section 4.6.16.3---OK, this could be placed better...). There is even an example on how to use them (copied from the manual):

      #include <pic18fregs.h>
      #include <signal.h>

      /* This creates the dispatcher for HIGH priority interrupt sources. */
      DEF_INTHIGH(high_int)
      DEF_HANDLER(SIG_TMR0, _tmr0_handler)
      DEF_HANDLER(SIG_BCOL, _bcol_handler)
      END_DEF

      /* This creates a handler for a particular source.
      ** Make sure it is referenced in the dispatcher code! */
      SIGHANDLER(_tmr0_handler)
      {
      /* action to be taken when timer 0 overflows */
      }

      SIGHANDLERNAKED(_bcol_handler)
      {
      _asm
      /* action to be taken when bus collision occurs */
      retfie
      _endasm;
      }

      For the config words, you need to look into your device's data sheet, figure out which you need to set and then use
      __code char __at(__CONFIG1H) _conf1h = 0xFF & _OSC_XT__XT_PLL__USB_XT_1H & ...;

      The names are automatically geenrated and often ridiculously longish and can only be obtained from looking into the device header file, located next to the pic18fregs.h (sdcc/device/include/pic16/ in the sources, probably /usr/share/sdcc/include/pic16/ when installed?).
      If no values are specified, the device defaults are used, which is often (???) OK for testing...

      HTH,
      Raphael

       
    • Francesco Orsenigo

      Thanks for the prompt help!
      I totally missed the manual part dedicated to the pic16 port (i fear i had an obsolete version...) and tried to follow them step-by-step.

      Unfortunately, I still fail to get an interrupt: namely, i try to increase a variable with the timer interrupt, but i detect no change.
      Here's the code:

      /* =========================================================================
        MAIN.C    v0.00
      */

      #include <signal.h>
      #include "pin.h"

      volatile int cnt = 0;

      DEF_INTHIGH(high_int)
      DEF_HANDLER(SIG_TMR0, _tmr0_handler)
      END_DEF

      SIGHANDLER(_tmr0_handler)
      {
      //    TMR0L = 0xb2;
          cnt++;
      //    INTCONbits.TMR0IE = 0;
      }

      void main()
      {
      int i;

      PIN_INIT();
      T0CONbits.TMR0ON = 1;

      while(1)
      {
          i = cnt;

          LED_CHRONO =    (i>>2)&1;
          LED_SPEED =        (i>>8)&1;
          LED_AVG =        (i>>11)&1;

          LED_REVAUTO =    (i>>12)&1;
          LED_REVREV =    (i>>11)&1;
          LED_REVOFF =    (i>>13)&1;

          LED_STARTED =    1; //(i>>15)&1;
      }
      }
      //EOF =========================================================================

      ----

      /* ============================================================================
        PIN.H        v0.00

        This file will contain everything compiler- and chip specific:
          pin definitions
          interrupt calls
      */
      #ifndef H_FILE_PIN
      #define H_FILE_PIN
      //=============================================================================
      #include <pic18fregs.h>

      #define LED_SPEED    PORTAbits.RA0
      #define LED_REVREV    PORTBbits.RB2
      #define BUZZER        PORTBbits.RB3
      #define LED_REVOFF    PORTBbits.RB4
      #define LED_REVAUTO    PORTBbits.RB5
      #define LED_CHRONO    PORTCbits.RC6
      #define LED_AVG        PORTCbits.RC7
      #define LED_STARTED    PORTEbits.RE1

      /*
      * INIT
      */
      #define __bit(a,b,c,d, e,f,g,h)            \     ((a&1)<<7) | ((b&1)<<6) | ((c&1)<<5) |    \     ((d&1)<<4) | ((e&1)<<3) | ((f&1)<<2) |    \     ((g&1)<<1) | ((h&1))            \

      #define PIN_INIT()        \     ADCON1bits.PCFG0 = 1;    \     ADCON1bits.PCFG1 = 1;    \     ADCON1bits.PCFG2 = 1;    \     ADCON1bits.PCFG3 = 1;    \     TRISA = __bit(1,0,1,1,1,1,1,0);    PORTA = 0;    \     TRISB = __bit(0,0,0,0,0,0,1,1);    PORTB = 0;    \     TRISC = __bit(0,0,1,1,1,0,0,0);    PORTC = 0;    \     TRISD = __bit(0,0,0,0,0,0,0,0);    PORTD = 0;    \     TRISE = __bit(1,1,1,1,1,1,0,1);    PORTE = 0;    \

      #endif
      //EOF =========================================================================

      ---

      Whenever i make a program that does not rely on the timer, my leds work like a charm (except for REVAUTO on RB5).
      When i try to use the timer counter, all timer-controlled LEDS stay off, just as if the counter is not increased.

      I compiled with:

      sdcc -mpic16 -p18f452 --mplab-comp main.c

      SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.7.2 #4862 (Jun 27 2007) (UNIX)

      I guess i'm missing something important, but I have no clue what.
      Once more, thanks a lot for the help!

       
      • Raphael Neider

        Raphael Neider - 2007-07-17

        Are the global interrupt enable flags (INTCON.GIE, INTCON.PEIE) set? Is INTCON.TMR0IE set? Also check RCON.IPEN to determine whether the HIGH/LOW priority feature is enabled or not. If it is, also check if TMR0IP is 1 to associate Timer0 with HIGH interrupt priority. You might also consider duplicating your DEF_INTHIGH(high_int) definition for DEF_INTLOW(low_int) just to make you are not unexpectedly getting Timer0 interrupts on the LOW priority level...

        You should explicitly setup all bits related to the timer (i.e., initialize the complete T0CON register, INTCON, RCON, TMR0L and TMR0H). Check with your device's data sheet which registers are related to the interrupt source.

        Good luck,
        Raphael

         
    • Francesco Orsenigo

      Problem solved =)
      I had forgot to set

      T0CONbits.T0CS = 0;

      Thanks to everyone for the patiece =)
      I'm writing quite a complete program, hopefully i'll be able to post it, examples for pic18whatever are badly needed.

       

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks