PIC24/dsPIC33 ADC Input

Last modified by Microchip on 2024/06/24 06:33


This example demonstrates how to configure and use an internal Analog-to-Digital Converter (ADC) on a PIC24F MCU to change the speed of a blinking Light Emitting Diode (LED). You will configure a PIC24 timer to blink an LED on the demo board at an interval determined by the timer's Period register. The demo board used in this example has a digital potentiometer (pot) connected to one of the MCU's analog-capable pins. When the pot is moved, the resulting voltage on the analog pin will change. You will write code that triggers the ADC to read the value of the attached pot and place that value into the timer's Period register.

When the project is completed and programmed into the development board, the speed at which the LED blinks will change as the pot is rotated.

diagram of ADC conversion wave form

This lab uses timer interrupts and builds upon the work done in the timer interrupts example. For more information on timer interrupts, please refer to the "Programming a PIC24/dsPIC33 Timer Using Interrupts" example.

With the use of MPLAB® Code Configurator (MCC), this project demonstrates the following:

  • Creating a project for the 16-bit Microchip MCU on the development board
  • Adding a timer and the ADC unit to the list of peripherals used by the application
  • Configuring the MCU system oscillator to run off the internal RC oscillator at 4 MHz
  • Configuring one of the I/O pins connected to an LED as an output
  • Configuring the pin connected to the pot as an analog input
  • Configuring the added timer to trigger an interrupt based on the Period register
  • Configuring the ADC conversion to be triggered by the application software
  • Configuring the timer interrupt priority
  • Generating MCC code
  • Manually editing MCC-generated code to:
    • Create a function that toggles the LED and triggers the ADC conversion
    • Register the just-written function as the Interrupt Service Routine (ISR) for the timer
    • Start the timer operation when the application begins execution
    • Monitor the ADC conversion process and put the ADC result into the timer's Period register
  • Building and programming the completed application into the development board

As a result of this lab, the selected LED will begin to blink. The speed at which the LED blinks will change as the pot is manually rotated.

This project uses the PIC24F Curiosity Development Board. This board has several LEDs, two input switches, and one digital potentiometer. This lab uses the LED connected to pin RA10 (PORTA pin 10) and the digital pot connected to pin RC0 (PORTC pin 0).

PIC24F curiosity showing digital pot and led1

Back to Top


To follow along with this example, you will need the following software and hardware:

Software Tools

Hardware Tools

Information on how to download the software tools or acquire the development board can be found on the "Resources Needed for PIC24F Labs" page.

Back to Top


Create the Project

After installing the software, connect the PIC24F Curiosity Development Board to a USB port on your computer. Create a new standalone project in MPLAB X IDE for a PIC124FJ128GA204. The PIC124FJ128GA204 is the microcontroller on the PIC24F Curiosity Development Board. When the project creation wizard asks for a hardware tool (Step 2 in the New Project window), select the PIC24F Curiosity Board as displayed in the accompanying image.

New project window showing the PIC24F curiosity board

If this is your first time creating an MPLAB X IDE project, please visit the "Create a Standalone Project" page to follow step-by-step instructions on how to do this.

After the project has been created, the Projects tab in the upper-left corner of the IDE shows that the project has been created with no source or header files.

projects tab showing no source files

Back to Top

Open MCC

Open MCC under the Tools > Embedded menu of MPLAB X IDE.

Open MCC under the Tools > Embedded menu of MPLAB X IDE.

MCC will place a Resource Management tab on the left-hand side of the IDE. Inside this tab, you will see a section for Project Resources and Device Resources. For each MCC-generated project, you will need to verify/modify the System Modules under the Project Resources window.

verify/modify the System Modules under the Project Resources window

Back to Top

Add a timer and the ADC to the list of peripherals being used in the application

From the Device Resources section of the MCC Resource Management window, locate Timer1 (TMR1).

From the Device Resources section of the MCC Resource Management window, locate Timer1 (TMR1)

Double-click on TMR1 to add this peripheral to the resources available to the project.

Double-click on TMR1 to add this peripheral to the resources available to the project

Repeat the step to add ADC1 [ PIC24F / dsPIC33 / PIC32MM MCUs]

Repeat the step to add ADC1 [ PIC24F / dsPIC33 / PIC32MM MCUs]

Back to Top

Set the Project Resources

There are three system elements that need attention:

  • Interrupt Module: controls the MCU's interrupts.
  • Pin Module: configures the I/O pins.
  • System Module: selects and configures the clock source for the MCU.

Interrupt Module

This section displays and controls the priority and the enable bit for each interrupt. This section will be reviewed after the Timer and ADC peripherals are configured (Step 6).

System Module

The System Module allows the user to configure the MCU's clock, and the Watchdog Timer (WDT), and make changes to the debug pin assignments. This feature of the PIC24F MCU has numerous options, which are typically modified to fit the needs of the application. MCC provides default settings if no changes are selected by the developer. For this lab, accept the default clock settings:

  • 8 MHz Internal Free Running Oscillator with no Prescaler, but a 1:2 Postscaler (4 MHz Fosc)
  • Watchdog Timer - disabled
  • Unchanged debug pins

To verify the default settings, click on the System Module tab and verify the following selections have been made:

click on the System Module tab and verify the default settings

We will now set the pin connected to LED1 (RA9) as an output pin. In the Grid View window, click on the output box under RA9. The grid view will display the padlocks in green, indicating these pins have been configured for use.

the grid view

  1. Ensure that RA10 is set as an output pin.
  2. Rename RA10 to "LED".
  3. Select RC0 in the ANx row as the analog signal (this pin is connected to the pot).
  4. Leave the analog change name channel AN10 unchanged.

Ensure that RA10 is set as an output pin. Rename RA10 to "LED". Select RC0 in the ANx row as the analog signal (this pin is connected to the pot). Leave the analog change name channel AN10 unchanged.

Back to Top

Configure Timer1 for 1/2 Second Period with the Interrupt Enabled

We will start with the timer period at 1/2 second and will modify it based upon the ADC value with the Fosc set at 2 MHz, TMR1 will be unable to generate a 1/2 second period as the 16-bit counter will overflow before 1/2 second. To lengthen the period window for this timer, we will prescale the system clock by 0256 to down the timer. Once the timer is slowed, we will be able to select the 1/2 second timer period.

Select TMR1 from the Project window and select the following settings:

Select TMR1 from the Project window and make select the following settings

Ensure that the Enable Timer Interrupt box is checked.

Back to Top

Verify the Priority of the Timer Interrupt

Select the Interrupt Module icon in the Project Resources window to verify that the TMR1 interrupt has been enabled.

Verify the Priority of the Timer Interrupt

For this example, TMR1 should be shown as the only enabled interrupt with the default priority of '1.' Please refer to the 16bit-interrupts page for details on how interrupts are implemented and programmed on this device

Back to Top

Configure the ADC unit

  • Set the trigger source to Clearing sample bit and sampling and begins conversion
  • Set the output format to Absolute decimal result, unsigned, right justified
  • Enable the ADC.
  • Enable Auto Sampling.
  • Verify the name given the I/O pin.

Configure the ADC unit

Back to Top

Generate Code

To generate the code, click the Generate button on the MCC window.

click the Generate button on the MCC window

The projects tab will show the source and header files created by MCC.

The projects tab will show the source and header files created by MCC.

The main(void) is located within the main.c file. main(void) calls the MCC generated SYSTEM_Initialize() function before it enters the while(1) loop.

The main(void) is located within the main.c file. main(void) calls the MCC generated SYSTEM_Initialize() function before it enters the while(1) loop

SYSTEM_Initialize() in turn calls PIN_MANAGER_Initialize()INTERRUPT_Initialize()CLOCK_InitializeADC1_Initialize, and TMR1_Initialize(). These functions initialize the ADC, and TMR1, set up the I/O pins, and establish the interrupt writing to the device's function registers.

SYSTEM_Initialize() in turn calls 5 other functions

If you are interested in learning more about the details of device initialization, please consult the PIC24FJ128GA204 datasheet for the specific registers and settings used to configure the System Clock, the I/O pins, ADC, and Timers.

Back to Top

Modify the MCC-generated Code to Complete the Application

We will now modify main.c.

An inspection of MCC-generated header file pin-manager.hadc1.h, and tmr1.h shows that MCC has created several control functions useful for our applications.

pin-manager.h Function Prototype:

  • LED1_toggle();: changes the value of the I/O pin connected to the LED1.

tmr1.h Function Prototypes:

  • TMR1_Start(): starts the operation of TMR1.
  • TMR1_SetInterruptHandler(): registers a user defined function as the ISR for TMR1.
  • TMR1_Period16BitSet(): sets the period length for TMR1.

adc1.h Function Prototypes:

  • ADC1_ChannelSelect(channel): selects the pin to be connected to the ADC unit.
  • ADC1_Stop(): triggers the conversion by clearing the sample bit.

Yes, ADC1_Stop() will actually start an ADC conversion. While the name of this function is counter-intuitive, when Auto-Sampling is enabled, stopping the sampling begins the conversion.

  • ADC1_IsConversionComplete: returns a True if the ADC unit has finished the conversion.
  • ADC1_ConversionResultGet: returns the value of the last conversion.

Make the following modifications to main.c

  1. Insert the text #include "mcc_generated_files/mcc.h" near the top of the file.
  2. Create a function void My_ISR(void); which toggles the LED, then call ADC1_Stop.
  3. Register My_ISR as the ISR for TMR1 by calling TMR1_SetInterruptHandler(My_ISR).
  4. Insert the code in main.c below to start the ADC conversion and put the results into the timer Period register.


#include "mcc_generated_files/system.h" 
"mcc_generated_files/mcc.h" //##### must be added ##### 

void My_ISR(void)
      ADC1_SoftwareTriggerDisable(); // trigger next conversion
int main(void)
      ADC1_SoftwareTriggerDisable();    // begin first conversion
     while (1)
           if (ADC1_IsConversionComplete(channel_AN10))
                 if (ADC1_ConversionResultGet(channel_AN10)==0)
           // application code goes here
   return 1;

#include "mcc_generated_files/mcc.h" is required to be placed in any application source file which accesses MCC generated functions. This line must be placed above the application's call to an MCC function. Not all versions of MCC correctly include this code into main.c. You will also need to manually add this line to each of the application source files you create.

Back to Top

Build, Download, and Run the code

To run the program on the development board, click on the Make and Program Device Main Project button build target and program. This will build the program into the flash memory of the PIC®. The output window of the IDE will tell you when the device has been programmed and the application is running.

Build, Download and Run the code

Back to Top


When the application is built and programmed into the MCU, LED1 will change state every 1/2 second.

When the application is built and programmed into the MCU, LED1 will change state every 1/2 second.

Back to Top