PIC12F683 Variable PWM duty cycle

Thread Starter

simo_x

Joined Dec 23, 2010
200
Hi all,

I am programmig a dimmer for a 12V lamp with a PIC12F683 with duty cycle controlled by 2 button switch connected as PULL UP to GP5 (to decrease the duty cycle) & GP4 (to increase it).

The PWM period is 312.5Hz, Internal clock oscillator is 4Mhz so Tosc is 0.25us

PWM Period = [(PR2 + 1) ] · 4 · Tosc · TMR2Prescaler

Taking a TMR2 prescaler of 16

0.0032s = [(x + 1) ] · 16u
PR2 = 0xC7
T2CON = 0x03

I started writing the program, which has to be written in Assembly language, but I have a problem.
The register CCPR1L can't be changed during the program (has I know) so I use a general purpose register which I call dcycle.
Normally, I just want to test if GP4 or GP5 are to logical 0 and than control dcycle and than store the variable in CCPR1L, but, if this last register cannot be changed, is obvious that maybe my idea will not works.. Or I am wrong?

However, I my program which I am simulating through Proteus which seems to be a good PIC simulator (it always worked later with real PIC simulation)
program works until the register settings, than PWM doesn't work no more..
I post the code where I marked the line until the program works.
Rich (BB code):
INCLUDE P12F683.INC
LIST p = 12F683

__CONFIG _CP_OFF&_CPD_OFF&_BOD_ON&_PWRTE_ON&_WDT_OFF&_HS_OSC

CBLOCK    0x20
    dcycle                                ;variable duty cycle register
ENDC

;            configuration settings

            org    0x0000

            bsf        STATUS,    RP0        ; step to
            bcf        STATUS,    RP1        ; bank 1
    
            clrf        OPTION_REG        

            movlw        0x30                ;enable pull up interrupt
            movwf        IOC                ;for GP4 & GP5

            movlw        0xc7                ;configure PR2
            movwf        PR2                

            clrf        ANSEL                ;set all pin as Digital Inputs

            movlw        0x3b                ;set GP4 as input
            movwf        TRISIO                ;and GP2/CCP1 as output

            bcf        STATUS, RP0            ;step to bank 0

            movlw        0x07
            movwf        CMCON0            

            movlw        0x03                ;set T2CON with prescaler 1:16
            movwf        T2CON                ;and turn on T2
            
            movlw        0x3c
            movwf        CCP1CON

            

start:            
            movwf    dcycle
            movwf    CCPR1L


             goto    $
            end
            ;program works just until here

main:
            movwf    CCPR1L
        
            btfss    GPIO,    4                ;test if GP4 is 0
            incf    dcycle, 1                ;if so increment dcycle

            
            btfss    GPIO,    5                ;test if GP5 is 0
            decf    dcycle,    1                ;if so decrement dcycle

            movf    dcycle,    W                ;move dcycle to W
            goto    start                    
            end
I am thinking the way I am structuring the program is not correct..
How can I solve this problem? It's the first time I use PWM with PIC..

Thank you for your help
Regards,
Simo
 
Last edited:

ding_nz

Joined May 8, 2011
1
I have looked over some of my old code for PWM output on the PIC - Mine was a PIC 16F73

I was able to write to the CCPR1L register to set the duty cycle

I think that the problem you have is in the in the 2 lines after start:

You have :

Rich (BB code):
start:            
            movwf    dcycle
            movwf    CCPR1L
When it should be:

Rich (BB code):
start:            
            movfw    dcycle   ; Put duty cycle value into W register
            movwf    CCPR1L  ; Move W register into CCPR1L
You are not moving the value of dcycle into the working register other than that you don't appear to be doing any thing wrong for the PWM module not to work

I did notice the following

Also you enabling the interupt on change function not the weak pull ups as intended?

What oscillator do you plan on using as the GPIO's you have chosen are shared with the oscillator pins. In order to use them as inputs you need to change the _HS_OSC in you configuration word to _INTOSCIO or select 2 different inputs to use.

I simulated the code with your configuration word then changed the oscillator configuration and found the following:

With the _HS_OSC configuration the inputs were ignored so the value of dcycle was decremented then incremented for a net change of 0 - dcycle stayed the same

With the _INTOSCIO configuration the inputs responded and dcycle ws controllable

Hope that this helps I know that its alot of information but it should help get you on the right track

Dan
 

Thread Starter

simo_x

Joined Dec 23, 2010
200
Hi Dan, I read your response. Thank You very much for your interest ;)

I will try later to change the details from you suggested about oscillator..
I will update the post.

;)
See you later
 

Thread Starter

simo_x

Joined Dec 23, 2010
200
Hi Dan, it doesn't work. I changed to HS_OSC to _INTOSC, tried with _INTOSCIO, but nothing.. Also the MCLEAR is disabled...

I can't change the pins because the circuit requires that pinout.
The duty cycle control pins are set to enable interrupt on change, not to wake up the device..

Maybe it's because I need to work just with interrupts.. I am trying.. Did you control the duty cycle between interrupts or during normal execution of the program?

Regards,
Simo
 

Markd77

Joined Sep 7, 2009
2,806
If you want to use interrupts a good place to start is the assembler template for your PIC which should be found somewhere like:
c:\program files\microchip\MPASM suite\template\code
 

Thread Starter

simo_x

Joined Dec 23, 2010
200
Hi Markd77, I took a look to the file, thank you I didn' t know the example, but interrupt vector was not a secret yet ;)
In addition to the previous code, I am implementing this section
Rich (BB code):
            ;at starting
            org    0x000
            goto    settings
            org    0x004
            goto    INT_ON_CHANGE


;after configuration & goto $

INT_ON_CHANGE:
            bsf        INTCON,    0
            movf    CCPR1L,    W

            btfss    GPIO,    4
            call    inc

            btfss    GPIO,    5
            call    dec

            retfie

inc
            addlw    0x64
            movwf    CCPR1L
            bcf        INTCON,    0
            return

dec
            sublw    0x64
            movwf    CCPR1L
            bcf        INTCON,    0
            return
Which works.. I can increase or decrease the duty cycle, 0x64 = 100 is the interval test value, and I'll have to check for do not overflow 100% or 0% later... Now it's half past two in the morning here and I need to rest a little, to be spry again tomorrow morning :)

In simulation, the program seems to be quiet slow respect other PIC programs.. Should be the PWM simulation that over run the CPU (considering I run it in VBox)..

Maybe there is another way to improve the program section?

Thank you
Regards,
Simon
 
Last edited:
Top