Exact match. Not showing close matches.
PICList
Thread
'[PIC]: RB0 Interrupt Edge Triggering'
2003\08\20@192808
by
raham Cheetham
|
Hi,
I am developing a simple hardware delay device on a 16F876 using MPLAB and Hitech C. An overkill I know.
The code configures the ports, timers and interrupts as required,
- RB0 as input, RB1-7 as outputs
- interrupt on RB0 falling edge
- timer interrupt every 40 ms. (PAL video frame rate)
It looks for a falling edge on RB0 which generates an interrupt, the interrupt routine starts a software counter. The timer takes over incrementing the counter. When the counter reaches the required setting it drives an output low, RB1, and starts another software counter, which when done resets the output to high.
There are two problems -
1. The INTF interrupt is generated on any edge, rising or falling, when it should only be on the falling edge.
2. Clearing the INTE doesn't disable the interrupt. I am trying to disable the interrupt after the initial falling edge and then continue to process the timer interrupt. Then later re-enable the RB0 interrupt.
I searched the archive but couldn't find anything relevant.
Can anyone help?
Is there a know issue with this device and edge triggering?
Relevant source code below.
// 7 Cue Delay.c
// pic 16F876
#include <pic.h>
#define PIC_CLK 4000000
#include "7cue_dly.h"
__CONFIG(FOSC0 | UNPROTECT );
#define LED RA0
#define STBY_IN RB0
#define CUE_OUT RB1
#define STANDBY_LED RB6
#define CUE_LED RB7
#define ON 1
#define OFF 0
static unsigned int cCueDelayCnt;
static unsigned char cStdbyRx;
static unsigned char cCue;
main()
{
TRISB = 0b00000001; // Set RB1 as i/p and RB2 ->7 as o/ps
OPTION = 0b00000000; // Set Option reg for weak pullup, on falling edge of RB0 etc
// OPTION = 0b01000000; // Set Option reg for weak pullup, INT on rising edge of RB0 etc
cCueDelayCnt = 0;
cStdbyRx = OFF;
cCue = OFF;
CUE_OUT = ON;
CUE_LED = OFF;
STANDBY_LED = OFF;
init_interrupts();
while(1){
// Let interrupt handler do everything
}
}
void interrupt handler()
{
di();
if(INTF == 1){
cCueDelayCnt = 0;
cStdbyRx = ON;
STANDBY_LED = ON;
cCue = OFF;
INTE = 0; // Disable RB0 int
INTF = 0; // clear flag
// INTE = 0; // Disable RB0 int
}
if(TMR1IF == 1){
if(cCue == ON){
cCueDelayCnt = cCueDelayCnt + 1;
if(cCueDelayCnt == 12){ // 150 frames = 6 seconds
// 25 frames = 1 second
CUE_OUT = ON; cCueDelayCnt = 0;
cCue = OFF;
CUE_LED = OFF;
STANDBY_LED = OFF;
INTE = 1; // Enable RB0 int
INTF = 0; // clear flag
} }
if(cStdbyRx == ON){
cCueDelayCnt = cCueDelayCnt + 1;
if(cCueDelayCnt == 37){ // 600 frames = 24 seconds
// 37 frames = 1s 12f
CUE_OUT = OFF; cStdbyRx = OFF;
cCueDelayCnt = 0;
cCue = ON;
CUE_LED = ON;
} }
TMR1L = 0x77; // load 60535
TMR1H = 0xec;
TMR1IF = 0; // clear flag
}
ei();
}
void init_interrupts()
{
// timer 1 for 40mSec (1 Video frame) tick
// 4Mhz/4 Clock with prescale of 1:8 with Timer 1 preload of 60,535 , gives 40mSec tick
// Enable RB0 interrupt for falling edge
INTCON = 0; // disable all ints
PIE1 = 0;
PIE2 = 0;
T1CON = 0b00110001; // 1:8 Prescaler, internal clock and enable Timer 1
TMR1L = 0x77; // load 60535
TMR1H = 0xec;
TMR1IF = 0; // clear flag
INTF = 0; // clear RB0 interrupt flag
TMR1IE = 1; // Enable Timer 1 int
INTE = 1; // Enable RB0 int
PEIE = 1; // Enable Peripheral int
ei(); // enable ints
}
Thanks for your help.
Regards,
Graham Cheetham spam_OUTgcheethamTakeThisOuT
southerncrossqld.com.au Regards, Graham Cheetham Software & Systems Engineer Southern Cross Ten Queensland Townsville Office 07 4726 2074
Switch 07 4726 2000
Fax 07 4726 2109
.....gcheethamKILLspam
@spam@southerncrossqld.com.au
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
2003\08\20@213825
by
Richard.Prosser
|
I don't know about chip problems, but is it possible you are getting
ringing or noise on your interrupt line?
That could explain at least part of the problem. (but you should still be
able to disable the interrupt)
Try adding a rc filter if there's nothing there at the moment - especially
if the line is long or subject to noise injection etc.
RP
Graham Cheetham
<gcheetham@SOUTHERNCROSSQ To: PICLIST
KILLspamMITVMA.MIT.EDU
LD.COM.AU> cc:
Sent by: pic Subject: [PIC]: RB0 Interrupt Edge Triggering
microcontroller
discussion list
<.....PICLISTKILLspam
.....MITVMA.MIT.EDU>
21/08/03 11:16
Please respond to pic
microcontroller
discussion list
Hi,
I am developing a simple hardware delay device on a 16F876 using MPLAB and
Hitech C. An overkill I know.
The code configures the ports, timers and interrupts as required,
- RB0 as input, RB1-7 as outputs
- interrupt on RB0 falling edge
- timer interrupt every 40 ms. (PAL video frame rate)
It looks for a falling edge on RB0 which generates an interrupt, the
interrupt routine starts a software counter. The timer takes over
incrementing the counter. When the counter reaches the required setting it
drives an output low, RB1, and starts another software counter, which when
done resets the output to high.
There are two problems -
1. The INTF interrupt is generated on any edge, rising or falling, when it
should only be on the falling edge.
2. Clearing the INTE doesn't disable the interrupt. I am trying to disable
the interrupt after the initial falling edge and then continue to process
the timer interrupt. Then later re-enable the RB0 interrupt.
I searched the archive but couldn't find anything relevant.
Can anyone help?
Is there a know issue with this device and edge triggering?
Relevant source code below.
// 7 Cue Delay.c
// pic 16F876
#include <pic.h>
#define PIC_CLK 4000000
#include "7cue_dly.h"
__CONFIG(FOSC0 | UNPROTECT );
#define LED RA0
#define STBY_IN RB0
#define CUE_OUT RB1
#define STANDBY_LED RB6
#define CUE_LED RB7
#define ON 1
#define OFF 0
static unsigned int cCueDelayCnt;
static unsigned char cStdbyRx;
static unsigned char cCue;
main()
{
TRISB = 0b00000001; // Set RB1 as i/p and RB2 ->7 as o/ps
OPTION = 0b00000000; // Set Option reg for weak pullup, on falling
edge of RB0 etc
// OPTION = 0b01000000; // Set Option reg for weak pullup, INT on
rising edge of RB0 etc
cCueDelayCnt = 0;
cStdbyRx = OFF;
cCue = OFF;
CUE_OUT = ON;
CUE_LED = OFF;
STANDBY_LED = OFF;
init_interrupts();
while(1){
// Let interrupt handler do everything
}
}
void interrupt handler()
{
di();
if(INTF == 1){
cCueDelayCnt = 0;
cStdbyRx = ON;
STANDBY_LED = ON;
cCue = OFF;
INTE = 0; // Disable RB0 int
INTF = 0; // clear flag
// INTE = 0; // Disable RB0 int
}
if(TMR1IF == 1){
if(cCue == ON){
cCueDelayCnt = cCueDelayCnt + 1;
if(cCueDelayCnt == 12){ // 150 frames = 6 seconds
// 25 frames = 1 second
CUE_OUT = ON;
cCueDelayCnt = 0;
cCue = OFF;
CUE_LED = OFF;
STANDBY_LED = OFF;
INTE = 1; // Enable RB0 int
INTF = 0; // clear flag
}
}
if(cStdbyRx == ON){
cCueDelayCnt = cCueDelayCnt + 1;
if(cCueDelayCnt == 37){ // 600 frames = 24 seconds
// 37 frames = 1s 12f
CUE_OUT = OFF;
cStdbyRx = OFF;
cCueDelayCnt = 0;
cCue = ON;
CUE_LED = ON;
}
}
TMR1L = 0x77; // load 60535
TMR1H = 0xec;
TMR1IF = 0; // clear flag
}
ei();
}
void init_interrupts()
{
// timer 1 for 40mSec (1 Video frame) tick
// 4Mhz/4 Clock with prescale of 1:8 with Timer 1 preload of 60,535
, gives 40mSec tick
// Enable RB0 interrupt for falling edge
INTCON = 0; // disable all ints
PIE1 = 0;
PIE2 = 0;
T1CON = 0b00110001; // 1:8 Prescaler, internal clock and enable
Timer 1
TMR1L = 0x77; // load 60535
TMR1H = 0xec;
TMR1IF = 0; // clear flag
INTF = 0; // clear RB0 interrupt flag
TMR1IE = 1; // Enable Timer 1 int
INTE = 1; // Enable RB0 int
PEIE = 1; // Enable Peripheral int
ei(); // enable ints
}
Thanks for your help.
Regards,
Graham Cheetham
EraseMEgcheethamspam_OUT
TakeThisOuTsoutherncrossqld.com.au
Regards,
Graham Cheetham
Software & Systems Engineer
Southern Cross Ten Queensland
Townsville
Office 07 4726 2074
Switch 07 4726 2000
Fax 07 4726 2109
gcheetham
spam_OUTsoutherncrossqld.com.au
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
2003\08\20@213833
by
piclist
On Thu, 21 Aug 2003, Graham Cheetham wrote:
> There are two problems -
> 1. The INTF interrupt is generated on any edge, rising or falling, when it should only be on the falling edge.
> 2. Clearing the INTE doesn't disable the interrupt.
> __CONFIG(FOSC0 | UNPROTECT );
The default state of the watchdog timer is "on." You're not clearing
it in your code, so you're probably resetting frequently.
> void interrupt handler()
> {
>
> di();
> ei();
Don't manipulate the global interrupt flag in the interrupt handler.
> if(INTF == 1){
If you're disabling INTE, that doesn't prevent INTF from being set.
Your test should be
if (INTE && INTF)
--
John W. Temples, III
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
2003\08\20@235730
by
raham Cheetham
|
> > There are two problems -
> > 1. The INTF interrupt is generated on any edge, rising or
> falling, when it should only be on the falling edge.
> > 2. Clearing the INTE doesn't disable the interrupt.
There has been a suggestion of glitching on the RB0 input. But I thought that after the first interrupt, (glitching possible during manual testing), the RB0 interrupt should be disabled until after the two timeouts periods, where it is re-enabled.
> > __CONFIG(FOSC0 | UNPROTECT );
>
> The default state of the watchdog timer is "on." You're not clearing
> it in your code, so you're probably resetting frequently.
The assembly code listing from the compiler shows the WDTE bit set to zero, which is off.
> > void interrupt handler()
> > {
> >
> > di();
> > ei();
>
> Don't manipulate the global interrupt flag in the interrupt handler.
I'll give that a try removing these.
>
> > if(INTF == 1){
>
> If you're disabling INTE, that doesn't prevent INTF from being set.
> Your test should be
>
> if (INTE && INTF)
I still don't understand that if INTE is off (set to zero) how an interrupt can be generated.
Thanks.
Graham Cheetham
--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads
2003\08\21@004726
by
piclist
On Thu, 21 Aug 2003, Graham Cheetham wrote:
> > If you're disabling INTE, that doesn't prevent INTF from being set.
> > Your test should be
> >
> > if (INTE && INTF)
>
> I still don't understand that if INTE is off (set to zero) how an
> interrupt can be generated.
As the datasheets says, "Individual interrupt flag bits are set,
regardless of the status of their corresponding mask bit, or the GIE
bit."
An interrupt is not being generated, but your software is testing the
INTF flag, regardless of the reason that it is executing the ISR.
I.e., when your timer interrupt pops, your test for INTF will be true
if there has been an RB0 edge, regardless of the state of INTE.
--
John W. Temples, III
--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics
2003\08\21@021716
by
raham Cheetham
> On Thu, 21 Aug 2003, Graham Cheetham wrote:
>
> > > If you're disabling INTE, that doesn't prevent INTF from
> being set.
> > > Your test should be
> > >
> > > if (INTE && INTF)
> >
> > I still don't understand that if INTE is off (set to zero) how an
> > interrupt can be generated.
>
> As the datasheets says, "Individual interrupt flag bits are set,
> regardless of the status of their corresponding mask bit, or the GIE
> bit."
>
> An interrupt is not being generated, but your software is testing the
> INTF flag, regardless of the reason that it is executing the ISR.
> I.e., when your timer interrupt pops, your test for INTF will be true
> if there has been an RB0 edge, regardless of the state of INTE.
>
Thank you - it is making sense now. I will go and redo the code.
Graham Cheetham
--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics
2003\08\21@075809
by
Olin Lathrop
> 1. The INTF interrupt is generated on any edge, rising or falling, when
> it should only be on the falling edge.
No, it's not. If your signal is bouncing it can appear that way.
> 2. Clearing the INTE doesn't disable the interrupt.
Yes, it does.
You have to stop looking at the chip as the source of the problems. The
problem is in your software. Humility is important for debugging. Until
you start looking for what YOU screwed up, you have little chance of
finding it.
*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com
--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics
2003\08\21@090041
by
Mike Hord
> > If you're disabling INTE, that doesn't prevent INTF from being set.
> > Your test should be
> >
> > if (INTE && INTF)
>
>I still don't understand that if INTE is off (set to zero) how an interrupt
>can be generated.
It isn't; your periodic interrupt occuring, and during the course of testing
for
that interrupt, the INTF flag is spotted, causing the machine to
inadvertantly
go of course and service the INT interrupt.
Or at least, that's what would be happening if this were written in
assembler.
I don't know if the C compiler is smart enough to catch that little snafu.
Mike H.
_________________________________________________________________
<b>Help protect your PC:</b> Get a free online virus scan at McAfee.com.
http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963
--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics
2003\08\21@092806
by
hael Rigby-Jones
> > > If you're disabling INTE, that doesn't prevent INTF from being set.
> > > Your test should be
> > >
> > > if (INTE && INTF)
> >
> >I still don't understand that if INTE is off (set to zero) how an
> interrupt
> >can be generated.
>
> {Original Message removed}
2003\08\21@160132
by
Igor Pokorny
It's a bit cruel true, don't think? I'v had such problem years ago. When I
use TMR0 to count frequency of an external signal everything was fine. Using
a prescaler I obtained different results. The 100 pF cap to ground solved
the problem.
Igor
{Original Message removed}
2003\08\21@162007
by
Igor Pokorny
Try to test if both INTE and INTF are set before doing anything in your
interrupt procedure.
Igor
{Original Message removed}
More... (looser matching)
- Last day of these posts
- In 2003
, 2004 only
- Today
- New search...