Setting up Timer Module


Closed Thread
Results 1 to 13 of 13

Hybrid View

  1. #1
    Join Date
    Dec 2010
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Reynolds Electronics was nice in breaking it down but it won't give me a low enough frequency with the lowest value being 3.9kHz with a 4MHz clock - I need at least 325Hz. I don't really want to change the clock frequency since it affects the speed of my main program. I have posted my code below. It turns an LED on for 1 second and then off for one second while continually sending 3.9kH to a pin. Everyone helps is very much appreciated.

    'device PIC12F683

    DEFINE LOADER_USED 1'Setup for boot-loader programming
    OSCCON = %01100101 ' 01100101 - 4MHZ system clock
    TRISIO.2 = 0 ' GPIO.2 (GPIO.2 = Output)
    PR2 = 254 '(Max Value = 255 Set PWM Period for approximately 3.9KHz
    CCPR1L = 127 ' Set PWM Duty-Cycle to 50%
    CCP1CON = %00001100 ' Select PWM Mode
    T2CON = %00000100 ' Timer2 = ON + 1:1 prescale
    TRISIO.1 = 0


    LED_HIGH VAR BYTE
    LED_LOW VAR BYTE

    BEGIN:
    FOR LED_HIGH = 0 TO 10 'Turn ON LED for 1 Second
    HIGH GPIO.5
    PAUSE 100
    NEXT

    for LED_LOW = 0 to 10 'Turn OFF LED for 1 Second
    LOW GPIO.5
    PAUSE 100
    Next

    GOTO BEGIN

  2. #2


    Did you find this post helpful? Yes | No

    Default

    Madbass1,

    Try this I modified your code.

    DEFINE OSC 4

    TRISIO =%000000 'All outputs
    ANSEL = 0 'ALL I/O digital
    CMCON0 = 7 'comparator off
    OSCCON =$60 'set internal osc to 4mhz

    LED_HIGH VAR BYTE
    LED_LOW VAR BYTE

    BEGIN:

    HPWM 1, 127, 325 'GPIO.2 output 325hz

    FOR LED_HIGH = 0 TO 10 'Turn ON LED for 1 Second
    HIGH GPIO.5
    PAUSE 100
    NEXT

    for LED_LOW = 0 to 10 'Turn OFF LED for 1 Second
    LOW GPIO.5
    PAUSE 100
    Next

    GOTO BEGIN
    Last edited by mark_s; - 15th December 2010 at 18:41.

  3. #3
    Join Date
    Dec 2010
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    I think I'm just going to settle with changing my OSC value. I managed to complete the code and generate my 350Hz and being able to turn it on and off. Thanks for everyones help. My code is listed below:


    'device PIC12F683

    OSCCON = %00100101 '250kHZ system clock
    CCP1CON = %00001100 'Select PWM Mode
    T2CON = %00000100 'Timer2 = ON + 1:1 prescale

    PR2 = 177 'Max Value = 255 Set PWM Period for 350Hz
    CCPR1L = 150 'Set PWM Duty-Cycle to 85% (177*0.85 = 150)

    TRISIO.2 = 0 'GPIO.2 (GPIO.2 = Output)
    TRISIO.1 = 0

    PIN_VOLTAGE VAR BYTE

    INPUT GPIO.1 'Button input
    OUTPUT GPIO.4 'Red LED
    OUTPUT GPIO.5 'Green LED

    BEGIN:
    ADCIN 1, PIN_VOLTAGE 'ADCIN - Button Voltage Level
    IF PIN_VOLTAGE >= 163 THEN 'Voltage greater then 3.2V
    GOTO TURN_OFF_PULSE
    ENDIF

    IF PIN_VOLTAGE <= 160 THEN 'Voltage less then 3.2V
    GOTO TURN_ON_PULSE
    ENDIF

    TURN_ON_PULSE:
    TRISIO.2 = 0 'Turn ouput pulse on - make timer an output
    low GPIO.4 'Turn Red LED off
    HIGH GPIO.5 'Turn Green LED on
    PAUSE 32 'Wait 0.5sec
    LOW GPIO.5 'Turn Green LED off
    PAUSE 32 'Wait 0.5sec
    GOTO BEGIN

    TURN_OFF_PULSE:
    TRISIO.2 = 1 'Turn output pulse off - make timer an input
    HIGH GPIO.4 'Turn on Red LED
    goto begin

    END

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Here are a few ways to do this without using a slower osc.

    For a PIC12F1822 using a compare interrupt.

    Code:
    @  __config _CONFIG1, _FOSC_INTOSC & _MCLRE_OFF & _CLKOUTEN_OFF
    @  __config _CONFIG2, _PLLEN_OFF & _LVP_OFF
     
    DEFINE INTHAND HzOut
     
    LED VAR PORTA.0
     
    TRISA = 0
    ANSELA = 0           ' All digital
     
    CCP1CON = %00001011  ' Compare mode with auto reset of Timer1
    CCPR1H = $06         ' Load for match every 1,538uS
    CCPR1L = $02         ' 1,538uS x 2 = 3.076mS. 1/3.076mS = ~325.09 Hz
    OSCCON = %01101000   ' 4MHz internal osc
    T1CON = %00000001    ' Enable Timer1, 1:1 rescale
    PIR1.2 = 0           ' Clear int flag before enabling interrupt
    PIE1 = %00000100     ' Enable CCP1 interrupt
    INTCON = %11000000   ' Global & peripheral ints enabled
     
    Main:
      TOGGLE LED         ; Do whatever here. You have ~1,538 instruction
      PAUSE 1000         ; cycles before each interrupt
      GOTO Main
     
    ASM
    HzOut                ; Eats-up 5 instruction cycles
      MOVLW B'00000100'  ; Load WREG with %00000100 for XOR op below
      XORWF PORTA,F      ; Toggle PORTA,2 on each 1/2 cycle
      BCF   PIR1,CCP1IF  ; Clear CCP1 interrupt flag
      RETFIE             ; Go get some more
    ENDASM
     
      END
    And one for the 12F683 using Timer2/PR2 match interrupt;
    Code:
    @ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
     
    DEFINE INTHAND HzOut
     
    wsave VAR BYTE $70   SYSTEM
    ssave VAR BYTE BANK0 SYSTEM
    psave VAR BYTE BANK0 SYSTEM
     
    LED VAR GPIO.0
     
    TRISIO = 0
    ANSEL = 0            ' All digital
    CMCON0 = 7
    OSCCON = %01100000   ' 4MHz internal osc
    T2CON = %00111100    ' Enable Timer2, 1:1 prescale / 1:8 postscale
    PIR1.1 = 0           ' Clear TMR2 int flag before enabling interrupt
    PIE1 = %00000010     ' Enable TMR2 interrupt
    INTCON = %11000000   ' Global & peripheral ints enabled
    PR2 = 191
     
    Main:
      TOGGLE LED         ; Do whatever here.
      PAUSE 1000         ; 
      GOTO Main
     
    ASM
    HzOut                
      movwf wsave        ; Save W
      swapf STATUS,W     ; Swap STATUS to W (swap avoids changing STATUS)
      clrf  STATUS       ; Clear STATUS
      movwf ssave        ; Save swapped STATUS
      movf  PCLATH,W     ; Move PCLATH to W
      movwf psave        ; Save PCLATH
     
      MOVLW B'00000100'  ; Load WREG with %00000100 for XOR op below
      XORWF GPIO,F       ; Toggle GPIO,2 on each 1/2 cycle
     
      BCF   PIR1,TMR2IF  ; Clear TMR2 interrupt flag
     
      movf  psave,W      ; Retrieve PCLATH value
      movwf PCLATH       ; Restore it to PCLATH
      swapf ssave,W      ; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
      movwf STATUS       ; Restore it to STATUS
      swapf wsave,F      ; Swap the stored W value
      swapf wsave,W      ; Restore it to W (swap to avoid changing STATUS)
     
      retfie             ; Go get some more
    ENDASM
     
      END
    Interrupts are a LOT faster & easier with newer PIC types with auto context save/restore.
    Last edited by Bruce; - 16th December 2010 at 00:40.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Dec 2010
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Bruce,
    In your code for the pic12f683, is there a way I could define a 85% duty cycle for the 325Hz signal?

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Not without several modifications, but Darrel has a very handy routine at the link below you should find helpful - along with a brief explanation of how you could alter the above to work. http://www.pbpgroup.com/modules/wfse...hp?articleid=6
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7


    Did you find this post helpful? Yes | No

    Default

    Bruce,

    Questions about your code for the 12F1822. Yes, I looked it up and there are some new chips that have auto context save/restore.

    Does the interrupt handler have to be written in ASM? Not that it's a problem, the routines are usually short and simple. Also, can more than one type of interrupt be running together?

  8. #8
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Dick Ivers View Post
    Bruce,
    Does the interrupt handler have to be written in ASM? Not that it's a problem, the routines are usually short and simple. Also, can more than one type of interrupt be running together?
    No it doesn't necessarily have to be in assembler, but it's a lot faster if it is. If you prefer to use BASIC then look into using DT_INTs.

    Yes - you can have every interrupt that's available enabled. You just need to check in the interrupt handler to see which one triggered the interrupt.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts