PIC C Programming -> Interrupts on I/O ports

Thread Starter

Sniperchang

Joined Jul 1, 2009
6
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:

Rich (BB code):
#include <pic.h>

#define P1 0x01;
#define P2 0x02;
#define P3 0x04;

void Delay(unsigned short long time);
void Settings();

main()
{
    Settings();
    GPIO=0;

    while(1){
         GPIO = P1;
         Delay(10000);
         GPIO = P2;
         Delay(10000);
         GPIO = P3;
         Delay(10000);
    }
}

interrupt isr()
{
    GPIO = 0x07; //Turn all three LEDs on
    Delay(30000);
    GPIF = 0; //Clear the port interrupt bit
}



void Delay(unsigned short long time){
 unsigned short long c;
 for(c=0; c<time; c++);
}

void Settings(){
    TRISIO = 0x08;  // declare port as output, and GPIO3 as input
    INTCON = 0b10001000; //Enable: Global, Port Change interrupt. Disable: Peripheral, TMR0 Overflow, GP2/INT External interrupt.
    IOCB = 0b00001000; // Enable interupt on change for port 3.
}
Here's a link to the PIC12F629 Datasheet

Thanks, any help is greatly appreciated.
 

russ_hensel

Joined Jan 11, 2009
825
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.
 

Thread Starter

Sniperchang

Joined Jul 1, 2009
6
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.
Thanks for the reply. Could you show me a sample code?

Thanks
 

Thread Starter

Sniperchang

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

russ_hensel

Joined Jan 11, 2009
825
Thanks for the reply. Could you show me a sample code?

Thanks
Rich (BB code):
Try this:

// Overview:
//		A program showing a simple interupt routine to blink 2 led's
//		Not hardware tested, but stripped from a program that was, so should be close at least.
//		Compiles
//		Author:  see: http://www.opencircuits.com/User:Russ_hensel
//		
//
// Environment:  
//		SourceBoost BoostC  6.90 full version on XP
//		PIC: 16f877A
//		Check: Settings -> Options -> Extra compiler options: <none>
//		Check: Settings -> Options -> Extra linker options: <none>
//		Check: Settings -> Options -> Tools -> Compiler and Linker Location to match your configuration
//		Clock: see pragma and #define below

#include <system.h>        // always include in boostc

bool			buttonPress ;
volatile bit 	intf 	@ INTCON.INTF;  	// volatile for register that might change externally											// define symbolically better to read, better if you change processor 


// =========== interrupt ==========
void interrupt( void )  {
     
    // --------- RB0/IN   
	//External interrupt on the RB0/INT pin is edge triggered,
	//either rising, if bit INTEDG (OPTION_REG<6>) is set,
	//or falling, if the INTEDG bit is clear. When a valid edge
	//appears on the RB0/INT pin, flag bit INTF
	//(INTCON<1>) is set. This interrupt can be disabled by
	// clearing enable bit INTE (INTCON<4>). Flag bit INTF
	// must be cleared in software in the Interrupt Service ( see subroutine interrupt )
	// --------------
	// for each chip and interrupt read the data sheet 
	
	if ( intf ) {   				// set on interrupt, need to reset, this is the minimum to make sure we are in the 
									// correct interrupt
		clear_bit( intcon, INTF ); 	// alternative or better than intf = 0;  note: volatile bit intf 	@ INTCON.INTF;

		buttonPress = true;  		// assuming no bounce in the button -- not very safe assumption, but main line code shoul
									// be fairly tollerent
	}
}


void main()     {

	clear_bit( intcon, GIE );   	// interrupts off while setting up  / set = global enable 

	// setting tris one bit at a time so i do not disturbe, do not care about the other 6 bits

	trisa.0 	= 0;
	trisa.1 	= 0;

	// --------- RB0/IN 
	//External interrupt on the RB0/INT pin is edge triggered,
	//either rising, if bit INTEDG (OPTION_REG<6>) is set,
	//or falling, if the INTEDG bit is clear. When a valid edge
	//appears on the RB0/INT pin, flag bit INTF
	//(INTCON<1>) is set. This interrupt can be disabled by
	// clearing enable bit INTE (INTCON<4>). Flag bit INTF
	// must be cleared in software in the Interrupt Service ( see subroutine interrupt )
	set_bit( option_reg, INTEDG );  // set for rising edge
	set_bit( intcon, INTE );		// set to enable the interrupt	

	set_bit( intcon, GIE );   // all setup go  / set = global enable 
	
	buttonPress = false;
	
	while ( true ) {
	
		if ( buttonPress ) {
			porta.0		= 1;   	// turn on one led -- better if set up through #define like #define LED1 porta.0
			porta.1		= 1;	// turn on the other
			
			delay_ms( 250 );  	// beware argument is unsigned char so delay_ms( 3000 ) will not give a 3 second delay
			delay_ms( 250 );
			delay_ms( 250 );			
			delay_ms( 250 );	
			delay_s( 2 );		// finish off the last 2 seconds, could have done all 3 here
					
			porta.0		= 0; 	// turn off one led;
			porta.1		= 0;  	// the other
			
			// might want another delay here, else rapid pressing of button will come close to keeping the led on all the time
						
			buttonPress = false;	// by putting at end here we are sort of debouncing the switch;
		
		}
		
		// main loop can go on to do more, a button press will always get a blink, but 2 presses may get only one blink
		
	}

}
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
 

coopers

Joined Apr 19, 2011
1
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 ;
}
}

}
 
Top