PIC Interface PWM

This code sets up PWM on PIC MCU (RC2 pin), with duty cycle controlled by switch inputs (RB0–RB3). Useful for LED dimming or DC motor speed control. Generate predefined PWM using four buttons

Functions for PIC Interface PWM

  • pwm_init()
  • pwm_dutycycle(unsigned int duty)

How It Works

  1. Timer2 + CCP1 module generate PWM.
  2. RC2 pin outputs PWM signal.
  3. Buttons on RB0–RB3 control duty cycle.
    • RB0 → OFF (0%)
    • RB1 → 25% duty
    • RB2 → 50% duty
    • RB3 → 100% duty

Code of PIC Interface PWM

  • Generate PWM using PWM functions
  • Define Port-B as input and RB0, RB1, RB2 and RB3 used as button input

Note  :  UN-command the line depend on your preferred compiler.

//www.ArunEworld.com/embedded/microchip/pic_mcu/
#include<pic.h> // for Hi-Tech Compiler

#define _XTAL_FREQ 4000000

//short currduty1=16;
void init()
{
    PORTB=0X00;
    TRISB=0X0f;
}

void pwm_dutycycle(unsigned int duty)
{
    CCPR1L=duty;
    CCP1CON&=0xCF;
    CCP1CON=(CCP1CON|(0X30&(duty<<4)));
}

void pwm_init()
{
    TRISC=0X00;
    CCP1CON=0X0C;
    PR2=96;
    TMR2=0;
    T2CON=0x7B;
    pwm_dutycycle(0);
    T2CON=0X7F;
}

void delay(unsigned int de) {   while(de--);    }

void main()
{
    pwm_init();
    while(1)
    {
        if(RB0) {   /*delay(100);*/ pwm_dutycycle(0);   }
        if(RB1) {   /*delay(100);*/ pwm_dutycycle(64);  }
        if(RB2) {   /*delay(100);*/ pwm_dutycycle(128); }
        if(RB3) {   /*delay(100);*/ pwm_dutycycle(255); }
    }   
} 

 

 Code Explanation

Header & Clock

#include <pic.h>   // Hi-Tech C compiler header
#define _XTAL_FREQ 4000000   // 4 MHz crystal frequency
  • pic.h gives access to PIC registers.
  • _XTAL_FREQ is required for delay macros (__delay_ms() / __delay_us()).

Initialization

void init()
{
    PORTB = 0x00;   // Clear PORTB
    TRISB = 0x0F;   // RB0–RB3 as input, RB4–RB7 as output
}
  • PORTB is used for input switches (RB0–RB3).

Duty Cycle Function

void pwm_dutycycle(unsigned int duty)
{
    CCPR1L = duty;                // Load 8 MSBs of duty cycle
    CCP1CON &= 0xCF;              // Clear lower 2 bits
    CCP1CON = (CCP1CON | (0x30 & (duty << 4)));  // Update lower 2 bits
}
  • Configures PWM duty cycle.
  • CCPR1L stores the high 8 bits.
  • CCP1CON<5:4> stores the lower 2 bits → total 10-bit resolution.

PWM Initialization

void pwm_init()
{
    TRISC = 0x00;      // PORTC as output (PWM pin RC2)
    CCP1CON = 0x0C;    // Configure CCP1 in PWM mode
    PR2 = 96;          // Period register → sets PWM frequency
    TMR2 = 0;          // Clear Timer2
    T2CON = 0x7B;      // Start Timer2 with prescaler
    pwm_dutycycle(0);  // Start with 0% duty cycle
    T2CON = 0x7F;      // Enable Timer2
}
  • PWM output will be on RC2 (CCP1 pin).
  • PR2 + T2CON determine the PWM frequency.
  • CCP1CON = 0x0C → Enables PWM mode.

Main Function

void main()
{
    pwm_init();   // Initialize PWM
    while(1)
    {
        if(RB0) pwm_dutycycle(0);     // 0% duty → OFF
        if(RB1) pwm_dutycycle(64);    // ~25% duty
        if(RB2) pwm_dutycycle(128);   // ~50% duty
        if(RB3) pwm_dutycycle(255);   // ~100% duty
    }   
}
  • Reads push buttons on RB0–RB3.
  • Each button sets a different PWM duty cycle.
  • The PWM output can control LED brightness / motor speed / buzzer tone.

Please turn AdBlock off, and continue learning

Notice for AdBlock users

Please turn AdBlock off
Index

Discover more from ArunEworld

Subscribe now to keep reading and get access to the full archive.

Continue reading