PIC32MX delays

Discussion in 'Embedded Systems and Microcontrollers' started by davidc, Jun 14, 2012.

  1. davidc

    Thread Starter Member

    Jul 2, 2009
    16
    0
    Hi all. I need to implement delays of a few milliseconds on a PIC32MX microcontroller, and would just like some feedback on a possible method I plan to try.

    I plan to use the Timer1 interrupt, opening and configuring it as follows.
    Code ( (Unknown Language)):
    1.  
    2. #define FOSC 40e6
    3. #define PRESCALE 256
    4. /*
    5.     Set the tick period.
    6.     The timers are clocked by the peripheral bus. By default, the PBCLK (Peripheral Bus Clock) frequency is the SYSCLK frequency divided by 8
    7. */
    8. #define PB_DIV 8
    9. #define TICK_PERIOD_MSECS 1 /* tick period in milliseconds */
    10. #define TICK_PERIOD ((FOSC/PB_DIV/PRESCALE) * TICK_PERIOD_MSECS/1000)
    11.  
    12. void start_timer() {
    13.     OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, TICK_PERIOD);
    14.     ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2);
    15. }
    16.  
    The relevant interrupt service routine is this.
    Code ( (Unknown Language)):
    1. void __ISR(_TIMER_1_VECTOR, ipl2) _Timer1Handler(void) {
    2.     // clear the interrupt flag
    3.     mT1ClearIntFlag();
    4.    
    5.     period_elapsed++;
    6.     if (period_elapsed == delay_period) {
    7.         delay_over = 1;
    8.         CloseTimer1();
    9.     }
    10. }
    .

    The delay routine itself is
    Code ( (Unknown Language)):
    1.  
    2. void delay_ms(UINT8 ms) {
    3.     delay_period = ms;
    4.     period_elapsed = 0;
    5.     delay_over = 0;
    6.     start_timer();
    7.     while (!delay_over) {
    8.         asm("nop"); // do nothing
    9.     }
    10. }
    11.  
    .

    The above routines used global variables defined as
    Code ( (Unknown Language)):
    1.  
    2. UINT8 delay_period; // delay period in milliseconds
    3. UINT8 period_elapsed = 0; // period elapsed
    4. UINT8 delay_over = 0;
    5.  
    One of my concerns is that - with the above code - Timer1 is being opened and closed every time the delay routine is called. I'm just wondering if this could be a problem.

    Note: I would prefer to use interrupts than just loop constructs by themselves - as, according to my understanding, this will yield more reliable and precise time durations. I invite correction on that however. (E.g. the delays are required for the handshake in a serial communications protocol. Maybe the delays don't need to be so accurate?)

    The code is compiling fine, but I'm still waiting for a PIC32 starter kit to arrive so haven't tried this on the actual hardware yet. (And even if it does "work" that doesn't necessarily mean it's the preferred solution.)
     
  2. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,908
    2,169
    You're polling (and doing nothing else) for a semaphore from the ISR adding extra delays and complications, why not just skip the interrupt, start and poll the timer interrupt flag directly in the while statement?
     
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,389
    1,605
    I don't see any problems opening and closing the timer over and over. It's not like it's gonna break if you keep using it <grin>.

    Microchip has a nice library to handle delays like this located at ..\Microchip Solutions v2012-04-03\Microchip\Common\TimeDelay.c, and the header is in ..\Microchip Solutions v2012-04-03\Microchip\Include (where you will also find the incredibly useful GenericTypeDefs.h file). The library doesn't use any timers, just loops and counts.

    There is an excellent book on this device. well worth your time & money.

    I haven't done much with the timers. I have one running on my board as a heartbeat that the graphic device code set up for me. I think I made another interrupt for something else but don't remember those details.
     
  4. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,908
    2,169
    You have to be careful with MIPS prefetch/caching when doing software delays, the timing can be affected by large amounts depending on device configuration and other interrupts.

    http://www.microchip.com/forums/m655872.aspx
     
  5. davidc

    Thread Starter Member

    Jul 2, 2009
    16
    0
    Hi nsa. Hi Ernie. Many thanks for the feedback.

    Do you mean something like this (as well as scrapping the ISR)?

    Code ( (Unknown Language)):
    1.  
    2. void delay_ms(UINT8 delay_period) {
    3.     period_elapsed = 0;
    4.     start_timer();
    5.     while (period_elapsed < delay_period) {
    6.         if (INTGetFlag(INT_T1)) {
    7.             period_elapsed++;
    8.             mT1ClearIntFlag();
    9.         }
    10.     }
    11.     CloseTimer1();
    12. }
    13.  
    @Ernie: Thanks for the tips. Had a quick look into the Microchip TimerDelay library you mentioned and it would probably be adequate - but I will probably test out the afore-mentioned code before resorting to a third-party solution (especially a proprietary one).

    As an aside, is it necessary to zero the timer value when it is opened? E.g. is this
    Code ( (Unknown Language)):
    1. WriteTimer1(0x0000);
    worth adding to the start_timer() function?
     
    Last edited: Jun 14, 2012
  6. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,389
    1,605
    Zeroing the timer probably makes it easier to use (google the GetTickCount dilemma).

    As far as the proprietary third-party solution goes, the EULA is pretty open:
    So as long as you only use Microchip's code on a Microchip device you're cool.

    That works for me.
     
  7. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,908
    2,169
    That's the idea, skip the ConfigInt... and poll directly. In your case with program flow stopped and waiting for a flag anyway it should be simpler.
     
Loading...