PWM in pic18f4520 Help

Thread Starter


Joined Nov 19, 2015
Hello guys, First really thanks for the attention. Well going to the subject of my doubts, I'm planing to do a LED dimmer using PWM modulation in a PIC18f4520 using assembly language as my final project. I'm varying the duty cycle from 0 to 100% using a button that increases the duty cycle in 25%. But i'm having problems to make my circuit work, maybe because of some questions that I still don't know the answers or maybe because I programed wrongly, but I really hope that you guys can help me to overcome these issues.
So first I did some research about PWM to understand how it works, and after got some understanding about the subject I tried to implement the process in the pic18 using the steps provided by the datasheet of the PIC18f4520 to set the PWM mode. But I still have some questions.
I. How do I know the proper PWM frequency that I will need to my project? I just need choose any frequency and check if it works?!
II. I'm thinking to use the internal clock of the PIC18f which is 8Mhz, for these application. Is this possible or do I need to use a external clock for my project? If yes how can I set this in my code?

OBS: After wired my Pic and test my output in PORTB with a oscilloscope i didn't got nothing but noisy. It is like the PWM setup to PORTB isn't working. I really don't know what else to do, please anybody could help me with these big problem?!

The result of my work is the following code:

    call    pwm_setup
    goto    loop

    movlw    0x7F                     ;PR2 = Period = 1/F Setting PWM period as 127
    movwf    PR2
    movlw    0x00                      ;Set PWM duty cicle as a initial value of 0%
    movwf    CCPR2L                ;This register contains the 8MSbit of the dutty cicle
    bcf          CCP2CON, 5        ;Clear bit 5 (bits 5 and 4 are the LSbit   
    bcf          CCP2CON, 4        ;Clear bit 4

    clrf    PORTB                        ;Clear PORTB
    bcf     TRISB, 3                     ;Make RB3 output
    bsf     TRISB, 0                     ;Make RB0 as input

    movlw     0x07                      ;TMR2 = on, prescale = 1:16
    movwf     T2CON
    movlw     0x0C
    movwf    CCP2CON              ;turn on pwm


    btfsc      PORTB,0                ;testing RB0(Button) was pressed
    call        inc                           ;if was pressed call inc
    goto      loop                         ;If not Check again

inc                                             ;Incremeting the Dutty cycle in 25%
    movlw     0x20           
    addwf     CCPR1L,1



Joined Jun 26, 2012
Hi and welcome to AAC!

On the 4520, the default CCP2 is RC1. I don't see where you have changed CCP2MX in CONFIG so your output is going to be to RC1 - assuming it is set up right. It's very important to FULLY specify ALL config bits, every time. You also should specify ALL IO inits as well.

To make this all work, you set up TMR2/PR2 to generate the PWM period as a number of counts. The duty cycle is specified by loading a count into CCPR2L (and CCP2CON <5,4> if you want 10 bit resolution). That value is NOT in %, it is in counts that represent a fraction of the PWM period counts.

I would start by just setting up a 25% duty cycle and running that. When that works, add the code that modifies the duty cycle.

Some starting numbers:
8MHz oscillator
Prescaler = 16
PR2 = 124
Gives a PWM period of 1KHz.
CCPR1L= 31 gives about 25% duty cycle

Have fun.
Last edited: