| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				| 18F26K22 A/D example Please |  
				|  Posted: Sat Feb 12, 2011 10:44 am |   |  
				| 
 |  
				| I am having trouble setting up the a/d on a 18f26k22.  I need to read a 10bit value from an0 only using vss/vdd as references.  I have successfully configured other pics for a/d.  The application is not critical.  I am only wanting to use a pot to select options of a menu based on the a/d range input. 
 Would some one Please show me an example?
 
 Thanks Much
 Brian
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 12:55 pm |   |  
				| 
 |  
				| The header file for the device would be where I'd start to see what valid combinations are allowed. Then see what peripherals need to be disabled, if required.
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 2:33 pm |   |  
				| 
 |  
				| Thanks  for the reply.  I tried looking at the header file and I'm able to get the program to compile.  The trouble is I'm not getting the results I would expect.  I select the an0 port only as follows:  setup_adc_ports(sAN0|VSS_VDD); But when I view the ANSELA register I find it is set to 0010111b
 Should it not be 00000001b?  And the value = Read_ADC(); is always 00h
 
 Thanks
 Brian
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 2:39 pm |   |  
				| 
 |  
				| Sorry but I don't have that chip or the compiler for it. Perhaps there is an example in the examples folder that will help. Several of them have ifdef.... for various PIC series. |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 4:03 pm |   |  
				| 
 |  
				| Post your compiler version.  If it's a compiler bug, maybe I can look at the problem later today or tomorrow.
 
 (Always post your version. We don't remember it from your previous threads).
 |  | 
	
		|  | 
	
		| gpsmikey 
 
 
 Joined: 16 Nov 2010
 Posts: 588
 Location: Kirkland, WA
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 7:43 pm |   |  
				| 
 |  
				| It looks like the 18F26k22 is very similar to the one I'm using, the 18F14K22.  In that case, I wanted to use the internal reference (at 1.024 volts since the 2**10 = 1024 and the temp sensor gives 10mv/deg C it worked out very nice).  I'm using the internal precision oscillator at 8mhz using the compiler directive: #use delay(clock=8000000) // configure for 8mhz clock
 With compiler version 4.114, the header did not have the correct (or any actually) info configured for the internal reference - here is the code segment I used to set it up to use the internal reference:
 
 
  	  | Code: |  	  | // setup AD converter // AN2 (RA2) = ambient temp, AN10 (RA10)=htr temp
 // NOTE: the setup_adc_ports clears my selection of the Vref source
 //       so it needs to be done before I write to ADCON1.
 // => If we define VSS_VFVR using the same format as the rest of the ref
 //    config info in the .h file (0x800) then setup_adc_ports() does select
 //    the internal reference correctly and we only have to write to the
 //    VREFCON0 register to enable the FVR and select the 1x multiplier.
 setup_adc_ports(AIR_PORT | HTR_PORT,VSS_VFVR);
 setup_adc(ADC_CLOCK_DIV_16);
 
 // Have to enable the internal FVR and set to 1x
 VREFCON0 = 0x90; // FVR enabled, 1x (1.024v)  (pg 245)
 
 //  VREFCON1 = 0x00; // DAC is disabled  (pg 246)
 //  VREFCON2 = 0x00; // DAC output disabled (pg 246)
 //  ADCON1   = 0x08; // pos vref from FVR, neg vref from Vss (pg 214,207)
 //  ADCON2   = 0x95; // Rt. justify, TAD4,Fosc/16   (pg 215)
 
 // setup_adc_ports(AIR_PORT | HTR_PORT);
 // AN2 (RA2) = ambient temp, AN10 (RA10)=htr temp
 
 // check for current settings in eeprom - if first byte of eeprom is not
 // CHK_BYTE then copy defaults to eeprom else read settings from eeprom
 // into the settings structure (over write defaults).
 
 | 
 
 To read the ADC, I use the following code:
 
 
  	  | Code: |  	  | // read the heater ADC channel - return raw value + cal factor for sensor // also saves corrected reading in HTR_raw (mv)
 signed int16 rd_HTR_raw()
 {
 set_adc_channel(HTR_CHAN); // select the HTR temp channel
 delay_us(20);              // let stabilize
 HTR_raw = read_adc(ADC_START_AND_READ)+ settings.sens_cal_htr ;
 return(HTR_raw);          // return corrected raw value (mv)
 }
 
 | 
 
 Don't forget to specify the 10 bit mode with a device line near the top of your code:
 
 
  	  | Code: |  	  | #device adc=10         // 10 bit AD mode 
 
 | 
 
 Hope this helps - this code runs fine in my little application (2 sensors).
 Note that the page number references are for the 18F14K22 chip.
 
 mikey
 _________________
 mikey
 -- you can't have too many gadgets or too much disk space !
 old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 12, 2011 9:09 pm |   |  
				| 
 |  
				| Thanks Guys for the replies! I'll check out the code early tomorrow.
 
 P.S.
 My version is 4.110
 
 Thanks again
 Brian
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 9:47 am |   |  
				| 
 |  
				| Still no luck getting the adc to work.  The ANSELA value never changes from the default POR setting (00101111b)  even after the following lines execute: 
 setup_adc(ADC_CLOCK_INTERNAL);
 setup_adc_ports(sAN0|VSS_VDD);
 
 No compile errors so I assume the values I'm using are valid.
 
 How do I set the registers manually?
 
 Thanks
 Brian
 |  | 
	
		|  | 
	
		| gpsmikey 
 
 
 Joined: 16 Nov 2010
 Posts: 588
 Location: Kirkland, WA
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 11:09 am |   |  
				| 
 |  
				| Here are the definitions I use for the 18F14k22 - you will need to verify they are the same for your chip, but this is how I reference the registers I need to access the ADC config stuff.  Note the line in my example code above to set the VREFCON0 register as an example ... 
 
  	  | Code: |  	  | // Processor specific ADC config info // Define some SFR registers we need access to ...
 #BYTE VREFCON0 = 0xFBA  // Vref configuration registers
 #BYTE VREFCON1 = 0xFBB
 #BYTE VREFCON2 = 0xFBC
 
 #BYTE ADCON0 = 0xFC2    // A/D converter config registers
 #BYTE ADCON1 = 0xFC1
 #BYTE ADCON2 = 0xFC0
 #define VSS_VFVR  0x800 // new definition to use internal vref not listed in .h
 
 #BYTE ANSEL  = 0xF7E    // Analog Select Registers
 #BYTE ANSELH = 0xF7F
 
 #BYTE OSCCON = 0xFD3    // Oscillator control register
 #BYTE OSCCON2= 0xFD2
 
 | 
 
 
 mikey
 _________________
 mikey
 -- you can't have too many gadgets or too much disk space !
 old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 11:19 am |   |  
				| 
 |  
				| Thanks!  Can I also define CONFIG3H in the same way?  It's address is huge (300005h).  I would like to clear bit #1 (PBADEN) in this register so the portB a/d's are disabled upon POR. 
 Thanks
 Brian
 |  | 
	
		|  | 
	
		| gpsmikey 
 
 
 Joined: 16 Nov 2010
 Posts: 588
 Location: Kirkland, WA
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 11:58 am |   |  
				| 
 |  
				| I'm not sure on that one - seems to me there is something funny about the config registers up there that have to be accessed via a table command or something - I have seen other posts here about that.  I think that is one of the fuses - take a look in the install directory for the compiler (usually C:\Program Files\PICC ) for the file "fuses.txt"  One of the entries I find in there is: NOPBADEN PORTB pins are configured as digital I/O on RESET
 
 which sounds like what you are looking for.
 
 mikey
 _________________
 mikey
 -- you can't have too many gadgets or too much disk space !
 old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 3:07 pm |   |  
				| 
 |  
				| This program should work with vs. 4.110: 
  	  | Code: |  	  | #include <18F26K22.h>
 #device adc=10
 #fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
 #use delay(clock=4M)
 #use rs232(baud=9600, UART1, ERRORS)
 
 //======================================
 void main(void)
 {
 int16 result;
 
 setup_adc_ports(sAN0);
 setup_adc(ADC_CLOCK_DIV_4);
 set_adc_channel(0);
 delay_us(10);
 
 while(1)
 {
 result = read_adc();
 printf("%lx \n\r", result);
 delay_ms(500);
 }
 
 }
 | 
 
 I tested it with an 18F45K22 in hardware, with vs. 4.110, and it worked.
 It displayed these values in the terminal window as I turned a trimpot
 from one end to the other:
 
  	  | Quote: |  	  | 0001
 0001
 0034
 014a
 01a7
 023d
 032d
 03ae
 03ff
 03ff
 | 
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 3:14 pm |   |  
				| 
 |  
				| Thanks for the reply I'll test it out.  In the mean time I have the program working using manual setting of registers and testing / toggling the GO/DONE bit. 
 #byte ANSELA = 0xf38
 #byte ANSELB = 0xf39
 #byte ANSELC = 0xf3a
 #byte ANSELD = 0xf3b
 #byte ANSELE = 0xf3c
 #byte ADCON0 = 0xfc2
 #byte ADCON1 = 0xfc1
 #byte ADCON2 = 0xfc0
 
 #byte CM1CON0 = 0xf78
 #byte CM2CON0 = 0xf77
 
 
 
 //setup_adc(ADC_CLOCK_INTERNAL);
 //setup_adc_ports(sAN0|VSS_VDD);
 ANSELA = 1;
 ANSELB = 0;
 ANSELC = 0;
 ANSELD = 0;
 ANSELE = 0;
 
 ADCON0 = 1;					//AN0 (only) selected and a/d enabled
 ADCON1 = 0;					//Vss & Vdd are reference
 ADCON2 =  0x81;				//Rigth justify,
 
 CM1CON0 = 0;
 CM2CON0 = 0;
 
 
 Thanks Again
 Brian
 |  | 
	
		|  | 
	
		| bdrmachine 
 
 
 Joined: 24 Jan 2010
 Posts: 14
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 7:47 pm |   |  
				| 
 |  
				| PCM programmer 
 I tested the code with my hardware and I get the same results as before (ANSELA remains at POR value).
 
 The manual register select code work as expected.
 
 Thanks
 Brian
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 13, 2011 8:53 pm |   |  
				| 
 |  
				| The POR (power-on-reset) value of ANSEL is "all 1's" for the analog bits. This means they are all configured as analog pins on power-up. I looked
 at the .LST file for vs. 4.110 and it doesn't write to ANSELA (0xF38).
 It leaves it in the power-on-reset state.
 |  | 
	
		|  | 
	
		|  |