6th July 2010

Tutorial 5 – A/D Conversion in C

posted in Uncategorized |

Tutorial Goal: Implement A/D conversion as seen in Tutorial 3 in C

This document builds on Tutorial 3 and Tutorial 4. The purpose of this tutorial is to familiarize the reader with the A/D functionality of a PIC18F4550 microcontroller using the C18 compiler.

There are functions available to simplify the use of A/D (documented in the PIC18F Peripheral Library Help Document.chm, likely found in C:\MCC18\doc). However, this tutorial will focus on setting everything up manually, since the use of these functions is trivial once the underlying process is understood.

For this tutorial, I will be working with:

Remember that you may need to update your include and lib paths after updating your MPLAB IDE (see here for more details).

Tutorial 5 Setup - A/D conversion in C on the PIC18F microcontroller
The starting point will be the hardware from Tutorial 3 and the code from the previous tutorial, which blinked an LED at a specified interval. The following code is explained in more detail in Tutorial 4:

#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB 
#pragma config WDT = OFF //Disable watchdog timer

#define LEDPin LATDbits.LATD1 //Define LEDPin as PORT D Pin 1
#define LEDTris TRISDbits.TRISD1 //Define LEDTris as TRISD Pin 1

We do not need to #define the A/D pin since we will not directly address it.

The A/D settings are explained in detail in Tutorial 3, so please look through it before continuing with this tutorial.

To set up the A/D module, the ADCON registers must be set:

	ADCON1 = 0b00001110;//VSS,VDD ref. AN0 analog only
	ADCON0 = 0x00;//clear ADCON0 to select channel 0 (AN0)
	ADCON2 = 0b00001000;//ADCON2 setup: Left justified, Tacq=2Tad, Tad=2*Tosc (or Fosc/2)
	ADCON0bits.ADON = 0x01;//Enable A/D module

Once the A/D module is set up and enabled, we can use it to gather data:

		ADCON0bits.GO_DONE = 1;//Start A/D Conversion
		while(ADCON0bits.GO_DONE != 0);//Loop here until A/D conversion completes
		delay = ADRESH;//Set the delay to the 8 MSB
		LEDPin = ~LEDPin;//Toggle LED Pin
		if (delay > 0)
			Delay1KTCYx(delay);//Delay (argument of 250 will delay 1 second at 1MHz since each instruction takes 4 cycles)

Setting the GO_DONE bit starts the conversion. It is possible to receive the result via an interrupt, but to keep this tutorial simple, a while loop will poll the GO_DONE pin until it goes low (meaning the A/D conversion is finished). The amount of time it takes to go low depends on the ADCON2 settings above (consult Tutorial 3 for more information). Once the conversion is finished, we set the delay variable to the 8 Most Significant Bits of the result. It would be possible to get all 10 bits using

delay = (((unsigned int)ADRESH)<<8)|(ADRESL);

but the Delay1KTCYx function only takes values of 1-255, so the extra 2 bits are unnecessary for this application. After toggling the pin, we should check if the delay is 0. This is important because executing Delay1KTCYx with a value of 0 will cause a delay of 256,000 cycles instead of the intended 0 cycles.

This is everything that is necessary to perform a conversion and retrieve the result. An obvious improvement would be to replace the while loop with an interrupt, so that the main loop would not need to actively wait for the conversion.

The result is visually the same as the video in Tutorial 3:

Check the FAQ (in progress) or ask a question below if you are having problems.

C file:main.c

This entry was posted on Tuesday, July 6th, 2010 at 3:02 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

There are currently 25 responses to “Tutorial 5 – A/D Conversion in C”

Why not let us know what you think by adding your own comment! Your opinion is as valid as anyone elses, so come on... let us know what you think.

  1. 1 On July 7th, 2010, cooper said:

    thx for the tutorial’s :) could you put one online for serial datacommunication with usart?

  2. 2 On August 19th, 2010, juan said:

    i have some experience with 8051 assembler…now im starting with PICs.i bought a 18f2550..i saw ur assembler tutorial an i understood..i heard that usually PIcs 18 are programmed in C..do u think its better program in C or in assembler…i really think asembler its no too fast to program but u really understant how the micro works…here people usually use CCS but i tryed it a litle…and pic configuration its very easy…but code (in C way) its very extrange too me… now in your experience do u think..i have to forget assembler and start to program in to c? what do u usually use?

  3. 3 On October 2nd, 2010, Mike said:

    could you do an example data aquisition using USB?

  4. 4 On October 29th, 2010, TomsTools said:

    Thank you for the tutorials, having this stuff in c is cool


  5. 5 On November 4th, 2010, Cristian said:

    Hi, I saw your tutorials and I think are very good. I would like to experiment with the USB module. MPLAB C for PIC18 in LITE mode, has libraries to support USB? I hope you continue with the tutorials because they help everyone. Thanks

  6. 6 On January 13th, 2011, nganso said:

    je souhaiterai avoir le code du PIC18F4620.
    merci d’avance.

  7. 7 On February 9th, 2011, AC said:

    Nice tutorials. Do you think you can make one using USB? I am trying to do a project with the PIC18F4550 following http://www.create.ucsb.edu/~dano/CUI/ but I am not sure how to make simple code that displays “Hello World”

    Hoping to see more tutorials. Thanks!

  8. 8 On February 14th, 2011, Toon said:

    Thanks a lot for these tutorials, they are very useful!

  9. 9 On February 16th, 2011, Koen said:

    Thank you very much, it was a great help to my project!

  10. 10 On March 2nd, 2011, John said:

    wow, exactly what I was looking for!
    thanks for the explanation man, its very helpful!
    keep up the good work! :D

  11. 11 On March 7th, 2011, Kurt said:

    Hi there,

    Can you do a tutorial on how to handle sinewaves on the ADC (i.e. the negative portion). Also, some tips on using an external oscillator would be great!


  12. 12 On April 26th, 2011, Brian said:

    These are great tutorials. They have really helped my learning curve to get up to spped with the microchip tools.

    I did find one error in the code above. Should the following line…

    ADCON0bits.GO_DONE = 1;//Start A/D Conversion


    ADCON0bits.GO = 1;//Start A/D Conversion

  13. 13 On August 22nd, 2011, thulasi said:

    I am using the PIC18F46J50 to do the A/D conversion with a MPLAB starter kit for pic18f MCUs. How and when can I view the values of delay and ADRES/ADRESH/ADRESL (as specified in the post)in the watch window – Is it after the debugging step (I am using “Starter Kits” as the debugger) ?

  14. 14 On August 22nd, 2011, thulasi said:

    When I view the values in the watch window, I am getting different values for delay and ADRES (which should ideally be the same right?)

  15. 15 On November 16th, 2011, David deSousa said:

    The trouble is, this code does not produce true PWM. True Pulse Width Modulation is where the duty-cycle of a fixed frequency signal varies by % time on with the complementary time off. This setup and code produces a frequency varying by voltage with a fixed 50% duty-cycle. Not the same thing.

    Many applications need to have a fixed frequency signal, such as analog motor speed controllers, because the motor (non stepper) has a characteristic impedance favoring a fixed frequency and thus a true PWM takes advantage of the efficiency gained.

    I tried this code. It does work to blink a LED sure enough, but it is not a useful PWM implementation. Nice try though.

  16. 16 On December 27th, 2011, Paritosh said:

    Can you please tell me how to get the ADC output in hyperterminal? Can u send me the code for that. I’d be very grateful to you. Thanks…

  17. 17 On April 4th, 2012, priyanka said:

    thanks this really helped me to gind where was i wrong in my program.

  18. 18 On May 10th, 2012, robert said:

    thanks a lot! it is very simple and for begin it is very good!

  19. 19 On June 17th, 2012, Hrusikesh said:

    I am getting some problem in ADC interfacing of PIC18F6527 . I have taken like this,
    ADCON1 =0x0E; //0x0B ;
    ADCON2 = 0x08; // 0x92 ;
    ADCON0 |= 0x01 ; //to set the ADON bit
    ADCON0 |= 0x02 ; // go/done bit set
    while(ADCON0 & 0x02 );
    But the controller is not clearing the go/done bit .
    what mistake I would have done ,please help me …

  20. 20 On July 6th, 2012, Alexander Maya said:

    Awesome Work!!

  21. 21 On August 6th, 2012, sree said:

    pls put the circuit diagram

  22. 22 On June 24th, 2013, Pearce said:


    Thanks for the tutorial. I’m trying to do this right now with a PIC18F2620. I made sure to include the proper header files and such but when I go to build it says TRISDbits and LATDbits are not defined. Can you advise has to how I can fix this?


  23. 23 On November 2nd, 2013, karim said:

    Great tutorial – Thank you. I just read through this in 20 minutes and understood everything, yet i understood nothing in a 3 hour lab class on this subject at school.

  24. 24 On November 4th, 2013, Mike Richardson said:

    Once again, excellant for getting started.
    Works fine with 44-pin demo board with PICkit3 with the following changes;

    #pragma config FOSC = INTIO7 //Internal oscillator, CLKOUT on RA6
    #pragma config WDTEN = OFF //WDog off.

    Thank you.

  25. 25 On July 17th, 2014, thiru said:

    Hi, if i want to add (ADRESL + ADRESH ) value put into delay what will be the program code i must write? – Thanks

Leave a Reply

  • Sponsored Links

    July 2010
    M T W T F S S
    « Nov    
  • Donate