View previous topic :: View next topic |
Author |
Message |
ag6ju
Joined: 22 Jun 2021 Posts: 7 Location: Orange County Calif. USA
|
ADC error PIC18F25Q10T // CCS C ver 5.104 |
Posted: Tue Jun 22, 2021 4:57 pm |
|
|
CCS C ver 5.104 PIC18F25Q10T ADC error -
ADC function of PIC18F25Q10T always return 0x223 to 0x3FF.
As following code. However when I write into directly to SFR register it works fine.
Code of writing SFR register direct is below on bottom.
Code: |
// Read voltage from AD converter, return 10 bit value 0 to 1023
UI16 ui16_read_ADC_voltage ( UI8 ui8_ADC_select )
{
// 1MHz or 4MHz
UI16 ui16_ADC_read;
setup_adc_ports( sAN5, VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_16 | ADC_LEGACY_MODE | ADC_THRESHOLD_INT_DISABLED );
//setup_adc( ADC_CLOCK_INTERNAL | ADC_AVERAGE_MODE | ADC_CONTINUOUS_OPERATION_ENABLED);
//setup_adc_ports( ADC_9V_AN0 | ADC_EXT_POT_AN1 | ADC_VR012_AN5 ); // use Vdd input to CPU
//setup_adc_reference ( VSS_VDD );
//setup_adc_ports( sAN0 | sAN1, VSS_FVR ); // user Internal Voltage reference
//setup_vref ( VREF_ON | VREF_ADC_2v048 );
//setup_vref ( VREF_ADC_4v096 | VREF_ON );
//setup_vref( VREF_ON | VREF_ADC_1v024 );
delay_ms ( 10 ); // 2mS at 4MHz, 8mS at 1MHz
set_adc_channel ( 5 ); // select ADC channel
//set_adc_channel ( ui8_ADC_select ); // select ADC channel
delay_ms ( 2 ); // 2mS at 4MHz, 8mS at 1MHz
// ui16_battery_vol_01 = ( UI16 ) ( ( ( UI32 ) read_adc( ADC_START_AND_READ ) * ( UI32 ) 1000 ) / ( UI32 ) 736 ); // in 0.01 V step , range of ADC output for MSB 10 bits output / 0x40 = 0 -- 1023 ( 0x000 - 0x3FF ) 2.2k / ( 2.2k + 10k )
ui16_ADC_read = read_adc ( ADC_START_AND_READ );
//ui16_ADC_read = adc_read ( ADC_RESULT );
// 0.08 V 0x022 34 // 1.94V 0x3C3 963 // ( 963 - 34 ) / 100 = 9.29 for each 100 hz ( 100 step )
setup_adc( ADC_OFF );
//setup_vref( VREF_OFF );
return ( ui16_ADC_read );
} // UI16 ui16_read_ADC_voltage ( UI8 ui8_ADC_select )
|
Write directly to SFR register to control ADC:
Code: |
#pragma byte ADCON0 = getenv( "SFR:ADCON0" )
#bit bit_ADFM = ADCON0.2
#bit bit_ADON = ADCON0.7
#bit bit_ADCS = ADCON0.4
#bit bit_ADGO = ADCON0.0
#pragma byte byte_ADPCH = getenv( "SFR:ADPCH" )
#pragma byte byte_TRISA = getenv ( "SFR:TRISA" )
#bit bit_TRISA5 = byte_TRISA.5
#pragma byte byte_ANSELA = getenv ( "SFR:ANSELA" )
#bit bit_ANSELA5 = byte_ANSELA.5
#pragma byte byte_ADRESH = getenv("SFR:ADRESH")
#pragma byte byte_ADRESL = getenv("SFR:ADRESL")
/***
bit_ADFM = 1; // right justify
bit_ADCS = 1; // FRC clk
byte_ADPCH = 0b0000101; // ANA5
bit_TRISA5 = 1; // 1 == make input
bit_ANSELA5 = 1; // make it analog inp
bit_ADGO = 1; // start ADC conv
while ( bit_ADGO );
ui16_temp_01 = byte_ADRESH * 0x100 + byte_ADRESL;
***/ |
|
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Tue Jun 22, 2021 7:01 pm |
|
|
It's possible that the header file or the setup function has some mistakes.
I had an issue in 5.103 with my MCU (PIC24FJ256GL408) and it's ADC too.
Since you were able to make it work by setting the SFR directly, if you email ccs support explaining what you did, they can probably find the problem quickly and patch it in an upcoming release. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19503
|
|
Posted: Wed Jun 23, 2021 7:17 am |
|
|
OK.
On chips with the ANSEL registers, you have to use
set_analog_pins(PIN_B5); //etc
As well as the standard ADC setups.
This is what controls the ANSEL on these.
Now the setup_adc function is correctly setting all the bits in ANCON etc..
Looks right.
To me, the high value suggests the pin is being set as a digital output
and outputting a '1'. With ANSEL not set this could happen. |
|
|
ag6ju
Joined: 22 Jun 2021 Posts: 7 Location: Orange County Calif. USA
|
|
Posted: Wed Jun 23, 2021 12:46 pm |
|
|
I am find out, error only happen on seconds read and thereafter (after power on reset), first read are good.
If I leave ADC power on all the time, it works fine.
But, if I shut down ADC power at end of function using
Code: | bit_ADON = 0; // ADC OFF |
then second read after ADC re-power up read 0x0233 regardless of voltage to ADC input. Code: |
UI16 ui16_read_ADC_voltage2 ( UI8 ui8_ADPCH_sel )
{
UI16 ui16_return;
bit_ANSELA0 = 1; // make it analog inp ADC_9V
bit_ANSELA1 = 1; // make it analog inp EXT_POT
bit_ANSELA5 = 1; // make it analog inp VR-012
bit_TRISA0 = 1; // 1 == make input A0
bit_TRISA1 = 1; // 1 == make input A1
bit_TRISA5 = 1; // 1 == make input A5
//bit_ADON = 1; // ADC ON
bit_ADFM = 1; // right justify
bit_ADCS = 1; // FRC clk
byte_ADPCH = ADPCH_ANA5; // ui8_ADPCH_sel; // ADPCH_ANA5; // select ANA5
bit_ADON = 1; // ADC ON
delay_cycles ( 1 );
bit_ADGO = 1; // start ADC conv
while ( bit_ADGO );
ui16_return = byte_ADRESH * 0x100 + byte_ADRESL;
bit_ADON = 0; // ADC OFF
return ( ui16_return );
} // UI16 ui16_read_ADC_voltage2 ( UI8 ui8_ADC_select ) |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19503
|
|
Posted: Thu Jun 24, 2021 12:10 am |
|
|
You need to wait Tacq after the ADC is turned on, before you can start
a conversion. Just under 5uSeconds.
So instead of delay_cycles(1), you need delay_us(5); |
|
|
|