Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

clarification on using pwm module

Status
Not open for further replies.

spirosd

New Member
Hello,

I am doing some testing on using pwm with a 16f628a. Have read both the datasheet for the pic, the Mid-Range Ref Manual, and have tested a sample code using gpsim. I would like your help to clarify a couple of points

1) PWM operations can be controlled by either turning TMR2 on/off OR enabling/disabling PWM on the CCP module

2) While PWM is operational, no interrupts are fired. Polling (as per example on the Ref manual) can be done on the TMR2IF if needed (for example to change the duty cycle)

3) RB3, once configured as output, will generate the relevant output (once the PWM module is set up correctly - I am asking this as gpsim did not produce an output on RB3 - tested using polling of TMR2IF).

Thanks for your time
 
spirosd said:
Hello,
1) PWM operations can be controlled by either turning TMR2 on/off OR enabling/disabling PWM on the CCP module

I think your supposed to set the duty cycle to zero rather than turn off the PWM module. (could also be 50% or 100% depending on your hardware)

2) While PWM is operational, no interrupts are fired. Polling (as per example on the Ref manual) can be done on the TMR2IF if needed (for example to change the duty cycle)

Where did you read this. As far as I am aware, if timer2 interrupts are enabled then they will fire. As long as you set the Timer2 postscaler to 1:1 then interrupts should work fine. For Timer2 interrupts you need to set TMR2IE, PEIE & GIE.

3) RB3, once configured as output, will generate the relevant output (once the PWM module is set up correctly - I am asking this as gpsim did not produce an output on RB3 - tested using polling of TMR2IF).

Yes.

HTH

Mike.
 
Pommie said:
2) While PWM is operational, no interrupts are fired. Polling (as per example on the Ref manual) can be done on the TMR2IF if needed (for example to change the duty cycle)

Where did you read this. As far as I am aware, if timer2 interrupts are enabled then they will fire. As long as you set the Timer2 postscaler to 1:1 then interrupts should work fine. For Timer2 interrupts you need to set TMR2IE, PEIE & GIE.

Hmmm :roll: ... I have enabled TMR2IE on PIE1 (bit 1) and I am using a 1:1 post and pre scalars
Code:
movlw	b'0000010'
movwf	PIE1
and was trying to check for the interrupt with
Code:
btfsc PIR1,TMR2IF
goto TMR2_ISR

which works fine for processing interrupt on change(portb<4:7>) and tmr0. When debugging through gpsim I can step through those, but not for tmr2. Let me go back and re-check my code.

Many thanks for your reply, it was very helpful.
 
spirosd said:
Hmmm :roll: ... I have enabled TMR2IE on PIE1 (bit 1) and I am using a 1:1 post and pre scalars
Code:
movlw	b'0000010'
movwf	PIE1

You also need to set PEIE to enable peripheral interrupts. PEIE is bit 6 of INTCON.

Mike.
 
Pommie said:
You also need to set PEIE to enable peripheral interrupts. PEIE is bit 6 of INTCON.
Code:
movlw b'11101000'
movwf INTCON

Yeap doing that, Global and Peripherals ON, Timer0 ON (using it for an internal 10ms clock tick) and PortB interrupt on change ON.

Have not had a chance yesterday to look at this, hope to do so today. Thank you for your help Mike.

Spiros
 
Ok have kept the code to a minimum, and I still do not get interrupts from tmr2. If I poll the TMR2IF flag, I get the desired result (flashing leds).

Confused :oops: I would greatly appreciate a fresh pair of eyes on this asm code:

(using 16f628 as gpsim does not support 16f628a ... from what I looked at this should not pose problems ... perhaps I am wrong!)

Thank you for your time ...

Code:
list 		p=16F628
include		"p16F628.inc"
errorlevel -302

; fuses cnfiguration
; BrownOut OFF, Code Protection OFF, Data Protection (EEPROM) OFF
; PowerOn Timer ON, Watchdog OFF, Low Voltage Programming OFF, MCLRE OFF (MCLRE tied inernally to VDD)
; Internal 4MHz oscillator ON (no output)
__config _BODEN_OFF & _CP_OFF & _DATA_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT

;-------------------------
; variable declarations
cblock 0x20 ; start of general purpose registers
endc

cblock 0x70 ; at Bank0 and is accessible from 0xF0, 0x170 and 0x1F0
	w_temp
	status_temp
endc

;--------------------------

org 0x0000
goto Main

org 0x0004 
goto ISR

Main
	call INIT

loop
	;btfss	PIR1,TMR2IF	; poll TMR2IF
	;goto	loop
	;bcf	PIR1,TMR2IF ; clear the flag - lather,rinse,repeat
	;comf 	PORTA
	goto	loop

;------------ interrupt routine
ISR
	; save STATUS and W register before processing interrupt
	movwf	w_temp
	swapf	STATUS,w
	movwf	status_temp

	btfsc	PIR1,TMR2IF
	goto	PWM_INT
	goto	reset_after_isr

PWM_INT
	comf	PORTA
	bcf		PIR1,TMR2IF
	goto	reset_after_isr

reset_after_isr
; restore the working and status register
	movf	status_temp,w
	movwf	STATUS
	swapf	w_temp,f
	swapf	w_temp,w
	retfie

;------------ initialisation
INIT
	; TMR2 set up for pwm, using post and pre scalars of 1:1
	; (thus must enable peripheral interrupts and specifically TMR2IE)
    ; using the calculation defined in the datasheet
	; PWM_Period -> 1/req_Freq = (PR2+1) * 4 * (1/TOSC)*1
	; aiming for a 20KHz signal @ 4MHz (internal clock) with a tmr2 prescalar of 1 thus:
	; 1/20 = (PR2+1) * 4 * (1/4) * 1
	; 50ms = (PR2+1) * 4 * 0.25ms * 1
	; 50ms = (PR2+1) -> PR2 = 49
	; 8-bit resolution ok
	; 25% duty cycle CCPR1L = 12
	; 50% duty cycle CCPR1L = 24
	; 75% duty cycle CCPR1L = 36

	; bank 1 stuff
	bsf	STATUS,RP0
	; setting trisb (bit3 must be output as it is multiplexed for use by ccp/pwm module)
	clrf	TRISB
	clrf	TRISA
	clrf	OPTION_REG 
	; pwm period
	movlw	.49
	movwf	PR2

	;back to bank0
	bcf	STATUS,RP0
	; disable comparators
	movlw	0x07
	movwf	CMCON

	clrf	TMR2
	clrf	T2CON ; pre and postscalar 1:1 TM2ON = 0 (OFF)
	clrf	PIR1  ; all peripheral interrupts cleared
	clrf	PORTB
	;pwm duty cycle is 25%
    movlw	.12
	movwf	CCPR1L
	; enable pwm on ccp module
	movlw	b'00001100'
	movwf	CCP1CON
	; enable tmr2 interrupt and disable other peripheral interrupts
	movlw	b'00000110'
	movwf	PIE1
	; enable global and peripheral interrupts
	movlw	b'11000000'
	movwf	INTCON
	; enable tmr2
	bsf 	T2CON,TMR2ON

	return

end
 
PIE1 is in bank 1. I just copied your code into MPLAB and inserted the banking instructions and the timer2 interrupt fired OK.

Code:
        ; enable tmr2 interrupt and disable other peripheral interrupts 
        bsf	STATUS,RP0 ;    <----------------------
        movlw   b'00000110' 
        movwf   PIE1 
        bcf	STATUS,RP0;    <----------------------

HTH

Mike.
 
Pommie said:
PIE1 is in bank 1. I just copied your code into MPLAB and inserted the banking instructions and the timer2 interrupt fired OK.

Code:
        ; enable tmr2 interrupt and disable other peripheral interrupts 
        bsf	STATUS,RP0 ;    <----------------------
        movlw   b'00000110' 
        movwf   PIE1 
        bcf	STATUS,RP0;    <----------------------

HTH

Mike.

That program created by Jim Henson comes to mind! I can't believe that I missed that ...

Thanks for your help Mike
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top