CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Having issues while trying to use ADC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
suspiciousdeveloper



Joined: 02 Mar 2025
Posts: 4

View user's profile Send private message

Having issues while trying to use ADC
PostPosted: Sun Mar 02, 2025 3:52 pm     Reply with quote

Compiler Version: V5.118
MCU: 33CH128MP202-I/SS

Hey there, while trying to use ADC the code seems to be getting stuck whenever the read_adc() function is called. Tried multiple methods but no luck, appreciate any help provided. Code is attached below:


Code:
#include <33CH128MP202.h>

#device adc=12  // Ensure 12-bit ADC resolution

#fuses NOWDT, HS  // Disable watchdog, high-speed oscillator
#use delay(crystal=10mhz, clock=180000000)

// UART1 Configuration
#pin_select U1TX = PIN_B6
#pin_select U1RX = PIN_B5
#use rs232(UART1, STREAM=UART1, baud=9600, xmit=PIN_B6, rcv=PIN_B5, ERRORS)

// ADC Configuration
#define ADC_CHANNEL 0  // **Try AN0 Instead of AN4**
#define VREF 3.3       // Reference Voltage
#define ADC_MAX 4095   // 12-bit ADC max value
#define PIN_LED PIN_B7  // **LED for debugging**

void blink_led() {
    int i;
    for (i = 0; i < 5; i++) {  // **Blink LED 5 times before ADC setup**
        output_toggle(PIN_LED);
        delay_ms(500);
    }
}

// **Initialize ADC (With Debugging and Reset)**
void init_adc() {
    fprintf(UART1, "Initializing ADC...\r\n");

    setup_adc_ports(sAN0);         // Ensure AN0 is analog

    delay_ms(5);
    setup_adc(ADC_CLOCK_DIV_64);   // **Try a more stable clock setting**
   
    set_adc_channel(ADC_CHANNEL);  // Select AN0
    delay_ms(10);  // Allow ADC to stabilize

    // **Check if ADC Module is Enabled**
    if (!adc_done()) {
        fprintf(UART1, "ERROR: ADC is NOT READY! ADC module may be OFF.\r\n");
    } else {
        fprintf(UART1, "ADC Initialized Successfully.\r\n");
    }
}

// **Read ADC Value with Debugging**
unsigned int16 read_adc_value() {
    unsigned int16 adc_result;
    int timeout = 5000;

    fprintf(UART1, "Starting ADC Conversion...\r\n");

    set_adc_channel(ADC_CHANNEL);  // Select correct channel
    delay_us(10);  // Small delay before conversion

    // **Use ADC_START_ONLY to Prevent Hanging**
    read_adc(ADC_START_ONLY);

    // **Timeout Protection**
    while (!adc_done() && timeout > 0) {
        delay_us(10);
        timeout--;
    }

    if (timeout == 0) {
        fprintf(UART1, "ERROR: ADC Conversion Timed Out!\r\n");
        return 0;
    }

    adc_result = read_adc(ADC_READ_ONLY);
    fprintf(UART1, "DEBUG: read_adc() returned: %u\r\n", adc_result);
    return adc_result;
}

// **Main Function**
void main() {
    unsigned int16 temp_adc;
    float voltage;

    delay_ms(100);  // Allow MCU to stabilize
    fprintf(UART1, "\r\nBOOTING SYSTEM...\r\n");

    blink_led();  // **Confirm MCU is running**
    init_adc();   // **Initialize ADC**

    while (TRUE) {
        fprintf(UART1, "Trying to read ADC...\r\n");

        temp_adc = read_adc_value();  // Get ADC reading
        voltage = (temp_adc / (float)ADC_MAX) * VREF;  // Convert ADC value to voltage

        fprintf(UART1, "ADC Read: %u | Voltage: %.2fV\r\n", temp_adc, voltage);

        delay_ms(1000);  // Read every second
    }
}
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 02, 2025 5:50 pm     Reply with quote

ok ,curious like my cat...FYI I've never used it but...

THAT PIC appears to be 'dual core' . If so I assume YOU have to configure what pins are ADC and where they go --> PIC #1, --> PIC #2

first though , I'd get the clock set to something reasonable, say 10MHz for test purposes AND run the '1Hz LED' program to confirm it runs....

when 'happy' have main()
do....
read ADC
send data to PC
delay 500ms
...forever

CONFIRM this works, put pot on input,vary, result should 'follow' wiper.

bottom line..go back to basics, build on code that works.

forget about 'floating point' too !!

query... is that PIC rated for 180 MHz operation at 3 volt VDD ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 6:13 am     Reply with quote

He is rather pushing the core. It is rated for 180MHz, but only over a limited
supply and temperature range.
There are lots of extra complexities with these chips:
First the ADC clock source is not being specified. By default will be 'SYSTEM'.
Then, he needs to specify which ADC channel to use. On this ADC, there
are multiple SAR's feeding the single dedicated core on the master chip.
By default it will read all enabled channels, but he has none enabled.
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 6:43 am     Reply with quote

yeesh.... sounds like a 'fun' PIC to deal with !

Kinda wondered why the 'warp speed' for the clock, especially for testing .

I KNOW board layout,wiring,etc. is critical to get more than 10 bits of good data from a 12 bit ADC.
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 7:49 am     Reply with quote

Yes, they are getting fun.
The design is very much optimised to using the ADC triggered from something
like the PWM. You specify the channels you want, and when it gets the
trigger it automatically samples the specified channels.
The results are stored in buffers for each channel number.
The ADC won't sample without a channel setup enabled. I think this
is what he is missing. These are the CNVCHSEL bits. He has to perform
a channel setup as well as the basic ADC setup.
suspiciousdeveloper



Joined: 02 Mar 2025
Posts: 4

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 11:33 am     Reply with quote

temtronic wrote:
ok ,curious like my cat...FYI I've never used it but...

THAT PIC appears to be 'dual core' . If so I assume YOU have to configure what pins are ADC and where they go --> PIC #1, --> PIC #2

first though , I'd get the clock set to something reasonable, say 10MHz for test purposes AND run the '1Hz LED' program to confirm it runs....

when 'happy' have main()
do....
read ADC
send data to PC
delay 500ms
...forever

CONFIRM this works, put pot on input,vary, result should 'follow' wiper.

bottom line..go back to basics, build on code that works.

forget about 'floating point' too !!

query... is that PIC rated for 180 MHz operation at 3 volt VDD ?



Hey, thanks for the response, yea the MCU works fine with 180MHz as well. I tried lowering it down to 10MHz as you said but there was no change. Crying or Very sad
suspiciousdeveloper



Joined: 02 Mar 2025
Posts: 4

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 11:37 am     Reply with quote

Ttelmah wrote:
Yes, they are getting fun.
The design is very much optimised to using the ADC triggered from something
like the PWM. You specify the channels you want, and when it gets the
trigger it automatically samples the specified channels.
The results are stored in buffers for each channel number.
The ADC won't sample without a channel setup enabled. I think this
is what he is missing. These are the CNVCHSEL bits. He has to perform
a channel setup as well as the basic ADC setup.


Hey I couldn't find any other functions than adc_set_channel() which I am already using, can you please help regarding else I need to do?
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Mon Mar 03, 2025 12:18 pm     Reply with quote

The ADC channel number there is not the channel number for the sampling.
If you look at the functions you are already using they offer channel
selections as an option. You need to setup a channel with these.
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Tue Mar 04, 2025 3:05 am     Reply with quote

Problem here is the use of the word 'channel'.

On traditional ADC's, the 'channel' had one meaning, the input number
to be read. On this chip it has two meanings.... Sad
There is the analog channel, and the ADC sample channel. The analog
channel is the historic meaning. The sample channel, it which of the five
internal input channels it is actually to read.
Now if you look at the data sheet, these are the CNVCHSEL bits. It tells
you that when doing a software triggered read, it'll read the sample channel
that has this bit set. If none of these bits are set, it won't actually perform
a read.
Now the .h file makes this more confusing, by calling both these numbers
'channel'. It is right I suppose, since this is what they are called in the
data sheet, but doesn't help you to understand that these are separate....
Personally I think they should have changed the names so the one
in set_adc_channel, was called perhaps an_channel, and the ones in
read_adc, and add_done, were called perhaps samp_chan.
The key point here is that a sample channel has to be set.

So if you change adc_done(), to adc_done(1), this then is using sample
channel 1, similarly if you change the read_adc commands, to:
read_adc(ADC_START_ONLY,1);
and
read_adc(ADC_READ_ONLY,1);

This then says to set the bottom CNVCHSEL bit to work with this channel.
Now the data sheet says:
Quote:

CNVCHSEL [5:0]: Channel Number Selection for Software Individual Channel Conversion Trigger bits
These bits define a channel to be converted when the CNVRTCH bit is set.


The point is it won't actually do a conversion, unless one of these bits is
set. If you look at the listing, if you use the '1' as shown, it sets the bottom
one of these bits, so the software trigger should then know what it has
to convert.

I've only use this ADC with triggered sampling, but noted when looking
at the setups, that this bit needed to be set and worked out that this was
what did it.

I must admit I was surprised that the default didn't set a bit without this....
suspiciousdeveloper



Joined: 02 Mar 2025
Posts: 4

View user's profile Send private message

PostPosted: Thu Mar 06, 2025 2:32 pm     Reply with quote

Ttelmah wrote:
Problem here is the use of the word 'channel'.

On traditional ADC's, the 'channel' had one meaning, the input number
to be read. On this chip it has two meanings.... Sad
There is the analog channel, and the ADC sample channel. The analog
channel is the historic meaning. The sample channel, it which of the five
internal input channels it is actually to read.
Now if you look at the data sheet, these are the CNVCHSEL bits. It tells
you that when doing a software triggered read, it'll read the sample channel
that has this bit set. If none of these bits are set, it won't actually perform
a read.
Now the .h file makes this more confusing, by calling both these numbers
'channel'. It is right I suppose, since this is what they are called in the
data sheet, but doesn't help you to understand that these are separate....
Personally I think they should have changed the names so the one
in set_adc_channel, was called perhaps an_channel, and the ones in
read_adc, and add_done, were called perhaps samp_chan.
The key point here is that a sample channel has to be set.

So if you change adc_done(), to adc_done(1), this then is using sample
channel 1, similarly if you change the read_adc commands, to:
read_adc(ADC_START_ONLY,1);
and
read_adc(ADC_READ_ONLY,1);

This then says to set the bottom CNVCHSEL bit to work with this channel.
Now the data sheet says:
Quote:

CNVCHSEL [5:0]: Channel Number Selection for Software Individual Channel Conversion Trigger bits
These bits define a channel to be converted when the CNVRTCH bit is set.


The point is it won't actually do a conversion, unless one of these bits is
set. If you look at the listing, if you use the '1' as shown, it sets the bottom
one of these bits, so the software trigger should then know what it has
to convert.

I've only use this ADC with triggered sampling, but noted when looking
at the setups, that this bit needed to be set and worked out that this was
what did it.

I must admit I was surprised that the default didn't set a bit without this....



Thanks for the help, I got it working. Can you guide me on how to use ADC with Interrupts on this specific model? I already tried the basic ADC_START_ONLY in main code and calling ADC_READ_ONLY in isr but it doesnt seem to work Rolling Eyes
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Fri Mar 07, 2025 12:28 am     Reply with quote

Using interrupts with manual triggering would just waste time. Where
interrupts are useful, is when the ADC is started by an external event.
So (for example) the PWM, or a timer.
I would suggest you setup a Tacq in the ADC setup. This way the ADC
will automatically wait to acquire when sampling, so you can just read
without having to wait after selecting a channel.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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