Connect with us

Understanding PWM with PIC (assembly)

Discussion in 'Microcontrollers, Programming and IoT' started by mollekake, Jul 20, 2014.

Scroll to continue with content
  1. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    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
     
  2. shumifan50

    shumifan50

    548
    56
    Jan 16, 2014
    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?
     
    KrisBlueNZ likes this.
  3. shumifan50

    shumifan50

    548
    56
    Jan 16, 2014
    The Microchip example attached
     

    Attached Files:

  4. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    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?
     
  5. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    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
     
  6. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    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
     
  7. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    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
     
  8. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    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.
     
  9. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    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
     
  10. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    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
     
  11. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    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.
     
  12. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    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
    
     
  13. mollekake

    mollekake

    37
    0
    Jun 30, 2014
    Thanks Bob! :D Finally got it working and understanding it :p
     
  14. BobK

    BobK

    7,673
    1,684
    Jan 5, 2010
    Great! Glad to be of help.

    Bob
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-