read datasheet, specially page 61 (9.1 ADC Configuration) and page 31(GPIO Configuration):
http://www.electro-tech-online.com/c...04/41211d_.pdf
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!
read datasheet, specially page 61 (9.1 ADC Configuration) and page 31(GPIO Configuration):
http://www.electro-tech-online.com/c...04/41211d_.pdf
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.
Last edited by MikahB; 21st April 2012 at 10:45 PM.
Where did you set ANSEL bit high for this analog input?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.
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.
Last edited by panic mode; 21st April 2012 at 10:51 PM.
Look at page 35 you don't set this to 0 ANSEL = 0;
You want ANSEL =0x74;
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.
Last edited by MikahB; 21st April 2012 at 10:51 PM.
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; }
Last edited by MikahB; 21st April 2012 at 11:09 PM.
fair enough, how about ADCON0? is this used only for AN0? Is there ADCON2?
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.
| 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 |