View previous topic :: View next topic |
Author |
Message |
bells_electronics
Joined: 05 Dec 2009 Posts: 40
|
2 ADCs in 16F876A Problem |
Posted: Sun Jan 24, 2010 8:00 am |
|
|
Code: |
#include <16F876A.h>
#device adc=8
#FUSES NOWDT //Watch Dog Timer
#FUSES HS //High speed Osc (>4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming,
#FUSES NOCPD //No EE protection
#use delay(clock=4MHz , crystal)
unsigned char adc(void);
unsigned char adc_1;
unsigned char adc_2;
void main()
{
delay_ms(50); //stabilization time for PIC
set_tris_a (0b00000111);
set_tris_b (0x00);
set_tris_C (0b00000000);
delay_ms(100);
adc_1 = 0;
adc_2 = 0;
setup_comparator(NC_NC_NC_NC); // not use comparator module
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0_AN1_AN3);
while(TRUE)
{
set_adc_channel(0);
adc_1 = adc();
set_adc_channel(1);
adc_2 = adc();
}
}
unsigned char adc()
{
read_adc(ADC_START_ONLY);
while(!adc_done());
return read_adc(ADC_READ_ONLY);
}
|
the problem is that ADC1 value is dependent on ADC2 value,
ADC2 working fine independent of ADC1
whatz the heck with ADC1
1)
PIN_A0 = 5v
PIN_A1 = 0v
then i get
adc_1 = 180
adc_2 = 000
2)
PIN_A0 = 5v
PIN_A1 = 2.723v
then i get
adc_1 = 255
adc_2 = 138
3)
PIN_A0 = 1.187v
PIN_A1 = 0v
then i get
adc_1 = 060
adc_2 = 000
4)
PIN_A0 = 5v
PIN_A1 = 5v
then i get
adc_1 = 255
adc_2 = 255 |
|
![](templates/subSilver/images/spacer.gif) |
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Sun Jan 24, 2010 9:34 am |
|
|
The A/D multiplexer needs some time to settle after switching channels. I don't have time this morning to figure out how much, but if you wait 100us after switching channels before you start conversion your problem should go away. Study the PIC datasheet or search posts here to find out just how long you must wait.
I usually take a reading, switch channels, do math on the old reading, take the next reading, switch channels, do math, etc.. Doing the math takes longer than the mux settling time. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
![](templates/subSilver/images/spacer.gif) |
bells_electronics
Joined: 05 Dec 2009 Posts: 40
|
|
Posted: Sun Jan 24, 2010 11:23 am |
|
|
i put the delay still not working, but it works fine on ISIS
Code: |
#include <16F876A.h>
#device adc=8
#FUSES NOWDT //Watch Dog Timer
#FUSES HS //High speed Osc (>4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming,
#FUSES NOCPD //No EE protection
#use delay(clock=4MHz , crystal)
unsigned char adc(void);
unsigned char adc_1;
unsigned char adc_2;
void main()
{
delay_ms(50); //stabilization time for PIC
set_tris_a (0b00000111);
set_tris_b (0x00);
set_tris_C (0b00000000);
delay_ms(100);
adc_1 = 0;
adc_2 = 0;
setup_comparator(NC_NC_NC_NC); // not use comparator module
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0_AN1_AN3);
while(TRUE)
{
delay_ms(500);
set_adc_channel(0);
adc_1 = adc();
delay_ms(500);
set_adc_channel(1);
adc_2 = adc();
}
}
unsigned char adc()
{
read_adc(ADC_START_ONLY);
while(!adc_done());
return read_adc(ADC_READ_ONLY);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 24, 2010 11:47 am |
|
|
You don't need to set the TRIS. The compiler does it automatically.
You don't need to do the A/D in steps. Just use read_adc() to do it.
See the example in this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=32168&start=1
Quote: | but it works fine on ISIS |
The simulator doesn't model all aspects of hardware A/D operation. |
|
![](templates/subSilver/images/spacer.gif) |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
|
Posted: Sun Jan 24, 2010 12:04 pm |
|
|
As Sherpa Doug says you must have a delay between the channel set and
the read. It would help a lot if you would read the manual.
The following from page 48 of the current manual:
Code: |
set_adc_channel(0); //the next read_adc call will read channel 0
delay_us(10); //a small delay is required after setting the channel and before read
value=read_adc(); //starts the conversion, reads the result and stores it in value
|
_________________ Google and Forum Search are some of your best tools!!!! |
|
![](templates/subSilver/images/spacer.gif) |
|