PIC C Programming -> Interrupts on I/O ports

Discussion in 'Embedded Systems and Microcontrollers' started by Sniperchang, Jul 1, 2009.

  1. Sniperchang

    Thread Starter New Member

    Jul 1, 2009
    6
    0
    Hello Guys,

    I'm trying to teach myself to program PICs. I'm already familiar with C, so I'm using HI-TECH C compiler (The lite version that came with MPLAB).

    I'm using a PIC12F629. IOport 0 to 2 has LEDs, and port 3 is pulled high with a button to ground. If I just do simple pooling in the main, it seems to read the button press just fine so my hardware is ok.

    So now I'm trying to get an interrupt when I press that button. However it doesn't seem to work. Here's the source code so far:

    Code ( (Unknown Language)):
    1. #include <pic.h>
    2.  
    3. #define P1 0x01;
    4. #define P2 0x02;
    5. #define P3 0x04;
    6.  
    7. void Delay(unsigned short long time);
    8. void Settings();
    9.  
    10. main()
    11. {
    12.     Settings();
    13.     GPIO=0;
    14.  
    15.     while(1){
    16.          GPIO = P1;
    17.          Delay(10000);
    18.          GPIO = P2;
    19.          Delay(10000);
    20.          GPIO = P3;
    21.          Delay(10000);
    22.     }
    23. }
    24.  
    25. interrupt isr()
    26. {
    27.     GPIO = 0x07; //Turn all three LEDs on
    28.     Delay(30000);
    29.     GPIF = 0; //Clear the port interrupt bit
    30. }
    31.  
    32.  
    33.  
    34. void Delay(unsigned short long time){
    35.  unsigned short long c;
    36.  for(c=0; c<time; c++);
    37. }
    38.  
    39. void Settings(){
    40.     TRISIO = 0x08;  // declare port as output, and GPIO3 as input
    41.     INTCON = 0b10001000; //Enable: Global, Port Change interrupt. Disable: Peripheral, TMR0 Overflow, GP2/INT External interrupt.
    42.     IOCB = 0b00001000; // Enable interupt on change for port 3.
    43. }
    Here's a link to the PIC12F629 Datasheet

    Thanks, any help is greatly appreciated.
     
  2. russ_hensel

    Well-Known Member

    Jan 11, 2009
    818
    47
    not the compiler i use, but a couple of notes:

    I would never delay in an interrupt they should be fast: set a flag and do the blinking and delay in the main loop.

    In my compiler I have to configure the interrupt in the initialization, then in the interrupt check the flag and reset.
     
  3. Sniperchang

    Thread Starter New Member

    Jul 1, 2009
    6
    0
    Thanks for the reply. Could you show me a sample code?

    Thanks
     
  4. russ_hensel

    Well-Known Member

    Jan 11, 2009
    818
    47
    I will pull something together in boostc in a day or so if you are still interested.
     
  5. Sniperchang

    Thread Starter New Member

    Jul 1, 2009
    6
    0
    Sure, I appreciate the effort.
     
  6. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    Did you look at the samples that come with the High-Tech C lite compiler?
    Look at the InterruptDemo project.
     
  7. Sniperchang

    Thread Starter New Member

    Jul 1, 2009
    6
    0
    I found it. I needed to call the ei() function to set the byte to the register.
     
  8. russ_hensel

    Well-Known Member

    Jan 11, 2009
    818
    47
    Code ( (Unknown Language)):
    1.  
    2.  
    3. Try this:
    4.  
    5. // Overview:
    6. //      A program showing a simple interupt routine to blink 2 led's
    7. //      Not hardware tested, but stripped from a program that was, so should be close at least.
    8. //      Compiles
    9. //      Author:  see: http://www.opencircuits.com/User:Russ_hensel
    10. //     
    11. //
    12. // Environment:  
    13. //      SourceBoost BoostC  6.90 full version on XP
    14. //      PIC: 16f877A
    15. //      Check: Settings -> Options -> Extra compiler options: <none>
    16. //      Check: Settings -> Options -> Extra linker options: <none>
    17. //      Check: Settings -> Options -> Tools -> Compiler and Linker Location to match your configuration
    18. //      Clock: see pragma and #define below
    19.  
    20. #include <system.h>        // always include in boostc
    21.  
    22. bool            buttonPress ;
    23. volatile bit    intf    @ INTCON.INTF;      // volatile for register that might change externally                                           // define symbolically better to read, better if you change processor
    24.  
    25.  
    26. // =========== interrupt ==========
    27. void interrupt( void )  {
    28.      
    29.     // --------- RB0/IN  
    30.     //External interrupt on the RB0/INT pin is edge triggered,
    31.     //either rising, if bit INTEDG (OPTION_REG<6>) is set,
    32.     //or falling, if the INTEDG bit is clear. When a valid edge
    33.     //appears on the RB0/INT pin, flag bit INTF
    34.     //(INTCON<1>) is set. This interrupt can be disabled by
    35.     // clearing enable bit INTE (INTCON<4>). Flag bit INTF
    36.     // must be cleared in software in the Interrupt Service ( see subroutine interrupt )
    37.     // --------------
    38.     // for each chip and interrupt read the data sheet
    39.    
    40.     if ( intf ) {                   // set on interrupt, need to reset, this is the minimum to make sure we are in the
    41.                                     // correct interrupt
    42.         clear_bit( intcon, INTF );  // alternative or better than intf = 0;  note: volatile bit intf    @ INTCON.INTF;
    43.  
    44.         buttonPress = true;         // assuming no bounce in the button -- not very safe assumption, but main line code shoul
    45.                                     // be fairly tollerent
    46.     }
    47. }
    48.  
    49.  
    50. void main()     {
    51.  
    52.     clear_bit( intcon, GIE );       // interrupts off while setting up  / set = global enable
    53.  
    54.     // setting tris one bit at a time so i do not disturbe, do not care about the other 6 bits
    55.  
    56.     trisa.0     = 0;
    57.     trisa.1     = 0;
    58.  
    59.     // --------- RB0/IN
    60.     //External interrupt on the RB0/INT pin is edge triggered,
    61.     //either rising, if bit INTEDG (OPTION_REG<6>) is set,
    62.     //or falling, if the INTEDG bit is clear. When a valid edge
    63.     //appears on the RB0/INT pin, flag bit INTF
    64.     //(INTCON<1>) is set. This interrupt can be disabled by
    65.     // clearing enable bit INTE (INTCON<4>). Flag bit INTF
    66.     // must be cleared in software in the Interrupt Service ( see subroutine interrupt )
    67.     set_bit( option_reg, INTEDG );  // set for rising edge
    68.     set_bit( intcon, INTE );        // set to enable the interrupt 
    69.  
    70.     set_bit( intcon, GIE );   // all setup go  / set = global enable
    71.    
    72.     buttonPress = false;
    73.    
    74.     while ( true ) {
    75.    
    76.         if ( buttonPress ) {
    77.             porta.0     = 1;    // turn on one led -- better if set up through #define like #define LED1 porta.0
    78.             porta.1     = 1;    // turn on the other
    79.            
    80.             delay_ms( 250 );    // beware argument is unsigned char so delay_ms( 3000 ) will not give a 3 second delay
    81.             delay_ms( 250 );
    82.             delay_ms( 250 );           
    83.             delay_ms( 250 );   
    84.             delay_s( 2 );       // finish off the last 2 seconds, could have done all 3 here
    85.                    
    86.             porta.0     = 0;    // turn off one led;
    87.             porta.1     = 0;    // the other
    88.            
    89.             // might want another delay here, else rapid pressing of button will come close to keeping the led on all the time
    90.                        
    91.             buttonPress = false;    // by putting at end here we are sort of debouncing the switch;
    92.        
    93.         }
    94.        
    95.         // main loop can go on to do more, a button press will always get a blink, but 2 presses may get only one blink
    96.        
    97.     }
    98.  
    99. }
    100.  
    101.  
    Also take a look at: http://www.opencircuits.com/A_a_Tutorial_on_PIC_interrupts_using_BoostC_including_Example_Programs

    The compile and chip are different you need to make adjustments, you may also be using a different interrupt

    Russ :D
     
  9. coopers

    New Member

    Apr 19, 2011
    1
    0
    i'm new in programme pic. i'm try to programme interrupt using push button but it doesn't seem to work. Here's the source code so far


    #include <p18f4520.h>
    #include <portb.h>

    #define LED3 PORTBbits.RB3 //output RB3
    //#define BP PORTBbits.RB0 //interruption RBO input

    unsigned char etat_led;
    unsigned char flagIT_RB0;
    static int ledstatut=0;

    //declare fonction
    void ISR(void);
    void init(void);
    void EnableHighInterrupts (void);

    void init(void)
    {
    TRISBbits.TRISB0=1; // PORT RB0 Input
    TRISBbits.TRISB3=0; //PORT RB3 Output
    LATBbits.LATB3=0; //output
    }

    #pragma code HIGH_INTERRUPT_VECTOR = 0x08 // set address 0x08
    void HighVector (void)
    {
    _asm // assembly code
    goto ISR // create vector to High interrupt service routine
    _endasm // end asm code
    }

    #pragma code // return to the code section
    #pragma interrupt ISR // tells compiler to add correct return instruction

    void ISR(void)
    {
    // clear external interrupt flag
    //if (INTCONbits.INT0IF==1) //RB0 input

    // flagIT_RB0=1;
    // LATBbits.LATB3=!LATBbits.LATB3;

    if (INTCONbits.RBIF) {
    PORTC = PORTB;
    INTCONbits.RBIF = 0;
    }
    INTCONbits.INT0IF = 0;
    if ( ledstatut = 0)
    {
    LED3 = 1;
    ledstatut = 1;
    }
    /* -fm - nous avons qu'une état possible */
    else if (ledstatut == 1)
    {
    LED3=0;
    ledstatut = 0;
    }

    INTCONbits.RBIF=0;
    }

    void EnableHighInterrupts (void) // Initialisation - Enable interrupt code
    {
    RCONbits.IPEN = 0; // enable interrupts (RCON bit 7)
    INTCONbits.GIEH = 1; // enable global interrupt
    INTCONbits.GIEL=1;
    INTCONbits.INT0IE=1; // push button
    INTCON2bits.INTEDG0=0; //choix du front
    INTCONbits.INT0IF=0;
    ADCON1=ADCON1| 0x0F;
    }

    void main (void)
    {
    init();
    EnableHighInterrupts();

    TRISB=0;
    LED3=0;

    for(;;)
    {
    if (INTCONbits.INT0IF==1) //RB0 input
    //INTCONbits.INT0IF = 0;
    {
    //LED3=!LED3;
    LATBbits.LATB3=!LATBbits.LATB3;
    flagIT_RB0=0 ;
    }
    }

    }
     
Loading...