Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Setting up an interrupt


#1

Hello,

I am new to the Wixel and TI processor line. Also I have only done a few projects (3) and they used PICs.

I am trying to setup up a simple interrupt based on an input. No joy.

Here is the code:

#include <wixel.h>
#include <usb.h>
#include <usb_hid.h>
#include <gpio.h>
#include <board.h>
#include <stdio.h>
#include <cc2511_map.h>

unsigned char P0_0_interrupt;

SFRBIT(0x89, P0IFG, P0_7_INT, P0_6_INT, P0_5_INT, P0_4_INT, P0_3_INT, P0_2_INT, P0_1_INT,P0_0_INT)
SFRBIT(0x8C, PICTL, _PICTL_7, PICTL_6, P2IEN, P0IENH, P0IENL, P2ICON, P1ICON, P0ICON)

ISR(P0INT,0)
{
 if (P0_0_INT)
  {
   P0_0_interrupt = 1;
   P0_0_INT = 0;		//clear it
  }
}

void initialize()
{
    systemInit();
	usbInit();
	
							//setup a falling edge interrupt on P0_1.
	setDigitalInput(0,1);	//pull P0_0 high. I connected the switch to ground 
	P0IENL = 1;   			//Port 0, inputs 3 to 0 interrupt enable
	P0IE = 1;				//enable port 0 interrupts
	  
}


void main()
{
	initialize();

    while(1)
    {
	
    if (P0_0_interrupt == 1)
	 { 
	  LED_RED_TOGGLE();
	  P0_0_interrupt = 0;
	 }
	 
    }
}

Can anyone tell me what I am missing or doing wrong?

Thanks,

Mark


#2

Hello, Mark.

The SFRBIT macro can only be used with SFRs with an address that is a multiple of 8. You should use the definitions provided by cc2511_map.h to access PICTL and P0IFG. If you continue to have trouble, please post a description of how you are testing the code along with the expected behavior and the actual behavior.

–David


#3

Hi,

Thanks for the reply.

The SFRBIT macro can only be used with SFRs with an address that is a multiple of 8

Where is that documented?

You should use the definitions provided by cc2511_map.h to access PICTL and P0IFG.

I tried that but could not get it to work so shifted to SFRBIT to make it cleaner.

how you are testing the code along with the expected behavior and the actual behavior.

Simple, as the code shows, push the button and toggles the red state.

I will go back to the bit twiddling and if I can not get it to work will post the code.

Can you tell me if I am at least setting/reading the correct interrupt flags/enables?

Mark


#4

The SFRBIT macro is not documented at all because it is not intended to be used outside of cc2511_map.h. That macro uses the __sbit keyword. The documentation of __sbit in the SDCC Manual (version 3.4.1, section 3.5.1.7) says:

Since you are enabling interrupts on four pins (P0_0, P0_1, P0_2, and P0_3), you probably need to clear the P0IFG flags for all of those pins in your ISR or else you risk getting stuck in the ISR forever. After clearing those, it looks like you need to clear IRCON.P0IF. During initialization, you should write “EA = 1;” to explicitly enable interrupts instead of depending on the Wixel libraries to do it for you. The P0_0_interrupt variable should be volatile. There might be more issues that I have not thought of.

–David


#5

Hi David,

Thanks for the reply.

I asked about SFRBIT documentation because it is listed in the Wixel SDK help and it does not include any warnings about alignment. I know it is documenting the .h file.

I have the test code working and thought I would post it for anyone in the future.

Thanks again,

Mark

#include <wixel.h>
#include <usb.h>
#include <usb_hid.h>
#include <gpio.h>
#include <board.h>
#include <stdio.h>
#include <cc2511_map.h>

unsigned char P0_0_interrupt;

//P0IFG interrupt status port 0
//PICTL bit 3 interrupt control port 0, input 0-3
//IEN0 Interrupt Enable for many
//IEN1 Interrupt Enable 0 Register

ISR(P0INT,0)
{
 if (P0IFG & 0b00000001)
  {
   P0_0_interrupt = 1;
  }
 P0IFG = 0;					//clear them all, safety
 IRCON &= 0b10011111;		//clear port 0 flag and docs say bit six must always be 0
}

void initialize()
{
    systemInit();
	usbInit();
							//setup a falling edge interrupt on P0_1.
	PICTL = 0b00001001;   	//Port 0, inputs 3 to 0 interrupt enable, only for now 
							//and falling edge interrupt
	IEN1 = 0b00100000;		//enable port 0 interrupts
	EA = 1;					//enable all interrupts  
	
}

void main()
{
	initialize();

    while(1)
    {
	
    if (P0_0_interrupt == 1)
	 { 
	  LED_RED_TOGGLE();
	  P0_0_interrupt = 0;
	 }
	 
    }
}

#6

Hello,

I have three analog inputs P0_0 to P0_2. I would like to trigger an interrupt either on both falling or rising edge. With the published code it will be either rising or falling edge? If I use Timer 1 in input capture mode can I get the desired results? T1CCTL0 = 0b01000011 and T1CC0H:T1CC0L = 0x0BB7? Using Timer 1 helps in capturing the time of event?

Appreciate your help.

Regards


#7

Hello.

The comments in Mark’s code mention four registers that are important for for setting up interrupts: P0IFG, PICTL, IEN0, and IEN1. I recommend reading the documentation of each of these registers in the CC2511F32 datasheet. In particular, PICTL has some bits in it that let you specify a falling edge or a rising edge, and Mark chose the falling edge in his code above. The chip does not directly support interrupting on both a rising edge and a falling edge, but you could probably use one pin to detect falling edges and another pin on a different port to detect rising edges of the same signal.

I have not tried using Timer 1 in input capture mode, but it might work for you. Alternatively, you might consider letting Timer 1 run freely and then reading its count register in your interrupt. If your interrupt has the highest priority of all the active interrupts in the system, that should give you readings that are accurate to within a few instruction cycles.

–David


#8

Also note that you should use volatile keyword for the P0_0_interrupt variable so that the compiler does not optimize it away.

br