Skip to main content

Experiment No. 8: Use of PWM to control the brightness of a LED.

A PIC16F628A has an in-built Capture/Compare/PWM (CCP) module for which the I/O pin is served by RB.3 (Pin No. 9). In this experiment we are going to use the CCP as a PWM to control the power to a LED. PWM stands for the Pulse Width Modulation where the width of a digital waveform is varied to control the power delivered to a load. The underlying principle in the whole process is that the average power delivered is directly proportional to the modulation duty cycle. The term duty cycle describes the proportion of on time to the regular interval or period of time; a low duty cycle corresponds to low power, because the power is off for most of the time. Duty cycle is expressed in percent, 100% being fully on.
Image Source:
The mikroC has an in-built library functions for PWM hardware module. Click here for details.

Experimental Setup:

In this experiment, we are going to have 11 different intensities (including complete turn OFF) of a LED by varying the duty cycle. We will connect a LED to RB.3, and two Push Buttons to RB.0 and RB.1. The two buttons are for Increment/Decrement the intensity of the LED.


Project Name: Use of Timer 0 and Interrupt
* Copyright:
(c) Rajendra Bhatt, 2009.
* Description:
Use of CCP module as a Pulse Width Modulation

* Test configuration:
Oscillator: XT, 4.0 MHz

unsigned short new_DC, current_DC;
void main() {

PORTB = 0; // Initial state of port B
TRISB = 3; // RB0, RB1 input, RB3 (PWM1) output
PWM1_Init(5000); // PWM module initialization (5KHz)
new_DC = 0; // Initial value of variable Duty Cycle
current_DC = 0;
PWM1_Start(); // Start PWM1 module with Zero DC
while (1) {
if (Button(&PORTB, 0,1,0)) { // If the button connected to RB0 is pressed
if (new_DC < 250)         // Don't go above 250
new_DC = new_DC + 25 ; // increment Duty Cycle by 25
if (Button(&PORTB, 1,1,0)) { // If the button connected to RB1 is pressed
if (new_DC !=0)                 // Don't go below 0
new_DC= new_DC - 25 ; // decrement Duty Cycle by 25

if (current_DC != new_DC) {   
current_DC = new_DC ;
PWM1_Set_Duty(current_DC); // Change the current DC to new value


Experimental Output Video:


  1. Do you have a schematic for your test board?


  3. This comment has been removed by the author.

  4. This is awesome, I never know controlling PWM in PIC would be this easy.

  5. program that will control two LEDs using PWM. Every time the external interrupt button is pushed the program reads the analogue input and uses the value to set up the duty cycle of one of PWM LEDs (hint--> you must use A/D module). Thus, the external interrupt toggles between the two PWM LEDs. The program also uses other two LEDs for signalling which PWM LED is the active output.

    do u have a way to get through this ? like gv me hints and can u gv me ideas how to use the external interrupt to toggle between the two leds


  6. The PIC I am using is PIC16F628A, and it doesn't have A/D converter. If you want to implement more than one PWM with PIC16F628A, you can use software PWMs. Regarding the use of interrupt, I will write an article on that very soon.

  7. Hi. Can you put only the led brightness controling schematic? I want to build a led brightness controller with 2 buttons. 1 to increase the brightness and 1 to deacrease. Thanks

  8. I have posted a similar tutorial here, and it has circuit diagram too.

  9. This comment has been removed by the author.

  10. thx very much. I have one question. Can you modify it to a pic 12f675.

  11. Hi, Can you help me? I have test it on Proteus 7.5SP3, but It's not work!

  12. Thanh,
    I suggest you to read my new post here:


  13. Very useful tutorial, thank you!


Post a Comment

Popular posts from this blog

Contact less tachometer using PIC16F628A

Tachometer is a device that gives you the information about the rotational speed of any shaft or disc. It usually measures the speed in revolutions per minute (RPM). Today we are going to make a simple tachometer that could measure the rotation speed of a disk without making any physical contact (that's why it is contact less) with the rotating object. The range of this tachometer is 0 - 9999 RPM and displays the RPM on a multiplexed 4-digit seven-segment display. Of course, we are going to do this project on our usual PIC16F628A development board.

Infrared sensor
Contact-less measurement of RPM will be achieved through an IR sensor. An IR diode will send a beam of infrared towards the rotating disc, and any reflected pulse will be received by a photo diode. The resistance of a photo diode drops drastically when exposed to infrared. An infrared is reflected by a white surface and absorbed by the dark ones. The test disc for this project is shown below. You can see the …

Experiment No. 2 : Push Button and Seven Segment Display Interface

In this experiment, we will program the PIC16F628A as an UP/DOWN Decade Counter. The count value will be displayed on a Seven-Segment Display and will be incremented/decremented by two push buttons on the board.

Experimental Setup:
The board has built in interface for a multiplexed 4-digit seven segment display (HS-5461AS2 from will select only one digit by connecting a Digit Select pin to Vcc, as shown in figure below. A black jumper wire is used for this purpose. The seven segments will be driven through PORTB (already wired on the board). Connect Push Buttons (PB3 and PB4) to RA1 and RA0 female headers using jumper wires.

PIC16F628A Development Board

The development board we are going to make for our experimental microcontroller PIC16F628A will look like this. Here are the features it is going to have:
Access to all I/O pins through female header pins4 Push Buttons for Input4 LEDs for OutputAn LCD Interface PortA 4-digit Seven-Segment Display InterfaceLCD Backlight Switch and Contrast AdjustmentICSP Programming (Very Important)