# PIC pwm calculation

Discussion in 'Microcontrollers, Programming and IoT' started by ami85t, Mar 30, 2014.

1. ### ami85t

71
0
Feb 19, 2014
Hi,
I’m trying to figure out how to calculate the PWM duty cycle and frequency using a PIC16f877.
The equation for the d.c. is:
PWM duty cycle = (CCPR1L:CCP1CON<5:4>) • TOSC • (TMR2 prescale value)

I want to create a 50% duty cycle wave. I have a crystal of 8 and 16 MHz.
The minimum value which is available for the (CCPR1L:CCP1CON<5:4>) which I got to is 17D7840 (HEX) which of course is much more than 3 HEX digits.
What am I missing here? Is my equation supposed to look like this:
50= X * (1/8M max) * 16max ?

Thanks, Amitai

2. ### jpanhalt

426
4
Nov 12, 2013
The equations work fine. The point you are missing is that the duty cycle is defined by Microchip in units of time:

If you want duty cycle as a fraction, then you need to divide the duty cycle time by the period. For duty cycle as a percentage, convert that fraction in the usual way.

John

3. ### ami85t

71
0
Feb 19, 2014
Thanks, I exactly figured it out.
I have changed the code a little and read a few things which I tried out but
I see that the capture module doesn't work for some reason.
I inserted the led section in the program for verifying that the loop in the code works for the different sections.
The led does turn on and the first transmitting part does it's job. but the led doesn't flicker - what means that
there's something wrong at the loop for checking the PIR2, CCP2IF.
Do the sections of the code for the PWM and capture seem correct? do I need to power on the timer1 only before the
capturing process and use the flags the way I did?

Thanks, Amitai

Code:
```LIST	P=PIC16F877

include	<P16f877.inc>
org		0x00

__CONFIG _LVP_OFF &_WDT_OFF &_PWRTE_OFF &_CP_OFF & _HS_OSC

reset:
nop
goto	start
org		0x20

start:
; configuration
;-----------------------------------

; used_ registers:
MUX_sel			EQU H'0021'  		; for not transmitting '000000000'
del1			EQU H'0030'  		; for delay
del2			EQU H'0031'  		; for delay
tro_transmit	EQU H'0050'  		; Frequency data register
chk_zero		EQU H'0055'  		; for not transmitting '000000000'
demo_send	 	EQU H'0056'  		; FF sent in beginning
led1			EQU H'0070'  		; for led delay

movlw		0x07				; pin RA5 is configured as a digital I/O

;UART/*/*/
banksel  	TXSTA
movlw    	0x24        		 ; master, transmit EN, sync mode, Transmit Shift Register empty
m[CODE]```
ovwf TXSTA ; Baud Rate = Fosc/(4(SPBRG+1)) , BRGH (baud rate) ignored in sync

banksel TRISC
bsf TRISC, 6
bsf TRISC, 7

banksel SPBRG
movlw 0x10 ; = d"16" which corresponds to 15Kbps with 8MHz clock
movwf SPBRG

banksel RCSTA
movlw 0x80 ; enable UART
movwf RCSTA

;PWM, timer2/*/*/
banksel TRISC
bcf TRISC, 2 ; make the CCP1 pin an output.
banksel T2CON

movlw 0x04
movwf T2CON ; no post/Prescaler (1:1) , TMR2 ON

banksel PR2 ; output frequency = 15000hz =
movlw 0x84
movwf PR2 ; 1 / [(PR2) + 1] • 4 • TOSC •(TMR2 prescale value)

banksel CCPR1L ;duty cycle =(CCPR1L:CCP1CON<5:4>) • TOSC • (TMR2 prescale value)
movlw 0b01000010
movwf CCPR1L
banksel CCP1CON
movlw 0b00111100
movwf CCP1CON

;capture, timer1 /*/*/
banksel TRISC
bcf TRISC, 1 ; make the CCP2 pin an output.

banksel T1CON
movlw 0x09 ; Timer1 Input Clock Prescale 1:1, en TMR1
movwf T1CON ; , int clk (fosc/4) , oscillator en
banksel CCP2CON
movlw 0x07
movwf CCP2CON ; Capture mode, every 16th rising edge
banksel PIE2
bcf PIE2, CCP2IE ; avoid false interrupts

;MUX select
banksel TRISD
bcf TRISD, 0
bcf TRISD, 1
bcf TRISD, 2

;LED general delay
bcf TRISD, 4
bcf TRISD, 5
banksel PORTD
bcf PORTD, 4
bcf PORTD, 5

; end configuration --------------------------------------

;************ MAIN PROGRAM ***************
;*****************************************

main:

;MUX init
movlw 0x07
movwf MUX_sel

;transmit check /*/*/*/*
CALL DELAY
movlw 0xFF
movwf demo_send
movf demo_send, w
CALL transmitting_data

main_loop:

Led_flicker:
movlw 0xFF
movwf led1
t2:
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
decfsz led1
goto t2

bcf PORTD,5
bsf PORTD,4

banksel led1
movlw 0xFF
movwf led1
t1:
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
decfsz led1
goto t1

bcf PORTD,4
bsf PORTD,5
;---end Led flicker

;capture frequency/*/*
banksel TMR1H
clrf TMR1H
clrf TMR1L
check_capture:
banksel PIR2
btfss PIR2, CCP2IF ; 1 = A TMR1 register capture occurred (must be cleared in software)
goto check_capture

;transmitting data
banksel CCPR2H ; transmit MSB
movf CCPR2H, w
banksel tro_transmit
movwf tro_transmit
CALL transmitting_data

banksel CCPR2L ; transmit LSB
movf CCPR2L, w
banksel tro_transmit
movwf tro_transmit
CALL transmitting_data

;MUX select/*/*/
movf MUX_sel,w
banksel PORTD
movwf PORTD
decfsz MUX_sel
goto main_loop
movlw 0x07
movwf MUX_sel

goto main_loop

;******** END MAIN LOOP ********************

transmitting_data:
banksel TXREG
movwf TXREG ; writing to TXREG clears TXIF
trans_wait2:
btfss PIR1, TXIF ; wait for the frame to be transmitted
goto trans_wait2
CALL DELAY
return

DELAY:
movlw 0xFF
movwf del1
movlw 0xFF
movwf del2

loopa:
decfsz del1, f
goto loopa
loopb:
decfsz del2, f
goto loopb
return

end
[/CODE]

Last edited: Mar 30, 2014