|
|
View previous topic :: View next topic |
Author |
Message |
JimB
Joined: 25 Aug 2005 Posts: 65 Location: Huntington Beach, CA
|
EXT_INT_EDGE() How to disable and then enable? |
Posted: Wed Apr 19, 2006 1:02 am |
|
|
I am using the 16F877A and am generating a square wave (18KHz) using the PCW generator. I then feedback this signal to the RB0/INT pin to use the falling edge to trip the interrupt. (Couldn't figure out how to do this internally.) Then I want to wait until the square wave is high by using delay_us(X) in the ISR to have the A/D read the same square wave during its high portion of the cycle after being processed by external electronics that varies its amplitude and is then fed to pin AN0. From what I have read in the data sheet, I need to disable the interrupt before enabling it to insure that it has not all ready been tripped. However, in the 16F877A.h file, the enable/disable_interrupts(), EXT_INT_EDGE is not a choice. I want to read say 10 or 20 such readings and average them so disable/enable must be done repeatedly.
Is clear_interrupts the same function as disable_interrupts?
So the question is how does one disable this interrupt and then enable it? Or am I totaly off base? |
|
|
Ttelmah Guest
|
|
Posted: Wed Apr 19, 2006 4:45 am |
|
|
Disabling the interrupt, does not clear it. That is why there is a 'CLEAR_INTERRUPT' function.
The functions interact as follows:
Interrupt handler will be called if, the interrupt flag is set (hardware event), _and_ the interrupt is enabled, _and_ the global interrupt flag is enabled.
Clear_interrupt, clears the corresponding hardware interrupt flag, but does not affect the status of the enable/disable controls. Enabling/disabling the interrupt does not effect the interrupt flag itself.
Now there are potential problems with what you describe. At 18KHz, on a PIC at 20MHz (assuming you are running the maximum rate your chip supports), there are just 277 instruction times between interrupts. It'll take the best part of 40 instruction times, to actually arrive inside the handler routine. If you then wait in the routine for the other edge of the clock, you will now be at 134 instruction times after the 'event'. At this point the analog signal exists, but you then need to wait for the internal ADC capacitor to charge (typically over 100 instruction times on this chip....), then take the ADC reading (typically another 96 instruction times...). At this point you have already missed the next edge...
To sample at this sort of rate, you are going to need to consider using a faster ADC, or adding a sample/hold circuit, so that you don't have to wait for the signal to become 'present' for just part of the cycle. You really also may be better of considering just 'polling' the event, rather than using interrupts (the 'problem' of interrupts, is the amount of extra delay involved in calling the handler...).
Best Wishes |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Apr 19, 2006 11:00 am |
|
|
Quote: |
However, in the 16F877A.h file, the enable/disable_interrupts(), EXT_INT_EDGE is not a choice.
|
Not exactly.
PIC16F877A Datasheet, Section 2.2.2.2
OPTION_Reg Register.
Bit 6: INTEDG Interrupt Edge Select Bit.
1 = Interrupt on rising edge of RB0/INT pin
0 = Interrupt on falling edge of RB0/INT pin
From the interrupts capabilities point of view, the difference between
16F877 and 16F877A is the INT_COMP feature only available in the last one.
Humberto |
|
|
JimB
Joined: 25 Aug 2005 Posts: 65 Location: Huntington Beach, CA
|
It gets worse |
Posted: Wed Apr 19, 2006 6:35 pm |
|
|
First of all thanks for the input.
My processor is running at 5MHz rather than the 20MHz. So I clearly need to take hard look at things. My hardware is commited at this time so I am considering slowing the square wave way down.
I do have a couple of questions.
How did you arrive at these counts? I assume they are Osc/4 time periods.
What did you mean by polling? I know what polling means and that would mean hit or miss data, unless a S&H was implemented. What am I missing?
If I can slow the square wave down slow enough to get back to my original approach then the commands would be something like this:
clear_interrupt(EXT_INT_EDGE(H_to_L));
enable_interrupts(????); what goes in here????
enable interrupts(global);
while(i<+9)
{
EXT_INT_EDGE(H_to_L));
go to isr; delay for the proper time on the square wave
value=value+read_adc(0);
delay_us(XX);
clear_interrupts(EXT_INT_EDDGE(H_to_L));
i++
} |
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 20, 2006 10:48 am |
|
|
Interesting.
I posted a reply that other day, and yet it doesn't seem to have appeared...
'Polling', would simply be looking for the level. However there is another form of 'polling', in that you can use the interrupt hardware, and 'poll' the flag.
So if you set the chip to 'interrupt' on the rising edge (say), and then clear the interrupt, and have this disabled, the interrupt _flag_ will be set on the event. You can simply sit reading the flag (set the required bit with the #bit statement), and advance when it sets.
The response time will then just be a couple of instruction times.
Then wait for the chip's ADC acquisition time (just under 20uSec), trigger the ADC (20uSec to take a reading), and you have the value.
Both the acquisition time, and the reading time, can be quicker on latter chips (hardware changes).
Best Wishes |
|
|
JimB
Joined: 25 Aug 2005 Posts: 65 Location: Huntington Beach, CA
|
Now that's very clever. |
Posted: Thu Apr 20, 2006 12:57 pm |
|
|
Thanks very much. As a novice to this I wouldn't have come up with that approach. Very nice.
I think that I have things working by slowing down my 18KHz to 1KHz as a start. I will start increasing it until I see problems again or give your suggestion a try. I am running against a deadline.
To enable and clear the EXT_INT_EDGE() interrupt, I used the INT_EXT function.
Problem is I coudn't, for sure, determine that INT_EXT will clear the flag for EXT_INT_EDGE() based on the existing documentation. Is this a correct statement?
As for the posting problem, I entered replies that were placed into a message to myself a couple of times rather than in a reply to the topic.
Jim |
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 20, 2006 2:16 pm |
|
|
The instruction to clear the interrupt, is 'clear_interrupt(INT_EXT')'. There is no 'INT_EXT' statement?.... INT_EXT, is a 'flag' to other commands, telling them which interrupt is involved. So '#INT_EXT', is an instruction that the following subroutine is the handler for a particular interrupt, 'enable_interrupt(INT_EXT)', is a command to enable this interrupt, etc. etc..
If your compiler is old, there is no clear interrupt function, so this will need to be coded as a bit definition, and done 'manually'.
Best Wishes |
|
|
JimB
Joined: 25 Aug 2005 Posts: 65 Location: Huntington Beach, CA
|
That's what I meant to say. |
Posted: Thu Apr 20, 2006 3:34 pm |
|
|
Yes that appears to work for me. However, it was a little bit of a guess since the documentation was not clear regarding that. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|