Using crystals with PICs and their accuracy ..#2

bloguetronica

Joined Apr 27, 2007
1,541
Buy how does that lead to differences like the ones you saw? At what frequency are you running your MCU? I remember doing an experiment running at different frequencies, when using the PIC18F4550, and I concluded the higher the frequency the higher the accuracy. However, even at a low clock rate, the differences were marginal (unless the clock was ridiculously low).

I still have the program I've used, but I don't have the figures I've got. The program is attached, in the hope that helps.
 

Attachments

JohnInTX

Joined Jun 26, 2012
4,787
I don't see why that is a problem. In capture, isn't CCP comparing to TMR1H/L? That must take a little time, perhaps a whole TCY. Assuming a system clock of just 8 MHz, that's a 500 ns TCY. 3TCY +40 =1540 ns = 649 kHz. Your 32 kHz TMRI clock should be no problem.

Running the system clock at 32 kHz might be a problem, if you use Fosc for TMR1, not Fosc/4 for TMR1 clock. In other words, I read that restriction as saying that TMR1 clock cannot be faster than the system (instruction) clock, given that TCY = Fosc/4. The period for that is usually > 40 ns.
Intuitively I'd agree. But the spec is pretty clear and it fits with my experimental results on actual hardware. I tried every OSCCON-settable system clock speed from 31KHz - 500KHz and it was stable only at 500KHz and above. That is consistent with the formula in the table. By visual inspection I thought that >=125KHz waws working - which meant that I didn't understand the formula for min CCP period - but it still fails - just not often enough to see it visually.

Turning the crank on the formula says that the minimum Fosc for 32.768KHz on the CCP is 500KHz. The max CCP frequency at 500KHz Fosc is 41597Hz.
The max CCP freq at 250Khz is 20815Hz, which is not enough.

To test this on the hardware I replaced the interrupt routine with this code. It sets the LED on CCP interrupt and clears it on TIMER interrupt. When things are good, it cycles with the expected 2 sec. period. Gross faults in the operation will show flickering. It's pretty even to the eye at 125KHz+ Fosc but setting breakpoints in the traps below show that its still isn't perfect. Occasionaly it misses. The rate of failure gets worse as the system clock speed gets slower. At 31KHz, its immediate. At 125 KHz, you can get a cup of coffee before it breaks. At 250KHZ, you can get lunch but it will eventually fail. At 500KHz, it's solid.

You can check it out by replacing the interrupt routine with the code below and setting breakpoints where indicated. Start at the default 500KHz Fosc and verify operation. Reduce Fosc using OSCCON and it will start breaking.

The upshot is that it really doesn't look like the CCP will work with 31KHZ, sync'ed or not.

Sorry.
Code:
;********************************** Zone of common RAM ***********************************
;  Only 16 bytes are available, but there's no need to switch memory Banks to work on it
;*****************************************************************************************
TEMPVAR1   EQU 70H
TEMPVAR2   EQU 71H


JTflags EQU 72h            ; determines which IRQ should be next
#define FoundCCP JTflags,0

;*****************************************************************************************
;                       Reset and Interrupt program memory locations
;*****************************************************************************************
        ORG    0x000                ;processor reset vector
   
RESET_VECTOR:
        clrf    JTflags        ; TEST IRQ ONLY!
        goto    Init        ; go to beginning of program

        ORG    0x004        ;interrupt vector location
INT_VECTOR:
     ;--------------------------
      ; Modified IRQ service to enforce alternate CCP and TIMER 1 interrupts.
      ; LED ON on CCP interrupt, OFF on timer interrupt.
      ; When things are working correctly, the LED will flash ON/OFF with a
      ; 2 sec period.
      ; Breakpoint traps indicate when the CCP/TMR1 IRQs don't alternate.
      ; When running with a system clock of >=500KHz, the operation is flawless.
      ; Reducing the system clock will cause errors at an increasing rate
      ; as the system clock freq goes down.
 
 
    banksel    PIR1          ;Bank 0
    btfss    PIR1,CCP1IF ; CCP?
    goto    svcTMR1        ; nope, service timer interrupt

    bsf    LATC,LED_PIN        ; LED ON with CCP IRQ
    bcf    PIR1, CCP1IF      ;clear the compare mode interrupt flag
    btfsc    FoundCCP    ; flag has to be 0
    goto    multipleCCP    ; else its a repeat before timer overflow

    bsf    FoundCCP    ; its ok, set the flag
    goto    IRQdone

; Gets here if a second CCP interrupt happened before the Timer interrupt  
multipleCCP:
    nop            ; Set breakpoint here
    nop
    bcf    FoundCCP    ; for next break
    goto    IRQdone

svcTMR1:      
       bcf  PIR1,TMR1IF     ; clear the Timer1 interrupt flag
       bcf  LATC,LED_PIN    ; LED off on timer interrupt

       btfss    FoundCCP    ; previous CCP interrupt?
       goto    noCCP        ; nope

       bcf    FoundCCP    ; else, ack the CCP and done
       goto    IRQdone


; Gets here if two successive Timer interrupts without a CCP interrupt
noCCP:      
    nop            ; Set breakpoint here
    nop      
    ; fall through to exit
IRQdone:
    retfie ;Return from interrupt. Previous memory Bank will automatically be restablished
 

jpanhalt

Joined Jan 18, 2008
11,087
I don't see why that is a problem. In capture, isn't CCP comparing to TMR1H/L? That must take a little time, perhaps a whole TCY. Assuming a system clock of just 8 MHz, that's a 500 ns TCY. 3TCY +40 =1540 ns = 649 kHz. Your 32 kHz TMRI clock should be no problem.

Running the system clock at 32 kHz might be a problem, if you use Fosc for TMR1, not Fosc/4 for TMR1 clock. In other words, I read that restriction as saying that TMR1 clock cannot be faster than the system (instruction) clock, given that TCY = Fosc/4. The period for that is usually > 40 ns.
I am not sure we disagree in the actual analysis. Using the calculation in my first paragraph for 500 kHz Fosc: TCY = 8 us; 3TCY+40ns = 24.04 us = 41,597 Hz (max CCP freq). That is consistent with my calculation for an 8 MHz Fosc, unless I made a silly math mistake.

Where I screwed up was in my aside guess about a whole TCY (it's clearly 3 TCY + 40 ns) and the calculation in the second paragraph. If the system clock is at 32 kHz and TMR1 is at 8 kHz, then 32 kHz = 0.125 ms TCY; 3TCY +40 ns = 0.37504 ms = 2666 Hz, which is not enough.* Obviously, I forgot to multiply the TCY by 3 and add a little. I will edit my post accordingly.

I apologize for putting you through that extra work.

John

*MPLab SIM does show an issue with too fast a TMR1. I set the simulation speed at 32 kHz and T1CON to 00000101 (TMR1 clock = Fosc, no prescale, no sync) and on rollover, TMR1H/L = 049Fh. On CCP match interrupt, TMR1H/L = 849Fh. When I added a 1:8 prescale for TMR1, the results were 0093h and 8093h, respectively. I got similar results at 8 MHz simulation too.
 

JohnInTX

Joined Jun 26, 2012
4,787
I am not sure we disagree in the actual analysis. Using the calculation in my first paragraph for 500 kHz Fosc: TCY = 8 us; 3TCY+40ns = 24.04 us = 41,597 Hz (max CCP freq). That is consistent with my calculation for an 8 MHz Fosc, unless I made a silly math mistake.

Where I screwed up was in my aside guess about a whole TCY (it's clearly 3 TCY + 40 ns) and the calculation in the second paragraph. If the system clock is at 32 kHz and TMR1 is at 8 kHz, then 32 kHz = 0.125 ms TCY; 3TCY +40 ns = 0.37504 ms = 2666 Hz, which is not enough.* Obviously, I forgot to multiply the TCY by 3 and add a little. I will edit my post accordingly.

I apologize for putting you through that extra work.

John

*MPLab SIM does show an issue with too fast a TMR1. I set the simulation speed at 32 kHz and T1CON to 00000101 (TMR1 clock = Fosc, no prescale, no sync) and on rollover, TMR1H/L = 049Fh. On CCP match interrupt, TMR1H/L = 849Fh. When I added a 1:8 prescale for TMR1, the results were 0093h and 8093h, respectively. I got similar results at 8 MHz simulation too.
No worries. I was confused too since it looked like it was working correctly at 125KHz visually and I kept thinking my math was off, too. It wasn't until I did the breakpoint thing that the spec was confirmed. Heck, I didn't even know it HAD a spec and I've used CCP for years.

But, @cmartinez I don't know exactly why but it's been running fine with both CCP and TMR1 interrupts when I switch the clock over to use the external TIMER 1 oscillator. So.... maybe that restriction is to sync the external osc with the internal Tcycs?? Don't know but like John said, it isn't obvious why it takes 3 Tcyc to sync up to an ext. osc. Maybe it's happy when running from the same osc?

At any rate, the stopwatch count using the external Timer 1 osc as the system clock is 8192 Tcyc between interrupts every time. A few jabs at the Lil Professor says that is 32.768K Foscs so.. wow!

EDIT: I restarted it after the stopwatch stuff and it hit a fault-trap breakpoint so.. bummer. And ????
EDIT2: after a clean reset, its working again... Maybe doesn't like a restart inside the debugger... Worth some investigation.
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
Just to clarify: my project is working at 31 KHz, not 32 KHz.

Either way, thanks to John in TX and John in OH I now have a much clearer understanding of why my project is not working the way I want it to... leave it to me to be the one who finds a can of worms and opens it...

I'll be back with my results as soon as I get the 32.768 KHz MEMS oscillators and have them up and running in my circuit. I'll need to tweak the code a little bit too but that should take only a few minutes.
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
At any rate, the stopwatch count using the external Timer 1 osc as the system clock is 8192 Tcyc between interrupts every time. A few jabs at the Lil Professor says that is 32.768K Foscs so.. wow!
How do I do that? How can I make the chip use Timer1 as the system clock?
 

JohnInTX

Joined Jun 26, 2012
4,787
How do I do that? How can I make the chip use Timer1 as the system clock?
Let it start with the default system clock or something slower if you want; it doesn't matter until you turn on the interrupts
Start TIMER1 with the external oscillator.
You probably want to give it some time to stabilize - looks like a couple of seconds on my scope.
Write 00000001 to OSCCON to select TIMER1 oscillator as the system clock.
Relocate the interrupt enables to AFTER you think the TIMER 1 oscillator has stabilized - I haven't done that yet, maybe that's why it is a bit sketchy..

There probably is a preferred sequence, I just scabbed it in to see what would happen.

EDIT: an easy way to ensure that the ext TMR1 osc is up is to:
Clear the timer registers, TMR1IF and start the timer as early as possible in the program. Leave the interrupts OFF.
Do the rest of the init stuff using the default or slower system clock.
Poll TMR1IF. When it sets, you've had 64K good oscillator cycles.
Clear TMR1IF, CCP1IF and enable the interrupts.
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
I've just finished my code, and then I read your message. It is practically exactly what you've told me to do. But I'm checking Timer1's stability using the OSCSTAT register, and it seems to be working:

Code:
       banksel PIR1               ;Bank 0
       clrf PIR1                  ;clear all peripheral interrupt flags
       ;banksel TIMR1L            ;Bank 0
       clrf TMR1L                 ;clear both bytes of the
       clrf TMR1H                 ;Timer1 counter

       ;and lastly, set Timer1 parameters and turn it on
       ;banksel T1CON              ;Bank 0
       ;the bit structure of T1Con is as follows:
       ;  TMR1CS    |   T1CKPS    |T1OSCEN| /T1SYNC |  -  | TMR1ON|
       ; 7      6      5      4       3       2        1      0   |

       ;banksel T1CON               ;Bank 0       
       ;Clock source is pin or oscillator  (10)
       ;Prescaler is 1:1                   (00)
       ;Oscillator circuit enabled          (1)
       ;External Clock Input Sync disabled  (1)
       ;bit 1 is not used                   (0)
       ;Timer1 start                        (1)
       movlw b'10001101'
       movwf T1CON

       ;Timer1 interrupt period is now given by 2^16/32.768 KHz = 2 seconds exactly
       banksel OSCSTAT            ;select memory Bank 1
       btfss OSCSTAT, T1OSCR      ;wait here until Timer1 oscillator is ready
        goto $-2

       ;Switch system clock from internal oscillator to Timer1 oscillator 
      ;banksel OSCCON             ;select memory Bank 1
       movlw b'00000001'          ;the W register has been loaded with the IRCF bits as zeroes
       movwf OSCCON

       banksel PIE1               ;Bank 1
       bsf PIE1, TMR1IE           ;enable Timer1 overflow interrupt
 

JohnInTX

Joined Jun 26, 2012
4,787
But I'm checking Timer1's stability using the OSCSTAT register, and it seems to be working:
Cool! I didn't know they had that. Good work!

EDIT:
$-2 takes you back 2 instructions - is that what you want? It doesn't hurt here but just so you know.

banksel OSCSTAT ;select memory Bank 1
btfss OSCSTAT, T1OSCR ;wait here until Timer1 oscillator is ready
goto $-2 <<-- goes to banksel OSCSTAT, not btfss..
 

bloguetronica

Joined Apr 27, 2007
1,541
Indeed, that was another caveat I forgot about. The TIMER1 oscillator takes some time to warm um and stabilize. The trick is to keep it always on. However, if you are running your main clock at a frequency that low, you might run into some degree of imprecision. I remember running the PIC at frequencies like 8MHz or so, if I recall correctly, when I did the tests a long time ago. It was years ago, so I don't remember the details.

Anyway, it seems that you have this sorted out. Good job!
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
This is really neat... switching to Timer1 as the system clock source made the device consume a little less current... it went down from 15.2 µA to 14.6 µA ... it may not sound like much, but I want the batteries to last as much as possible, and lower current is always good news.
 

JohnInTX

Joined Jun 26, 2012
4,787
This is really neat... switching to Timer1 as the system clock source made the device consume a little less current... it went down from 15.2 µA to 14.6 µA ... it may not sound like much, but I want the batteries to last as much as possible, and lower current is always good news.
One less oscillator. Gotta keep that in mind! I’m learning, too.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,257
And by the way, here's a picture of my setup, in case you're curious:

f85b273b-6328-42e4-8c66-300939426a88.jpg
That µCurrent device that I bought from Dave Jones from EEVblog is a jewel of a gadget... :)
 

bloguetronica

Joined Apr 27, 2007
1,541
Oh, that PicKit3. If you have to open it, mind that you may never be able to close it again. I had to replace the female header on mine, so I opened it but the plastic hooks broke.

Anyway, it seems that you are targeting for low consumption. Now I understand why you don't wish to use a higher clock. Well, I guess it is a matter of compromise.
 

jpanhalt

Joined Jan 18, 2008
11,087
Oh, that PicKit3. If you have to open it, mind that you may never be able to close it again. I had to replace the female header on mine, so I opened it but the plastic hooks broke.

Anyway, it seems that you are targeting for low consumption. Now I understand why you don't wish to use a higher clock. Well, I guess it is a matter of compromise.
Did you try Duct Tape?

1605824366800.png
 

JohnInTX

Joined Jun 26, 2012
4,787
And by the way, here's a picture of my setup, in case you're curious:
Likewise. Kind of crammed up as there is another project off to the left. The scope shows your TIMER1 osc. It is till working with no errors for a couple of hours using TMR1/CCP IRQs w/TMR1 osc as system clock. No particular care taken for xtal loading etc..

1605827537816.jpeg
 

bloguetronica

Joined Apr 27, 2007
1,541
Ouch! ... by the way, I'll be buying the PICkit4 in a few weeks, just to stay up to date.
I was not aware of the new version. I've seen some pictures, and I'm glad they dropped the crystal polystyrene case, as it is too brittle (it would be something to be use in a CD jewel case), and they are back to the ABS enclosure. Much better!
 
Top