Problem with MCU timing in C

Discussion in 'Programmer's Corner' started by ke5nnt, Aug 24, 2011.

  1. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    I've been working on little projects to learn the C language using MPLAB IDE and High-Tech C lite compiler.

    I have noticed that although my codes function as they're supposed to, my timing is always off and I'm not sure why. A flash of the LED for 1 second is coming out to be about 800mS or so, and I'm unsure as to the discrepancy.

    I have heard that the High-Tech C compiler Lite version does not allow for precise timing operations, though I'm not sure if that's actually the case, but if anyone has heard this and it turns out it's not a problem with my code, that'd be nice to know. Here is my code snippet where I define clocks:

    Code ( (Unknown Language)):
    1.  
    2. // CONFIGURATION
    3.  
    4. #include <htc.h>
    5. #define _XTAL_FREQ 4000000
    6. __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & BORDIS & LVPDIS & UNPROTECT & UNPROTECT);
    7.  
    8. /*************************************************/
    9.  
    10. //    GLOBAL VARIABLES
    11.  
    12. unsigned char dlycnt;    //DELAY COUNTER
    13. unsigned char fpnum;    //FLASH PATTERN NUMBER
    14. unsigned char set = 0;
    15. unsigned char dbnce;    //SWITCH DEBOUNCE
    16. /*************************************************/
    17.  
    18. void main()                //MAIN PROGRAM START
    19. {
    20. unsigned char address = 0;    //DEFINE ADDRESS FOR EEPROM
    21. INTEDG = 1;                    //TRIGGER INTERRUPT ON RISING EDGE
    22. INTE = 1;                    //RB0 EDGE INTERRUPT ENABLED
    23. ei();                        //GLOBAL INTERRUPTS ENABLED
    24.  
    25. fpnum = eeprom_read(address); //DATA READ FROM EEPROM AND COPIED TO fpnum
    26.  
    27.  OSCF=1;            // INTERNAL OSCILLATOR 48KHz
    28.  TRISA=0XFF;        // TRISA NOT USED, ALL SET AS INPUT
    29.  TRISB=0XF7;        // TRISB 7-4 INPUT, 3 OUTPUT, 2-0 INPUT
    Also, I'm calling delays using this routine:

    Code ( (Unknown Language)):
    1.  
    2. RB3=1;            //SET RB3 HIGH
    3.      for (dlycnt=0; dlycnt<10; dlycnt++)    //CALL 1 SECOND DELAY
    4.      {
    5.         __delay_ms(100);
    6.      }
    Thanks for the help.
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    20% off for 10 loops of a 100 mS delay does seem excessive. Is that "INTIO" config setting for the internal oscillator? Have you checked how fast that is actually running?
     
  3. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    INTIO is for internal oscillator with the clock pins set to I/O mode. I have not checked how fast it is actually running as I'm not entirely sure how to do this, I'll be honest.

    Also, I'll clear something up right now that I just noticed about my code so that no one else does. I have _XTAL_FREQ set for 4MHz which is correct, but my comments under OSCF=1 say that it's set for 48KHz. 48KHz was the original setting, but I changed it to test if the 48KHz setting was what was messing up the timing, and I just never changed the comment. The timing is off regardless of whether the MCU is operating at 4MHz or 48KHz.

    Perhaps I should test the timing using an external 4MHz crystal, which I have on hand, and see if the timing is still off.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    When using a new PIC device my first "reality check" is to see if I've set up things correctly so I am actually running at the frequency I think I am.

    One way (simpler but...) is if your internal oscillator can drive a pin (and it's free!) you can drop a scope on it to read what Fosc / 4 is.

    Other way is to write some code to toggle any free pin hi and low several times, a short delay, then rinse wash repeat. A scope should be able to capture the pulse at the first edge if you set the re-trigger delay correctly. Go back and look at the disassemble listing and count how many instructions it takes for each 1 and 0, and use that to compute the internal instruction clock.

    I'd do that before I started changing hardware as you can introduce other problems doing that, though the crystal should run pretty dead nuts on 4MHz. Just that it may not run, and you are running now.
     
    ke5nnt likes this.
  5. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Thank you Ernie, appreciate the feedback. I do not own a scope, though I'm in the market for one, so the best way I have at the moment to test frequency accuracy (very rudimentary) is to flash a LED on/off once per second and compare it to the ticks on my wrist watch. Yea, I know... once you're done laughing...
     
  6. stahta01

    Member

    Jun 9, 2011
    133
    21
    A frequency counter is a cheaper solution that a O-scope.

    Tim S.
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Believe me, I'm not laughing. I'm lucky to have a scope I picked up as it was being tossed as "obsolete," but it is a classic Tektronics analog scope.

    Can you run your code in a simulator? If it sims as 1.00 seconds then it's the PIC running fast and the code is OK.

    Without a scope it may also be a good idea to use your crystal, it's probably either gonna run dead nuts accurate or not at all, so you learn something.
     
  8. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Still planning on testing things with an external crystal, just haven't had a chance to do it yet. I've been too busy between work and getting ready for the Fall school semester to start on Monday.
    Should have time to test this later today.
     
  9. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    There's nothing wrong with that! In the drawer on my compter desk I have a little cheap digital stopwatch. It's easy to generate (say) a 10second period in software and grab the stopwatch to check the timing is ok, that's also a great way to test simple things like PIC timer prescaler settings etc.

    Re your timing issue it might be that you have cleared the PIC internal osc calibration value, with some PICs when the calibration value is cleared the timing will be 10% or 20% out, similar to what you are getting.
     
  10. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    You know, that could actually be the case. I don't remember specifically clearing the MCU timing calibration, but I suppose being so new to programming yet that I could have inadvertently done so. If I remember correctly, the Datasheet of the PIC should tell me how to recalibrate the timing. I'll look into that... again, when I have time. I know I keep saying that I'm going to throw a crystal on the thing to see if that solves timing, but again, I haven't had time. School started and I'm working full time (as I always have) so time is short!

    I'll check both, crystal first, then recalibrate the chip. Thanks for all the great feedback guys, always appreciated. :)
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    My PicKit II could recalibrate some devices, it has an app for that. AFAIK it is a menu choice on the PicKit II stand-alone application.
     
  12. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Remember that _XTAL_FREQ is the system clock. So if your MCU is running at 48KHz clock speed. You should use 48KHz then defining the _XTAL_FREQ
    It would also help if you told us which PIC you are using
     
Loading...