Log in

View Full Version : Reading interupt pin as Standard IO


intellec7
15-04-2006, 13:26
I am trying to generate code that reads the pulswidth of a signal. I am avoiding use of Interupt pins 1 and 2 for later use. As my code is set up, I am trying to read the pulsewidth on pin 3. (BTW this is the Vex controller, I don't think it should make a difference though)
The code:

#define accel_x rc_dig_int3

.......
else if (INTCONbits.RBIF && INTCONbits.RBIE) /* Ints 3-6 (RB4, RB5, RB6, or RB7) changed. */
{
int_byte = PORTB; /* You must read or write to PORTB */
if(accel_x){
WriteTimer1( 0x00 );
T1CONbits.TMR1ON = 1; // turn it on
}
else if (!accel_x){
T1CONbits.TMR1ON = 0; // turn it off
accel_xTilt= ReadTimer1();
WriteTimer1( 0x00 );
}


INTCONbits.RBIF = 0; /* and clear the interrupt flag */
}


I had a suspicion that maybe I am reading the pin incorrectly, so I set up:


void Process_Data_From_Local_IO(void){
if(accel_x){printf("ON\n");}
else if (!accel_x){printf("OFF\n");}
}


It works, but it seems that there is a lag. Forexample I hooked up a normal switch to the pin. On the terminal I get
0n
0n
....
I then press the switch
0n
0n
0n
....................... (Ons for about another second)
Off
Off

It is the same for the 0ff to On transition.
I thought maybe for some reason my ISR was consuming to much time, explaining the delay, and so I took all of my code out an left the default:

...
else if (INTCONbits.RBIF && INTCONbits.RBIE) /* Ints 3-6 (RB4, RB5, RB6, or RB7) changed. */
{
int_byte = PORTB; /* You must read or write to PORTB */
INTCONbits.RBIF = 0; /* and clear the interrupt flag */
} /* to clear the interrupt condition. */




Thanks for anyhelp.

Mike
15-04-2006, 15:11
The delay may be the USART waiting for the transmit buffer to clear of "On"s before the "Off"s are being sent. Try setting a pin high/low and reading that, it is a much faster response time.

Alan Anderson
15-04-2006, 15:45
I second Mike's comment. I know the IFI loader's terminal window introduces a significant delay when there is continuous data coming in. Hyperterminal is much better.

I don't know how the Vex serial communication is implemented. It's likely that you're sending "on" and "off" messages faster than they can be transmitted, and that they're being buffered.

Greg Ross
15-04-2006, 15:57
I second Mike's comment. I know the IFI loader's terminal window introduces a significant delay when there is continuous data coming in. Hyperterminal is much better.

I don't know how the Vex serial communication is implemented. It's likely that you're sending "on" and "off" messages faster than they can be transmitted, and that they're being buffered.
Exactly. Try printing the on/off messages only when the pin state changes.

intellec7
15-04-2006, 21:10
Exactly. Try printing the on/off messages only when the pin state changes.

Alright, I did that, and I am pretty sure that was the lag I was experiencing, so now I can poll the input and if it is different from the last input I print something to the screen.

Now I'm trying to do it with interrupts, and I have the code in the ISR as so:

else if (INTCONbits.RBIF && INTCONbits.RBIE){ /* Ints 3-6 (RB4, RB5, RB6, or RB7) changed. */
int_byte = PORTB; /* You must read or write to PORTB */
INTCONbits.RBIF = 0; /* and clear the interrupt flag */
if(accel_x){
printf("High!n");
}
else if (accel_x ==0){
printf("LOW!n");
}
}


But I never get any output from the program, telling me that the interrupt is never... interrupting. Right?

[EDIT]-Stupid mistake... I never enabled interrupts by setting bit : INTCONbits.RBIE :-p

Alan Anderson
16-04-2006, 08:32
As a general rule, using printf in an interrupt service routine is a Bad Idea. The serial communication library routines might handle it without causing issues...or they might not.

ISRs should be reserved for things which take approximately no time to perform. Make a comparison, set a flag, store a value, maybe compute a delta or a sum. But try not to start something which will require waiting for something else to happen.

intellec7
16-04-2006, 20:42
As a general rule, using printf in an interrupt service routine is a Bad Idea. The serial communication library routines might handle it without causing issues...or they might not.

I was just doing that to see when the ISR was running.
My actual code is

else if (INTCONbits.RBIF && INTCONbits.RBIE){ /* Ints 3-6 (RB4, RB5, RB6, or RB7) changed. */
int_byte = PORTB; /* You must read or write to PORTB */
INTCONbits.RBIF = 0; /* and clear the interrupt flag */

if(accel_x){
//Here it measures the Low time
T1CONbits.TMR1ON = 0; // turn it off
accel_xTiltC=ReadTimer1();
WriteTimer1( 0x00 );
T1CONbits.TMR1ON = 1; // turn it on
Status = 2;
}
else if (accel_x ==0){
//This time it measures the High time
T1CONbits.TMR1ON = 0; // turn it off
accel_xTilt= ReadTimer1(); //capture timer value
WriteTimer1( 0x00 );
T1CONbits.TMR1ON = 1; // turn it on
Status = 1;
}
}


accel_xTilt is an unsigned integer, and since Timer1 is configured as a 16 bit timer, that should be suffice to hold any timer value right? But from 6ms - 4 ms I get negative values! I thought maybe for some reason it was wrapping around and doing something funny, so when I made it a long I got all zero values.
Does anyone have code that does frequency/duty cycle measurement?

Alan Anderson
16-04-2006, 21:59
accel_xTilt is an unsigned integer, and since Timer1 is configured as a 16 bit timer, that should be suffice to hold any timer value right? But from 6ms - 4 ms I get negative values! I thought maybe for some reason it was wrapping around and doing something funny, so when I made it a long I got all zero values.
You probably had the right values in the accel_xTilt variable, but printf() has difficulty showing anything other than an int unless you cast things just right.

intellec7
16-04-2006, 22:25
You probably had the right values in the accel_xTilt variable, but printf() has difficulty showing anything other than an int unless you cast things just right.

How did you know :-p. I had %d with an unsigned int... changed it to %u and voila. Thanks for your help.