Select Page

In my other post – PIC10F322 XC8 Analog-to-Digital Converter (ADC) Getting Started.

I went over the basics of getting up and going with the ADC on the PIC10F322. The code read the value from a potentiometer and if the value was over a certain range – turn on the LED.

In this code, we are going to read the value from the potentiometer connected to RA1 and then use that value to control the brightness of the LED directly connected to RA0.

If you wanted to control a larger load – say a motor. You could (with the right values) throw a transistor on the output of RA0 and drive something larger. I will save that for another blog post.

The only thing I want to point out in the code is that I am taking the value from the pot , which is only an 8 bit value, and multiplying that by 4 to get a 10bit number for the PWM.

The Circuit

And now… for the code.

 * File:   adc_pwm.c
 * Author: Jamie
 * Created on 9/14/2021, 8:04 PM

#include <xc.h>
#include <stdint.h>

//Device Configuration
#pragma config FOSC = INTOSC  // Oscillator Selection 
#pragma config BOREN = ON    // Brown-out Reset
#pragma config WDTE = OFF    // Watchdog Timer
#pragma config PWRTE = ON    // Power-up Timer
#pragma config MCLRE = OFF   // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF      // Code Protection 
#pragma config LVP = OFF     // Low-Voltage Programming 
#pragma config LPBOR = ON    // Brown-out Reset Selection bits
#pragma config BORV = LO    // Brown-out Reset Voltage Selection
#pragma config WRT = OFF    // Flash Memory Self-Write Protection

//Used to calculate the delay time - Change depending on processor Speed
#define _XTAL_FREQ 16000000  //16Mhz

void setup(void);
uint8_t ADC_Read(void);
void set_dutycycle(volatile uint8_t* pDutyCycleHigh, volatile uint8_t* pDutyCycleLow, uint16_t dutyValue);

void setup(void){    
    //Set the System Clock - You can change this to match the setting you are looking for
    OSCCONbits.IRCF = 0b111;  //Set System Clock to 16Mhz
    //Pin LED is connected to
    TRISAbits.TRISA0 = 0;  //Make pin Output A.0
    ANSELAbits.ANSA0 =0;   //Disable Analog A.0
    set_dutycycle(&PWM1DCH,&PWM1DCL,0); //Clear Duty Cycle for PWM1
    PR2 = 0xFF;   
    T2CONbits.T2CKPS = 0b00;
    T2CONbits.TMR2ON = 0x01;
    PWM1CONbits.PWM1OE = 0x01;   //PWM1 Turn on 
    PWM1CONbits.PWM1EN = 0x01;  //PWM1 Enable Output

    TRISAbits.TRISA1 = 1;  //Make pin Input A1
    ANSELAbits.ANSA1 =1;   //Enable Analog A1
    //Set Analog conversion clock FOSC/32, since we are running 16Mhz, we need to have a conversion time at or greater 1uS
    //FOSC/32 will give us 2uS
    ADCONbits.ADCS = 0b010; 
    //Select the Analog channel - A1 or AN1
    ADCONbits.CHS = 0b001;
    //Turn on the ADC module
    ADCONbits.ADON = 1;      

void main(void)
        uint8_t ADC_Value = 0;
        ADC_Value = ADC_Read();  //Read the ADC Value
        uint16_t ADC_adj_Value = ADC_Value * 4; //PWM is running at 10bits. ADC is 8bits. We will fluff it up some
        set_dutycycle(&PWM1DCH,&PWM1DCL, ADC_adj_Value); //Set the Duty cycle of PWM1
        __delay_ms(500);  //Wait .5 second and do it again  

uint8_t ADC_Read(){
    //Starts the ADC read and waits until a conversion is complete before returning
    //Returns the ADC value
    ADCONbits.GO_nDONE = 1;  //Start the conversion
    while (ADCONbits.GO_nDONE == 1){
    return ADRES;

void set_dutycycle(volatile uint8_t* pDutyCycleHigh, volatile uint8_t* pDutyCycleLow, uint16_t dutyValue)
/*Sets the duty value of the supplied registers. 
 *Usage set_dutycycle(&PWM_duty_register_high,&PWM_duty_register_low, duty_value)
 *Valid range for 10bit resolution is 0 - 1023
 *TO convert percent to value, lets say we want 33%.  1023 x .33 = 337.59  round it to 338.
 *338 would be the value we enter for the duty.  */
    *pDutyCycleLow =  (uint8_t)((dutyValue & 0b11) << 0x06);  //Get the LSB
    *pDutyCycleHigh = (uint8_t)(dutyValue >> 0x02);    //Get the MSB

Let’s talk!

I am always looking for oppunities to put my skills to work.
I am always looking to connect with like minded people.

Want to connect – drop me an email