Maker Pro
Maker Pro

Understanding PWM with PIC (assembly)

mollekake

Jun 30, 2014
37
Joined
Jun 30, 2014
Messages
37
Hello all.
I got a PIC16f1824 that i want to experiment with PWM on.
But i don't understand it completely. Why does the frequency need to be set? What should i set it to? How do i set it?
Does PWM only work on certain pins?
If anyone got a good example code with assembly, i would be very happy :D
 

shumifan50

Jan 16, 2014
579
Joined
Jan 16, 2014
Messages
579
Microchip provide excellent examples of using PWM in the examples folder of the XC8 C compiler (free).
You need to read a bit to understand a few concepts like period, duty cycle etc and most importantly what PWM means - not just that it stands for Pulse Width Modulation, but what it is. Try Wikipedia.

If you use the inbuilt module for PWM then it is on specific pin(s), as specified by the data sheet, or on some PICs the pins can be configured. You can however implement 'soft PWM' on any PIC output pin.

The frequency used for a specific PWM implementation will be determined by the target being driven and the result desired. You also have to set the duty cycle.

Have you got a scope as it will be a big benefit when playing with PWM?
 

shumifan50

Jan 16, 2014
579
Joined
Jan 16, 2014
Messages
579
The Microchip example attached
 

Attachments

  • Microchip-PWM-Example.zip
    23.8 KB · Views: 313

mollekake

Jun 30, 2014
37
Joined
Jun 30, 2014
Messages
37
Ok, i don't quite get it yet, and the example is in C.
So in a PWM, the T2CON is the prescaler right?
What does the PR2 represent?
I know the CCPR1L sets the cycle, half of PR2 for a 50%(right?)
What about CCP1CON, what does that represent?

I have a 4Mhz oscillator, so a prescaler(t2con) of 4 would give me 10khz right?
But i don't get why the PR2 then is 24, or why the CCP1CON is 28? At least according to the calculator.
Also, why is T2CON 5 and not 4?
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
PR2 tells you how many counts in the PWM period. If the CCP is clocked at 1MHz and you set PR2 to the max of 255, you will get PWM period of 1M / 256 = 3906 Hz.

You the set the duty cycle in CCPR1L to anywhere between 0 and 255 for 0 to 100% duty cycle with a resolution of about 0.4%.

You can add two more low bits to the duty cycle in CCP1CON<5:4>, giving you 10 bits in all and a resolution of 0.1%.

If you set the PR2 to 24, you will get 1M / 25 = 40KHz as the PWM frequency. And you will only be able to set the duty cycle from 0 to 24, which will still correspond to 0 to 100%, with a resolution of 4% In this case, you would probably really want to use the extra 2 low bits to get a resolution of 1%.

Note that the clock going into the prescalar is already divided by 4, so with a 4MHz run speed you would use no prescaler for the calculations above. With the prescaler set to 4, you will get 10KHz with PR2 set to 24 as you said above.


Hope this helps.

Bob
 

mollekake

Jun 30, 2014
37
Joined
Jun 30, 2014
Messages
37
Ok so i tried something, but the light will not fade. Got any ideas why?
Just trying out with a simple led for now. Here is what i have:

Code:
BANKSEL LATC
BSF LATC,3

BANKSEL T2CON
movlw b'00000100'
movwf T2CON

BANKSEL PR2
movlw d'99'
movwf PR2

BANKSEL CCP2CON
movlw b'00001100'
movwf CCP2CON

BANKSEL CCPR2L
movlw d'99'
movwf CCPR2L

Blarg
ADDLW -1
movwf CCPR2L
call Delay2
BTFSC CCPR2L,Z
GOTO Blarg
movlw d'99'
movwf CCPR2L
GOTO Blarg
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
You might need a BANKSEL before the move to CCPR2L, depending on what Delay2 does with bank selection. Other than that, I see no problems with the code.

Bob
 

mollekake

Jun 30, 2014
37
Joined
Jun 30, 2014
Messages
37
Didn't think about that, thanks! Although, it didn't make any diffrence :(
Is it possible to decrease CCPR2L registry instead of moving w?
Like this: DECF CCPR2L,F

If i do however set a value to w, move it to CCPR2L, it works, but i don't want to set it manual all the time.
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
Yes, you can do:

decf CCP1RL, f

To subtract one from the register.

I would suggest that you step through your program with the MPLAB simulator at this point to make sure it is doing what you expect it to do.

Bob
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
Whoops, I did not look at you code very well. The way you are testing for zero will not work. The Z bit is in the STATUS register, not in CCP2RL.

You can use:

Code:
     decfsz CCP2RL, f
     goto Blarg
     movlw .99
     movwf CCP2RL
     goto Blarg

Bob
 

mollekake

Jun 30, 2014
37
Joined
Jun 30, 2014
Messages
37
Thanks for all the replies! Really helps! Figured that part out while reading up on the instructions.
How can i prevent a incf overflow? Like make it not go over to 0 or a certain number, 99 in this case.
 

BobK

Jan 5, 2010
7,682
Joined
Jan 5, 2010
Messages
7,682
By subtracting 99 from it and checking status:

Code:
incf    CCP2RL, f
movlw .99
subwf CCP2RL, w
btfss  STATUS, Z
goto  not_hit_99
goto hit_99
 
Top