Electronic Circuits and Projects Forum



12F683 in MPLAB X - Cannot Get ADC Working

12 Last »
  1. #1
    MikahB MikahB is offline

    12F683 in MPLAB X - Cannot Get ADC Working

    I've been struggling with this for hours now and am officially chasing my tail.

    Not seeing the expected behavior on my physical circuit, I started playing with the simulator. Every time I set the GO_DONE bit in ADCON0, I get a warning from the simulator that says "ADC-W101: Selected channel is configured as digital IO. The channel selected:X." Where X is whichever channel I've selected (I've tried AN0 and AN2 so far with identical results).

    The first goal of this program is just to blink the LED on GPIO4 at a speed that is proportional to the input voltage to the ADC (0-5V).

    I'm confident I must be missiong something on my setup, but I've been through the datasheets and countless examples online and have been unable to spot the problem.

    Here is the code:
    Code :
    #include <htc.h>
    #include <stdio.h>
     
    #define _XTAL_FREQ 4000000
    #define _ADCBITS 10;
    #define _ADC_CLOCK3;
    #define _ADC_SAMPLEUS 50;
     
    __CONFIG(FCMEN_OFF & WDTE_ON & PWRTE_ON & MCLRE_OFF & IESO_OFF & CP_OFF & BOREN_OFF & FOSC_INTOSCIO);
     
    void config_ADC(void);
    int read_ADC(void);
     
    bit on_state;
    unsigned char delay;
    volatile unsigned int count;
     
    void main()
    {
        config_ADC();
     
        while(1)
        {
            on_state = ~on_state;
            GPIObits.GP4 = on_state;
     
            count = 1000 * read_ADC();
     
            while(count>0)
            {
            count--;
            }
     
        }
    }
     
    void config_ADC(void) {
        /* Turn off all comparators */
        CMCON0 = 7;
     
        /* Set the ADC Control register per Data sheet */
        ADCON0 = 0;             //initialize to zero
        ADCON0bits.VCFG = 0;     // reference Vdd
        ADCON0bits.CHS = 0b010;  // read AN2
        ADCON0bits.ADON = 1;    // turn ADC on
        ADCON0bits.ADFM = 1;    // right-justify for 10-bit ADC
     
        /* Set all ports except GP0 to digital (0) */
        ANSEL = 0;
        ANSELbits.ANS = 0b0100;     // set AN2 to analog
        ANSELbits.ADCS = 0b001;     // set freq to fosc/8
     
        /* Set all pins to output except GP0 (to be used as ADC input)*/
        TRISIO = 0;
        TRISIObits.TRISIO2 = 1;     // set AN2/GPIO2 to input
        TRISIObits.TRISIO3 = 1;     // set MCLR/GPIO3 to input
     
    }
     
    int read_ADC(void)
    { // start an ADC conversion and return the result
    	int ret = 0;
    	//__delay_ms(5);
    	ADCON0bits.GO_DONE = 1;		//start conversion
       	while(ADCON0bits.GO_DONE);		// wait for conversion
       	ret =  (ADRESH & 0x3) << 8;		// get
       	ret += ADRESL;				// result
    	return ret;
    }

    I appreciate any help or guidance!

  2. #2
    panic mode panic mode is offline
    read datasheet, specially page 61 (9.1 ADC Configuration) and page 31(GPIO Configuration):
    http://www.electro-tech-online.com/c...04/41211d_.pdf
    0

  3. Thread Starter #3
    MikahB MikahB is offline
    Been reading it - both of those sections and more for a long time. I'm missing or misunderstanding something I'm reading. Can you be any more specific to point me in a direction?

    I've disabled the comparators...
    I've set my tristates on TRSIO2 and TRISIO3 high...
    I've set ANSEL for the clock cycle, justification, and set AN2 as analog...
    I've sed ADCON0 with what I believe are the proper settings (error seems to indicate I'm asking for the correct channel)...

    When I stop the code right before I try to set ADCON0.GO_DONE high, here are the binary values in key registers:

    Code :
    TRISIO: 00001100
    ANSEL: 00010100
    ADCON0: 10001001
    CMCON0: 00000111

    Those are the values I expect to see based on what I'm reading in the datasheet. Just missing something.
    0
    Last edited by MikahB; 21st April 2012 at 10:45 PM.

  4. #4
    panic mode panic mode is offline
    4.2.1 ANSEL REGISTER
    The ANSEL register is used to configure the Input
    mode of an I/O pin to analog. Setting the appropriate
    ANSEL bit high will cause all digital reads on the pin to
    be read as ‘0’ and allow analog functions on the pin to
    operate correctly.
    Where did you set ANSEL bit high for this analog input?
    What I see is that you keep mentioning two analog ports AN0 and AN2.
    Are you using one or two analog ports?

    If you are using AN0, as your post suggests, then fix the code so that you are enabling AN0 and not AN2 (and fix the code comments).
    If you are using AN2... same story, stick with AN2 - don't mix and match.
    0
    Last edited by panic mode; 21st April 2012 at 10:51 PM.

  5. #5
    be80be be80be is offline
    Look at page 35 you don't set this to 0 ANSEL = 0;

    You want ANSEL =0x74;
    0
    Burt
    be80be
    “No beard, no belly, no guru…”

  6. Thread Starter #6
    MikahB MikahB is offline
    I set the ANSEL bits high in config_ADC():

    Code :
        /* Set all ports except GP0 to digital (0) */
        ANSEL = 0;
        ANSELbits.ANS = 0b0100;     // set AN2 to analog
        ANSELbits.ADCS = 0b001;     // set freq to fosc/8

    I did it this way because I read somewhere that it's good to explicitly clear the register before I start plugging stuff into it. Plus, being new to this and in a constant troubleshooting mode, it's easier for me to look at it long-hand for now so I know what I'm doing - right or wrong.

    @Burt - Tried setting to 0x74 per your suggestion (only clock selection was different from what I had) and identical result.
    0
    Last edited by MikahB; 21st April 2012 at 10:51 PM.

  7. #7
    panic mode panic mode is offline
    Quote Originally Posted by MikahB View Post
    I set the ANSEL bits high in config_ADC():

    Code :
        /* Set all ports except GP0 to digital (0) */
        ANSEL = 0;
        ANSELbits.ANS = 0b0100;     // set AN2 to analog <<<<NOTE What is THIS?  Why AN2 when you want to use AN0?
        ANSELbits.ADCS = 0b001;     // set freq to fosc/8
    .
    NOTE: What is THIS? Why AN2 when you want to use AN0?

    for AN0 you should set

    Code :
        ...
         ANSELbits.ANS = 0b0001;     // set AN0 to analog
        ...

    or configuration byte should be 0x11 (or 0xX1)
    0
    Last edited by panic mode; 21st April 2012 at 11:02 PM.

  8. Thread Starter #8
    MikahB MikahB is offline
    Switched from AN0 to AN2 during troubleshooting - forgot to change the comment but I"ve changed everything else (and now fixed the comment as well). I made a couple other minor changes to the code while troubleshooting also, here is a "fresh" new version that works equally poorly:

    Code :
    #include <htc.h>
    #include <stdio.h>
     
    #define _XTAL_FREQ 4000000
    #define _ADCBITS 10;
    #define _ADC_CLOCK3;
    #define _ADC_SAMPLEUS 50;
     
    __CONFIG(FCMEN_OFF & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & IESO_OFF & CP_OFF & BOREN_OFF & FOSC_INTOSCIO);
     
    void config_ADC(void);
    int read_ADC(void);
     
    bit on_state = 0;
    unsigned char delay;
    volatile unsigned int count = 0;
     
    void main()
    {
        config_ADC();
     
        while(1)
        {
            on_state = ~on_state;
            GPIObits.GP4 = on_state;
     
            count = read_ADC();
     
            while(count>0)
            {
            __delay_ms(10);
            count--;
            }
        }
    }
     
    void config_ADC(void) {
        /* Turn off all comparators */
        CMCON0 = 7;
     
        /* Set all ports to digital then un-set the ones we need */
        ANSEL = 0;
        ANSELbits.ANS = 0b0100;     // set AN2 to analog
        ANSELbits.ADCS = 0b001;     // set freq to fosc/8
     
        /* Set the ADC Control register per Data sheet */
        ADCON0 = 0;             //initialize to zero
        ADCON0bits.ADFM = 1;    // right-justify for 10-bit ADC
        ADCON0bits.VCFG = 0;    // reference Vdd
        ADCON0bits.CHS = 0b010; // read AN2
        ADCON0bits.ADON = 1;    // turn ADC on
     
        /* Set all pins to output except GP0 (to be used as ADC input)*/
        TRISIO = 0;
        TRISIObits.TRISIO2 = 1;     // set AN2/GPIO2 to input
        TRISIObits.TRISIO3 = 1;     // set MCLR/GPIO3 to input
     
    //    __delay_ms(10);
     
    }
     
    int read_ADC(void)
    { // start an ADC conversion and return the 8 most-significant bits of the result
    	int ret = 0;
    	ADCON0bits.GO_DONE = 1;	//start conversion <<<NOTE: This is the line that produces the error I mentioned in the 1st post
    	__delay_ms(5);
            while(ADCON0bits.GO_DONE);		// wait for conversion
       	ret = ADRESL + (ADRESH & 0x3) << 8;		// get result
    	return ret;
    }
    0
    Last edited by MikahB; 21st April 2012 at 11:09 PM.

  9. #9
    panic mode panic mode is offline
    fair enough, how about ADCON0? is this used only for AN0? Is there ADCON2?
    0

  10. Thread Starter #10
    MikahB MikahB is offline
    This PIC only has one ADCON register - ADCON0 - that controls all 4 channels (AN0-AN3) so it's common between the two channels I've tried.
    0

12 Last »
Tags
Similar Threads
Thread Starter Forum Replies Last Post
555 servo controller? can get them working lompa General Electronics Chat 19 6th November 2009, 12:59 AM
Cannot get Interrupt on TIMER0 to work on 16F628 johankj Microcontrollers 8 6th October 2008, 02:11 PM
Cant get LM2917 working vuchris Electronic Projects Design/Ideas/Reviews 1 27th August 2007, 08:58 PM
Cannot get 57600 b/s on 18f452 BOBKA Microcontrollers 12 26th February 2007, 08:36 AM
cannot get 4Mhz frequency for PIC16F84A pulpak Microcontrollers 2 12th July 2003, 09:36 AM
Electronic Circuits  |  Learning Electronics

Join our community with over 100,000 Members! It's free, easy and when you're logged in you have many more features! Click to register.
Page Time: 0.08361 seconds      Memory: 7,700 KB      Queries: 16      Templates: 0