![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
Help: 16F877A How to get Interrupt on ADC change only? |
Posted: Sun Jul 11, 2010 6:03 pm |
|
|
I've been reading and trying code to get the ADC to interrupt only when it changes. But it seems to interrupt every time I prime it, and none if I don't prime it. I want an interrupt only when the ADC result changes.
Code: |
#include <16f877A.h>
#fuses HS, NOLVP, NOWDT, PUT, NODEBUG
#use delay (clock = 20000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#INT_AD //Analog to Digital Converter - Conversion Done ISR
void ADC_done()
{
printf("\n\r ADC>%d",read_adc(ADC_READ_ONLY));
}
void main(void)
{
setup_adc_ports ( RA0_ANALOG ); //Use the A0 analog bit
setup_adc ( ADC_CLOCK_INTERNAL ); //Set the ADC to use its internal clock
set_adc_channel (0); //Select channel 0 corresponding to A0
enable_interrupts(INT_AD); //enable AD conversion interrupts
enable_interrupts(GLOBAL);
while(1)
{
delay_ms(1000);
read_adc(ADC_START_ONLY); //Prime ADC_Done interrupt
};
}
|
The PIC is on a proto-board that has a multi-turn pot on it, connected to the ADC. Turning the pot changes the reading.
The printf outputs the reading about every second.
Moving the read_adc(ADC Start Only) above the while loop gets me only one reading. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 11, 2010 11:34 pm |
|
|
Quote: |
I want an interrupt only when the ADC result changes.
|
But that's not the way it works. The 16F877A data sheet says
it interrupts when the A/D conversion is done:
Quote: |
11.0 ANALOG-TO-DIGITAL CONVERTER (A/D) MODULE
When the A/D conversion is complete, the result is loaded into
this A/D result register pair, the GO/DONE bit (ADCON0<2>)
is cleared and the A/D interrupt flag bit ADIF is set.
|
Possible solutions:
You could create a periodic timer interrupt (using Timer0 for example)
and read the A/D in the isr. In effect you would be polling the A/D
voltage. Then set a flag or do something if the current value is
sufficiently different from the previous value.
If you were just looking for a interrupt if the input moved above or
below a fixed voltage, then you could use the comparator, and use
the INT_COMP interrupt. You could even change the reference voltage
inside the isr, to provide some hysteresis, and thereby reduce the
effects of signal noise (to prevent getting lots of spurious interrupts
if the input voltage is hanging right around the reference voltage). |
|
![](templates/subSilver/images/spacer.gif) |
louarnold
Joined: 13 May 2010 Posts: 42 Location: Ottawa, Canada
|
|
Posted: Mon Jul 12, 2010 8:56 am |
|
|
PCM programmer wrote: |
If you were just looking for a interrupt if the input moved above or
below a fixed voltage, then you could use the comparator, and use
the INT_COMP interrupt. You could even change the reference voltage
inside the isr, to provide some hysteresis, and thereby reduce the
effects of signal noise (to prevent getting lots of spurious interrupts
if the input voltage is hanging right around the reference voltage). | That's an interesting solution; I will try it. ADC readings are not a priority in my software, so running a slow polling loop is reasonable, but your suggestion will improve my knowledge of the chip - a major goal for me.
Many thanks,
Lou. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|