PWM with PIC16F84A?

Discussion in 'The Projects Forum' started by detroit, Mar 14, 2014.

  1. detroit

    Thread Starter New Member

    Mar 13, 2014
    5
    0
    I'm new to this forum so hello to everyone.

    How I got here:
    I am working on PIC16F84A to generate a PWM signal where gradually increases and decreases the brightens of an LED in assembly ( maybe C if too hard) depending on 3 DIP switch input

    1. I am having a hard time grasping the idea around timer, prescaler and interrupt. Reading I think I have to implement this in the code to get the desired result. Not sure how...

    2. Do I have to use an outside oscillator or use the RC method only?

    3. I have created where I can use the switch to turn on and of.. ( that is as far I have gotten)

    I would like some help in pointing me in the right direction.

    Thank you for your help in advance
     
  2. mcgyvr

    AAC Fanatic!

    Oct 15, 2009
    4,771
    971
    There are NUMEROUS tutorials on the internet to generate a PWM signal with a PIC..
    google "PIC16F84A PWM" and have fun :)
     
  3. MaxHeadRoom

    Expert

    Jul 18, 2013
    10,555
    2,375
  4. detroit

    Thread Starter New Member

    Mar 13, 2014
    5
    0
    Thanks for the quick reply mcgyvr,

    I have probably read 99 % of them, and yet did not come across any that clarify how the prescaler is implemented with timer to control the duty cycle ( 0%, 50% ...)

    If you can suggest a good site or maybe take some of your time to explain it it would be greatly appreciated.

    thanks
     
  5. BobTPH

    Active Member

    Jun 5, 2013
    784
    114
    The timer on the PIC16F84A does not have a controllable duty cycle. Use a PIC with a PWM module, such as the 16F628.

    If you must use that PIC, you will have to control the on and off time separately by software, using either the timer or a program delay loop.


    Bob
     
  6. detroit

    Thread Starter New Member

    Mar 13, 2014
    5
    0
    Thanks Bob for your time,

    I have to use PIC16F84A, and from the reading that I have done i have concluded that I need both the timer and delay implemented in the code.
    Can you please break each of them down.
    I have done normal delay where its on and off.
    Timer part I am straight lost....

    Thanks
     
  7. BobTPH

    Active Member

    Jun 5, 2013
    784
    114
    Example for PWM with 1ms period.

    1. Calculate the on time base on period and duty cycle:

    on_time = 1ms * duty;

    2. Set a pin to high.
    3. Wait for the on time
    4. Set the pin to low
    5. Wait for the off_time = period - on_time
    6. goto 2;

    Bob
     
  8. detroit

    Thread Starter New Member

    Mar 13, 2014
    5
    0
    Thanks again, but I still am confused (do apologize just trying to grasp the logic)

    So I would like to read 3 switches each one has a duty cycle.
    So how do I implement the PWM method in the below code that I have done so far.
    PLEASE Keep in mind I am at work therefore the code is close to what I have done at home.

    Code ( (Unknown Language)):
    1.  
    2.     ;include the header file
    3.  
    4.     __CONFIG  0X3FF2       ; i think I am missing something here ????    
    5.  
    6.     ORG        0X0000
    7.     GOTO    START        
    8.  
    9.     ORG        0X0004
    10.     RETFIE
    11.  
    12. START
    13.  
    14.     BSF        STATUS,RP0    ;Shift to bank 1
    15.     MOVLW    0XF0
    16.     MOVWF    TRISB        ;Set RB0,RB1,RB2,RB3 as outputs
    17.     BCF        STATUS,RP0    ;Shift to bank 0
    18.  
    19.  
    20. LOOP
    21.  
    22.     CLRF    TEMPB
    23.  
    24.     BTFSC    PORTB,7        ;Check Switch 1
    25.     CALL    S1        ;Call switch1 subroutine if switch is on
    26.     BTFSC    PORTB,6        ;Check Switch 2
    27.     CALL    S2        ;Call switch1 subroutine if switch is on
    28.     BTFSC    PORTB,5        ;Check Switch 3
    29.     CALL    S3        ;Call switch1 subroutine if switch is on
    30.  
    31.     MOVF    TEMPB,W        ; to the PORTA and PORTB registers to display
    32.     MOVWF    PORTB        ; on the LEDs
    33.  
    34.     GOTO    LOOP    ;Return to top of loop
    35.  
    36. S1
    37. ; Turns on LED 1-4 at(would like @ 25% duty cycle)
    38. ; Not sure how to implement the logic in here
    39.     MOVLW    0X0F        ;0000 1111 on PORTA
    40.     IORWF    TEMPB,F
    41.     RETURN
    42.  
    43. S2
    44. ; Turns on LED 1-4 (would like @ 50% duty cycle)
    45. ; Not sure how to implement the logic in here
    46.     MOVLW    0X0F        ;0000 1111 on PORTA
    47.     IORWF    TEMPB,F
    48.     RETURN
    49.  
    50.  
    51. S3
    52. ; Turns on LED 1-4 (would like @ 100% duty cycle)
    53. ; Not sure how to implement the logic in here
    54.     MOVLW    0X0F        ;0000 1111 on PORTA
    55.     IORWF    TEMPB,F
    56.     RETURN
    57.  
    58. ; And havent gone further for the reverse process,
    59. ;as I would like to solve the above first
    60.  
    61.     END
    62.  
    Again thanks for your help is greatly appreciated...
     
  9. Dodgydave

    Distinguished Member

    Jun 22, 2012
    4,998
    745
    there is a programme here for pwm on pic16f84
     
  10. detroit

    Thread Starter New Member

    Mar 13, 2014
    5
    0
    So I would like to use the delay method, however I do not know how to use the timer as a counter.

    I need to clear timer, for me to use it as a counter.
    clear watch time dog.
    and select a prescaler.

    can someone provide a sample code in assembly how this would be done, no it is not making me lazy.
    Just that I know I will understand it better.

    Thanks
     
  11. Ian Rogers

    Member

    Dec 12, 2012
    158
    29
    Do you not want to use an interrupt on the timer? It makes PWM generation so much easier..

    If you require two PWM outputs.

    Set up two compare variables pwm1 and pwm2.
    Set the timer on... and switch both outputs on.
    Compare pwm1 against timer, if timer is bigger switch off the output pin.
    Compare pwm2 against timer, if timer is bigger switch off the output pin.
    If the timer spills over set both outputs high again...

    If you put all the above in an interrupt all you need to do is adjust the two variables pwm1 and pwm2...
     
  12. Ian Rogers

    Member

    Dec 12, 2012
    158
    29
    Look at this code... Its yours with a 4 pwm outputs at 5 bits precision... Only 200hz, but enough for LED's..

    Code ( (Unknown Language)):
    1.  
    2. ;include the header file
    3.  
    4. pwm1    equ 20h ; pwm1 variable
    5. pwm2    equ 21h ; pwm2 variable
    6. pwm3    equ 22h ; pwm3 variable
    7. pwm4    equ 23h ; pwm4 variable
    8. Period  equ 24h ; pwm period
    9. Pcount  equ 25h ; period counter
    10. Wsav    equ 26h ; save w reg
    11. Ssav    equ 27h ; save status reg
    12. TEMPB   equ 28h
    13.  
    14.     list     p=16f84a
    15.     #include p16f84a.inc
    16.  
    17.     __CONFIG  0X3FF2       ; i think I am missing something here ????    
    18.    
    19.  
    20.     ORG 0X0000
    21.     GOTO    START        
    22.  
    23.     ORG 0X0004
    24.     goto    ISR     ; goto ISR routine
    25.  
    26. START
    27.     BSF STATUS,RP0  ;Shift to bank 1
    28.     movlw   b'00001000' ; fast as possible
    29.     movwf   OPTION_REG
    30.     MOVLW   0XF0
    31.     MOVWF   TRISA       ;Set RA0,RA1,RA2,RA3 as outputs
    32.     BCF STATUS,RP0  ;Shift to bank 0
    33.     movlw   b'10100000' ; timer on
    34.     movwf   INTCON
    35.     movlw   032h        ; set period
    36.     movwf   Period      ; pwm cannot go past this
    37.     movlw   0BfH       ; This defines the speed of the interrupt...
    38.     movwf   TMR0
    39.     movlw   16h
    40.     movwf   pwm1
    41.     movwf   pwm2
    42.     movwf   pwm3   
    43.     movwf   pwm4
    44.  
    45. LOOP
    46.  
    47.     BTFSC   PORTB,7     ;Check Switch 1
    48.     CALL    S1      ;Call switch1 subroutine if switch is on
    49.     BTFSC   PORTB,6     ;Check Switch 2
    50.     CALL    S2      ;Call switch1 subroutine if switch is on
    51.     BTFSC   PORTB,5     ;Check Switch 3
    52.     CALL    S3      ;Call switch1 subroutine if switch is on
    53.  
    54.     GOTO    LOOP        ;Return to top of loop
    55.  
    56. S1
    57. ; Turns on LED 1-4 at(would like @ 25% duty cycle)
    58. ; Not sure how to implement the logic in here
    59.     movlw   8h
    60.     movwf   pwm1
    61.     movwf   pwm2
    62.     movwf   pwm3   
    63.     movwf   pwm4
    64.     RETURN
    65.  
    66. S2
    67. ; Turns on LED 1-4 (would like @ 50% duty cycle)
    68. ; Not sure how to implement the logic in here
    69.     movlw   16h
    70.     movwf   pwm1
    71.     movwf   pwm2
    72.     movwf   pwm3   
    73.     movwf   pwm4
    74.     RETURN
    75.  
    76.  
    77. S3
    78. ; Turns on LED 1-4 (would like @ 100% duty cycle)
    79. ; Not sure how to implement the logic in here
    80.     movlw   32h
    81.     movwf   pwm1
    82.     movwf   pwm2
    83.     movwf   pwm3   
    84.     movwf   pwm4
    85.     RETURN
    86.  
    87. ; And havent gone further for the reverse process,
    88. ;as I would like to solve the above first
    89.  
    90. ISR
    91.     movwf   Wsav
    92.     movf    STATUS,w
    93.     movwf   Ssav        ; save registers
    94.     incf    Pcount,f    ; preriod timer
    95.    
    96.     movf    pwm1,w      ; Check pwm 1
    97.     subwf   Pcount,w   
    98.     btfsc   STATUS,C
    99.     bcf PORTA,0
    100.  
    101.     movf    pwm2,w      ; check pwm 2
    102.     subwf   Pcount,w
    103.     btfsc   STATUS,C
    104.     bcf PORTA,1
    105.  
    106.     movf    pwm3,w      ; check pwm 3
    107.     subwf   Pcount,w   
    108.     btfsc   STATUS,C
    109.     bcf PORTA,2
    110.  
    111.     movf    pwm4,w      ; check pwm 4
    112.     subwf   Pcount,w   
    113.     btfsc   STATUS,C
    114.     bcf PORTA,3
    115.  
    116.     movf    Period,w    ; check period
    117.     subwf   Pcount,w
    118.     btfss   STATUS,C
    119.     goto    noclear
    120.     movlw   0fh
    121.     movwf   PORTA
    122.     clrf    Pcount
    123.  
    124. noclear:
    125.     bcf INTCON,T0IF
    126.     movlw   0BfH
    127.     movwf   TMR0
    128.    
    129.     movf    Ssav,w
    130.     movwf   STATUS
    131.     swapf   Wsav,w
    132.     retfie
    133.  
    134.     END
    135.  
    136.  
    It uses interrupts so I hope you get the idea...
     
Loading...