12f675_fuse_about_to_blow!


Closed Thread
Results 1 to 40 of 929

Hybrid View

  1. #1
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    No, not trimmer... or timmer .... I really need to get a dictionary

    Timer as in TMRO.

    Many times we will at the beginning of a new project to make sure things are setup correctly we will do a simple "blinky" just like we tell the newbees to do. I will a lot of times leave it running as a "heart beat" type of thing. But if you do this using pauses to blink the LED the pauses will maybe get in the way.

    So now comes a basic interrupt based on time.
    This may or may not be correct for your chip so verify with the data sheet.
    Code:
        INTCON.5 = 1    'ENABLE TMR0
        OPTION_REG = %10000101  '16BIT 1:64 PRESCALE
        ON INTERRUPT GOTO TLOOP
    
        MAINLOOP:
        'MAIN CODE GOES HERE
        GOTO MAINLOOP
    
        DISABLE
        TLOOP:
        INTCON.2=0:TOGGLE PORTD.4
        RESUME: ENABLE
    Dave
    Always wear safety glasses while programming.

  2. #2
    Join Date
    Feb 2010
    Location
    I live in the UK
    Posts
    562


    Did you find this post helpful? Yes | No

    Default

    Hi mackrackit, everyone.

    I've been doing a lot of reading trying to figure out what's actually going within your Timer / Interrupt program. So here's my interpretation (he typed as he makes a fool of himself again).....!

    Code:
     INTCON.5 = 1    'ENABLE TMR0
    Setting the Interrupt_Control pin.5 = 1 simply enables the Timer0 interrupt.

    Code:
    OPTION_REG = %10000101  '16BIT 1:64 PRESCALE
    First of all you set the Global Interrupt Enable bit.7 =1.
    Then bits 0 = 1 & bit 2 = 1 sets the PRESCALE value 1/64 of the system clock.
    4MHZ or the instruction clock 1MHZ (not 100% sure on that one) This divided down figure is then sent to the TIMER0 register (incremented count from the prescaler).

    When the count goes from FF(HEX) +1 (255 decimal,it over-runs back to zero).

    So (wild assumption here) when the count overflows passed 255 the INTERRUPT occurs and the program jumps to the Label TLOOP. The LED blinks, then INTCON.2 pin is the reset to 0 and it does it all again.

    So basically to my (small) mind the LED would blink every 1/64th of 1MHZ.

    Anywhere warm on this one?

    Dave
    Last edited by LEDave; - 22nd March 2010 at 17:20.

  3. #3
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Warm...
    Setting the Interrupt_Control pin.5 = 1 simply enables the Timer0 interrupt.
    That is not setting a pin, it is setting bit#5 of the register.
    When the count goes from FF(HEX) +1 (255 decimal,it over-runs back to zero).
    Correct.


    Now for the tricky part.
    Running with a 4MHz OSC the chip is actually running at 1MHz.. Or cycles at 1 micro second (ticks).
    If the prescaler is set for 1:1 then it will overflow every 256 micro seconds.
    If the prescaler is set for 1:2 then it will overflow every 512 micro seconds.
    If the prescaler is set for 1:256 then it will overflow every 65536 micro seconds.
    Dave
    Always wear safety glasses while programming.

  4. #4
    Join Date
    Feb 2010
    Location
    I live in the UK
    Posts
    562


    Did you find this post helpful? Yes | No

    Default

    Hi there.

    As ever can I start with a question:

    The TIMER program. My reading of it is that with a prescaler of 1:64 the LED
    attached to PORTD.4 would blink (toggle) every 16384 microseconds (pretty quick) And that because this is driven by the internal clock runs independently of any code enclosed within 'MAIN'. For example, you could have an LED set within MAIN to say PORTD.3 which would blink every 2 seconds whilst the LED on PORTD.4 would to all intents and purposes show permanently on (like you said a heartbeat indicator that all's running well).

    Am I reading this right?

    David

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi Dave,
    Yes, the LED would toggle every 16384uS, in other words it would blink at rougly 30.5Hz, youll be hard pressed to see that. If you change the prescaler to 1:256 you'll get 4000000/4/256/256/2 = 7.62Hz.

    The problem with PBP's way of handling interrupts is that it can not interrupt the command/statement that it is currently executing. Lets say for example that your main routine looks something like this:
    Code:
    Main:
      GPIO.0=1
      Pause 500
      GPIO.0=0
      Pause 500
    Goto Main
    This would blink a LED connected to GPIO.0 at 1Hz and you would think that the TMR0 interrupts would blink the other LED at 7.62Hz, unfortunatley that's not the case....
    In the above code the interrupts generated by TMR0 would only get served between each statement. In other words, during the 0.5 second pauses the 7.62Hz blink would stop.

    Basically, what PBP does, under the hood, is to add check after each statement, like:
    Code:
    Main:
      GPIO.0=1
      IF Interrupt goto TLOOP    'This is not the actual code it adds, it's just to illustrate the principle
      Pause 500
      IF Interrupt goto TLOOP
      GPIO.0=0
      IF Interrupt goto TLOPP
      Pause 500
      IF Interrupt goto TLOOP
      Goto Main
      IF Interrupt goto TLOOP
    As you can see, if an interrupt occurs in the middle of a Pause it won't get serviced until the Pause statement has finished so if you're using PBP's ON INTERRUPT you need be aware of this. There are other ways to do it which doesn't suffer from the issue described above (Darrels Instant Interrupt routines obviously).

    Hope it helps.
    /Henrik.

  6. #6
    Join Date
    Feb 2010
    Location
    I live in the UK
    Posts
    562


    Did you find this post helpful? Yes | No

    Default

    Hi Henrik

    As you can see, if an interrupt occurs in the middle of a Pause it won't get serviced until the Pause statement has finished so if you're using PBP's ON INTERRUPT you need be aware of this.
    Very interesting that because I built a little test circuit based on mackrackit's code using a PIC12F683 (program below) with the INTERRUPT toggling an LED on GPIO.4 The MAIN code turned an LED on and off you've guest it using pause statements!

    I was expecting the INTERRUPT LED (GPIO.4) to blink really quickly and the LED on GPIO.0 to blink at 500 mili_secs much slower, in reality they were much the same speed.

    The manual refers to this as (latency). Like you say it pays to be aware of it. You wouldn't want an interrupt acting as an emergency stop when combined with a long pause statement.....Ouch!

    Code:
    ANSEL  = %00000000
    CMCON0 = %00000111
    TRISIO = %11101110
    GPIO   = %00000001
    INTCON.5 = 1                    'ENABLE TMR0
    OPTION_REG = %10000101  '16BIT 1:64 PRESCALE
     
        ON INTERRUPT GOTO TLOOP
    
        MAINLOOP:
        PAUSE 500    
        low GPIO.0   
        PAUSE 500    
        high GPIO.0  
        GOTO MAINLOOP
         
    
        DISABLE
        TLOOP:
        INTCON.2=0:TOGGLE GPIO.4
        RESUME: ENABLE

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Now that you're aware of how ON INTERRUPT works there are a few things that can be done to help speed up the response (latency). Instead of having a single 500ms long pause, how about 500 pauses, each 1ms long?
    Code:
    i VAR WORD
    Main:
      GPIO.0 = 1
      GOSUB GoToSleep
      GPIO.0=0
      GOSUB GoToSleep
    Goto Main
    
    GoToSleep:
      For i = 1 to 500
        PauseUs 1000     'Tweak this if timing is critical.
      Next
    RETURN
    Now, you should get pretty close to what you expected in the first place. If timing is really critical you'll need to tweak the PauseUs statement as each time thru the loop takes a couple of uS longer due to the inserted checks of the interrupt-flag and the fact that it takes a few cycles to jump around inside the FOR-NEXT loop.

    Also, remember what we said about HIGH and LOW? That they write to the TRIS register everytime.....and there's no need for you to use them as you've so elegantly set the TRIS register correctly at the beginning of your program. It's usually "better" and faster to simply write directly to the port register with GPIO.0=1 etc.

    /Henrik.
    Last edited by HenrikOlsson; - 23rd March 2010 at 18:44.

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