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.

cannot get PWM output?

Status
Not open for further replies.

rashidme

Member
i am using 18f4520, Fosc=4Mhz and the led is connected to RB3. The led is working fine, i have checke that. I am not getting pwm output.
here is my code:

Code:
;********************************************************************
;* FileName:        pwm.asm
;* Processor:       PIC18F4520
;* Compiler:        MPLAB C18 v.3.06 
;*
;* (description)
;* Using pwm to control the brightness of a LED
;*
;* 4khz pwm frequency, Fosc = 4Mhz
;* 
;* PWM period = 1 / 4khz = 0.25 msec
;*
;* 0.25 ms = [(PR2) + 1] * 4 * 1 / 4Mhz * 1
;* 0.25 ms = [(PR2) + 1] 1 / 1Mhz
;* 250 = PR2 + 1
;* PR2 = 250 or 0xFA (1111 1010)
;*
;*PWM RESOLUTION: pwm resolution = (log (Fosc/Fpwm)) / (log(2)) bits
;*         = log (4Mhz/4Khz) / log(2) 
;*        = 9
;*that means 0 <= (CCPRXL:CCPXCON<5:4>) <= 511
;*
;*PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>)* Tosc * (TMR2 Prescale Value)
;*For 50% duty cycle: PWM period / 2 = 0.125 msec
;*     0.125 msec = (CCPRXL:CCPXCON<5:4>) * 1 / Fosc * 1
;*     (CCPRXL:CCPXCON<5:4>) = 500 (0111 1101 00)
;*     CCPRXL = 0x7D
;*     CCPXCON<5:4> = 00
;*      
;*
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

LIST P=18F4520    ;directive to define processor
#include <P18F4520.INC>
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Configuration bits

CONFIG OSC = EC      ;external 4MHz oscillator
CONFIG WDT = OFF   ;watch dog timer off
CONFIG LVP = OFF
CONFIG BOREN = OFF
CCP2MX = PORTB      ;use RB3 for pwm output

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Variables 

pr2_val        EQU  0xFA      ;needed for 4khz pwm frequency
ccprxl_val    EQU  0x7D      ;needed for duty cycle
ccp1con_val EQU  0x0C     ;includes 2 lsb's for duty cycle

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Reset Vector

ORG 0x0000
goto Main     ;goto start of main code

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Main starts here

Main:
call INIT_PORT
call INIT_TMR2

pwm_settings: 

;sets our duty cycle
movlw ccp1con_val 
movwf CCP2CON  
movlw ccprxl_val 
movwf CCPR2L 

here: bra here

INIT_PORT:
clrf PORTB
movlw 0x0F
movwf ADCON1
movlw 0x00
movwf TRISB  ;make portb output
return

INIT_TMR2:
bsf PIE1,1   ;timer2 interrupt enables
bcf T2CON,1  ;1:1 prescalar
bcf T2CON,0  ;
movlw pr2_val
movwf PR2
bsf T2CON,2  ;start timer2
bra pwm_settings

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;End of program
END

Any help would be appreciated.
 
Check in the datasheet all registers related with PWM generation and go through them bit by bit.

Did you enable the commited pin as OUT?
 
Yes i did enable the commited pin as out.
Code:
INIT_PORT:
clrf PORTB
movlw 0x0F
movwf ADCON1
movlw 0x00
movwf TRISB  ;make portb output
return

I even tried the logic analyzer in MpLab but no luck!
any one please!!!
 
Last edited:
HAVE YOU CHECKED ALL THE REGISTERS INVOLVED bit by bit?
 
Yes I have checked all the registers. Do i have to worry about any interrupts while setting up pwm? I think the problem is where TMR2 values gets compared to PR2. It clears the TMR2, as they say in the datasheet, but i guess it does not Set the CCPx pin. Is there anything wrong with my calculations, that i cannot see but may be you guys can see it?

Thank you.
 
You are supposed to clear the TMR2IF flag in PIR1 to be able to continue the PWM Cycle. Also i see that you start Timer2 before doing the PWM Duty Cycle settings. It would e better if you turned it on in the pwm_settings routine and then kept checking for it. After it goes high. Clear it and and then again turn it on.
 
No, you don't clear the interrupt flag. PWM is self-maintaining once it is setup. I haven't done PWM on an 18F, so I can't test the code, but I've done it recently with a 16F886 and a 12F683 without trouble by following the steps in the datasheet exactly.
 
I stand corrected about the Clearing of the TMR2ON Flag. I use C so thats why.

i am using 18f4520, Fosc=4Mhz and the led is connected to RB3. The led is working fine, i have checke that. I am not getting pwm output.
here is my code:

Code:
;********************************************************************
;* FileName:        pwm.asm
;* Processor:       PIC18F4520
;* Compiler:        MPLAB C18 v.3.06     [COLOR="Red"](I see assembly being used)[/COLOR]
;*
;* (description)
;* Using pwm to control the brightness of a LED
;*
;* 4khz pwm frequency, Fosc = 4Mhz
;* 
;* PWM period = 1 / 4khz = 0.25 msec
;*
;* 0.25 ms = [(PR2) + 1] * 4 * 1 / 4Mhz * 1
;* 0.25 ms = [(PR2) + 1] 1 / 1Mhz
;* 250 = PR2 + 1
;* PR2 = 250 or 0xFA (1111 1010)
;*
;*PWM RESOLUTION: pwm resolution = (log (Fosc/Fpwm)) / (log(2)) bits
;*         = log (4Mhz/4Khz) / log(2) 
;*        = 9
;*that means 0 <= (CCPRXL:CCPXCON<5:4>) <= 511
;*
;*PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>)* Tosc * (TMR2 Prescale Value)
;*For 50% duty cycle: PWM period / 2 = 0.125 msec
;*     0.125 msec = (CCPRXL:CCPXCON<5:4>) * 1 / Fosc * 1
;*     (CCPRXL:CCPXCON<5:4>) = 500 (0111 1101 00)
;*     CCPRXL = 0x7D
;*     CCPXCON<5:4> = 00
;*      
;*
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

LIST P=18F4520    ;directive to define processor
#include <P18F4520.INC>
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Configuration bits

CONFIG OSC = EC      ;external 4MHz oscillator
CONFIG WDT = OFF   ;watch dog timer off
CONFIG LVP = OFF
CONFIG BOREN = OFF
CONFIG CCP2MX = PORTBE       ;use RB3 for pwm output [COLOR="Red"](Correction)[/COLOR]

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Variables 

pr2_val        EQU  0xFA      ;needed for 4khz pwm frequency
ccprxl_val    EQU  0x7D      ;needed for duty cycle
ccp1con_val EQU  0x0C     ;includes 2 lsb's for duty cycle

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Reset Vector

ORG 0x0000
goto Main     ;goto start of main code

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Main starts here

Main:
call INIT_PORT
call INIT_TMR2

pwm_settings: 

;sets our duty cycle
movlw ccp1con_val 
movwf CCP2CON  
movlw ccprxl_val 
movwf CCPR2L 

here: bra here

INIT_PORT:
clrf PORTB
movlw 0x0F
movwf ADCON1
movlw 0x00
movwf TRISB  ;make portb output
return

INIT_TMR2:
bsf PIE1,1   ; timer2 interrupt enables   ([COLOR="Red"]It does enable the timer 2 interrupt 
                     but for interrupts to occur, the Global and Peripheral bit in INTCON need to be  
                      enabled, secondly you need not turn on the timer interrupt since you are 
                       using it for pwm.Also no interrupt  vector has been defined. And there is no 
                       need for this)[/COLOR]
bcf T2CON,1  ;1:1 prescalar
bcf T2CON,0  ;
movlw pr2_val
movwf PR2
bsf T2CON,2  ;start timer2
bra pwm_settings

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;End of program
END

Any help would be appreciated.

The problem with your code is that the configuration bit CCP2MUX is not being set to RB3. This will work.:)


Download the Configuration bits addendum by MC to help you with setting them correctly.

https://www.electro-tech-online.com/custompdfs/2010/03/C18_Config_Settings_51537F.pdf
 
Give this a shot;
Code:
;********************************************************************
;* FileName:        pwm.asm
;* Processor:       PIC18F4520
;* Compiler:        MPASM 
;*
;* (description)
;* Using pwm to control the brightness of a LED
;*
;* 4khz pwm frequency, Fosc = 4Mhz
;* 
;* PWM period = 1 / 4khz = 0.25 msec
;*
;* 0.25 ms = [(PR2) + 1] * 4 * 1 / 4Mhz * 1
;* 0.25 ms = [(PR2) + 1] 1 / 1Mhz
;* 250 = PR2 + 1
;* PR2 = 250 or 0xFA (1111 1010)
;*
;*PWM RESOLUTION: pwm resolution = (log (Fosc/Fpwm)) / (log(2)) bits
;*         = log (4Mhz/4Khz) / log(2) 
;*        = 9
;*that means 0 <= (CCPRXL:CCPXCON<5:4>) <= 511
;*
;*PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>)* Tosc * (TMR2 Prescale Value)
;*For 50% duty cycle: PWM period / 2 = 0.125 msec
;*     0.125 msec = (CCPRXL:CCPXCON<5:4>) * 1 / Fosc * 1
;*     (CCPRXL:CCPXCON<5:4>) = 500 (0111 1101 00)
;*     CCPRXL = 0x7D
;*     CCPXCON<5:4> = 00
;*      
;*
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

  LIST P=18F4520    ;directive to define processor
  #include <P18F4520.INC>
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Configuration bits

  CONFIG OSC = EC        ;external 4MHz oscillator
  CONFIG WDT = OFF       ;watch dog timer off
  CONFIG LVP = OFF
  CONFIG BOREN = OFF
  CONFIG CCP2MX = PORTBE ;use RB3 for pwm output

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Variables 

pr2_val     EQU  0xFA    ;needed for 4khz pwm frequency
ccprxl_val  EQU  0x7D    ;needed for duty cycle
ccp1con_val EQU  0x0C    ;includes 2 lsb's for duty cycle
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Reset Vector

  ORG 0x0000
  goto Main     ;goto start of main code

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Main starts here

Main
  call INIT_PORT
  call INIT_TMR2

pwm_settings: ;sets our duty cycle
  movlw ccp1con_val 
  movwf CCP2CON  
  movlw ccprxl_val 
  movwf CCPR2L 

here 
  bra here       ;loop forever

INIT_PORT
  clrf  PORTB
  movlw 0x0F
  movwf ADCON1
  clrf  TRISB    ;make portb output
  return

INIT_TMR2
  clrf  T2CON    ;1:1 prescaler
  movlw pr2_val
  movwf PR2
  bsf   T2CON,2  ;start timer2
  return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;End of program
  END
 
Well the problem was that i was using PORTB instead of PORTBE. As pointed out by Syed. It works now. Thanks everyone.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top