View previous topic :: View next topic |
Author |
Message |
esbelektronik
Joined: 13 Dec 2018 Posts: 23
|
16F19197 ADC problem |
Posted: Tue Jan 15, 2019 3:42 pm |
|
|
Hi,
I use PIC16F19197 AN0, AN1 and AN2 analog input basic mode. But all input read 2048 decimal while 0V. And read 4095 decimal while 5V.
You can see a piece of code and configration is below.
Code: | #include <16F19197.h>
#device ADC=12
#device CCS4
#FUSES WDT //Watch Dog Timer
#FUSES RSTOSC_HFINTRC_PLL //On Power-up clock running from HFINTRC with 4x PLL
#FUSES VBATEN //VBAT functionality is enabled
#FUSES NOLCDPEN //LCD Charge Pump forced off
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES NOZCDDIS //Zero-cross detect circuit is enabled at POR
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES PROTECT //Code protected from reads
#use delay(internal=32000000,restart_wdt)
#use STANDARD_IO( a )
#use STANDARD_IO( D )
#use fixed_io(f_outputs=PIN_F5, PIN_F6,PIN_F7)
#use FIXED_IO( B_outputs=PIN_B6,PIN_B5,PIN_B4,PIN_B3,PIN_B2,PIN_B1 )
#use FIXED_IO( C_outputs=PIN_C5,PIN_C4,PIN_C3,PIN_C2 )
#use FIXED_IO( E_outputs=PIN_E7,PIN_E6,PIN_E5,PIN_E4,PIN_E3,PIN_E1,PIN_E0 )
#use STANDARD_IO(g)
#use STANDARD_IO(h)
void main()
{ int16 adcvalue;
setup_oscillator(OSC_HFINTRC_32MHZ );
setup_dac(DAC_OFF);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_lcd(LCD_DISABLED);
setup_adc(ADC_CLOCK_INTERNAL | ADC_CLOCK_DIV_2 );
setup_adc_reference(VSS_VDD);
setup_adc_ports(sAN0|sAN1|sAN2,VSS_VDD);
//set_analog_pins(PIN_A0,PIN_A1,PIN_A2); // i try this but not change result.
setup_zcd(ZCD_ENABLE|ZCD_INT_L_TO_H);
set_tris_f(0b00011111);
set_tris_a(0b11111111);
set_tris_h(0b00000000);
set_input_level_f(0xFF);
set_slow_slew_f(0b00000000);
set_open_drain_f(0b00000000);
setup_rtc(RTC_ENABLE | RTC_CLOCK_SOSC );
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(T0_INTERNAL|T0_DIV_4);
setup_timer_1(T1_INTERNAL |T1_DIV_BY_2);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
disable_interrupts(INT_TIMER2);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER0);
disable_interrupts(INT_EXT);
enable_interrupts(INT_ZCD);
while(1)
{
set_adc_channel(0);
adcvalue=read_adc(); //i send to LCD after this colums.
}
} |
_________________ ^ ^
(q p) ESB
( V )
L L |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Jan 15, 2019 4:13 pm |
|
|
you've got 3 interrupts enabled yet not corresponding ISRs for them. While 'global' is not enabled, there might be a rndom problem
usully adc_clock_internl is for PICs in Sleep mode, though I've never used this PIC(too many pins..) maybe it's valid ?
2048 is a 'magic' number... is VSS really ground?
It's almost that Vref is NOT VSS(ground). A check of the listing should confirm the proper bits are set for the ADC code. If wrong, possible complier 'bug'.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: 16F19197 ADC problem |
Posted: Tue Jan 15, 2019 7:44 pm |
|
|
esbelektronik wrote: |
setup_adc(ADC_CLOCK_INTERNAL | ADC_CLOCK_DIV_2 );
|
You are using the internal adc clock. The errata sheet for the 16F16197
says this will not work properly:
Quote: |
PIC16(L)F19195/6/7 Family Silicon Errata and Data Sheet Clarification
1.1 ADC2 Clock Selection
The ADC does not function properly if FRC is
selected as its clock source resulting in the MSB
being stuck as a ‘0’ or a ‘1’. This also prohibits
using the ADC module in Sleep mode. |
Link to errata document:
http://ww1.microchip.com/downloads/en/DeviceDoc/PIC16F19195_errata_80000727E.pdf
Microchip web page for this PIC:
https://www.microchip.com/wwwproducts/en/PIC16F19197
Look at this table on page 284 of the 16F19197 data sheet:
Quote: | TABLE 19-1: ADC CLOCK PERIOD (TAD) VS. DEVICE OPERATING FREQUENCIES |
Choose a divisor that will work with your 32 MHz oscillator frequency.
I would say Fosc/16. Look in the 16F19197.h to see the constant to use
in your program for that divisor.
Link to PIC datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/40001873C.pdf |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Jan 16, 2019 4:21 am |
|
|
There are other issues. Surprised it works at all:
WDT is enabled in the fuses. This gives '11' to the watchdog enable bits
which means SWDTEN is ignored. Result watchdog will be running and
will be resetting the chip. It'll only be working if he is running in debug
mode which overrides the watchdog setting.
The fuse needs to be WDT_SW which then means it can be controlled
in software....
Then he has:
setup_spi(SPI_SS_DISABLED);
Which is a common error. Means the SPI is enabled, and slave select turned
off. The correct syntax to disable the SPI, is
setup_spi(FALSE);
Then he is reading the ADC, without allowing any Tacq, and doing it
repeatedly without pause. Both wrong. There must be time for acquisition
between selection and reading, and precharge between readings..
This ADC can be set to generate both the precharge, and acquisition times
for you. If this is not done, then there needs to be a delay.
Then the comment already made about the interrupts.
|
|
|
esbelektronik
Joined: 13 Dec 2018 Posts: 23
|
Re: 16F19197 ADC problem |
Posted: Wed Jan 16, 2019 7:19 am |
|
|
Yesss,
setup_adc(ADC_CLOCK_INTERNAL | ADC_CLOCK_DIV_2 );
change to,
setup_adc(ADC_TAD_MUL_16);
now right working.
Thanks for help. _________________ ^ ^
(q p) ESB
( V )
L L |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Jan 16, 2019 7:37 am |
|
|
It still won't give proper values unless you add some acquisition/precharge time.
Also not the other errors pointed out. |
|
|
esbelektronik
Joined: 13 Dec 2018 Posts: 23
|
|
Posted: Wed Jan 16, 2019 12:27 pm |
|
|
Ttelmah wrote: | It still won't give proper values unless you add some acquisition/precharge time.
Also not the other errors pointed out. |
yes you are right. i connect 5V to an0 input, but never see 4094 decimal. i saw max 4000 decimal. if connect gnd see 0. _________________ ^ ^
(q p) ESB
( V )
L L |
|
|
esbelektronik
Joined: 13 Dec 2018 Posts: 23
|
|
Posted: Wed Jan 16, 2019 12:46 pm |
|
|
Hi
CCS support response,
"There is an errata for this family with the ADC when using the internal ADC clock as the clock source that says the MSB of the result is stuck at either 0 or 1. In your case it appears to be stuck at 1, this is why you're getting a reading of 2048 when then input is 0V. The only way to work around this issue is to use a clock other then the internal ADC clock as the clock source for the ADC. Changing your ADC setup to the following will set the system clock as the ADC clock source with the same period as the internal ADC clock when using a 32 MHz system clock:
setup_adc(ADC_CLOCK_DIV_64);"
i try setup_adc(ADC_CLOCK_DIV_64); now read 4095 decimal. _________________ ^ ^
(q p) ESB
( V )
L L |
|
|
|