PIC32MX delays

Thread Starter

davidc

Joined Jul 2, 2009
16
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.
Rich (BB code):
#define FOSC 40e6
#define PRESCALE 256
/*
    Set the tick period.
    The timers are clocked by the peripheral bus. By default, the PBCLK (Peripheral Bus Clock) frequency is the SYSCLK frequency divided by 8
*/
#define PB_DIV 8
#define TICK_PERIOD_MSECS 1 /* tick period in milliseconds */
#define TICK_PERIOD ((FOSC/PB_DIV/PRESCALE) * TICK_PERIOD_MSECS/1000)

void start_timer() {
    OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, TICK_PERIOD);
    ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2);
}
The relevant interrupt service routine is this.
Rich (BB code):
void __ISR(_TIMER_1_VECTOR, ipl2) _Timer1Handler(void) {
    // clear the interrupt flag
    mT1ClearIntFlag();
    
    period_elapsed++;
    if (period_elapsed == delay_period) {
        delay_over = 1;
        CloseTimer1();
    }
}
.

The delay routine itself is
Rich (BB code):
void delay_ms(UINT8 ms) {
    delay_period = ms;
    period_elapsed = 0;
    delay_over = 0;
    start_timer();
    while (!delay_over) {
        asm("nop"); // do nothing
    }
}
.

The above routines used global variables defined as
Rich (BB code):
UINT8 delay_period; // delay period in milliseconds
UINT8 period_elapsed = 0; // period elapsed
UINT8 delay_over = 0;
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.)
 

nsaspook

Joined Aug 27, 2009
13,277
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?
 

ErnieM

Joined Apr 24, 2011
8,377
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.
 

Thread Starter

davidc

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

nsaspook said:
why not just skip the interrupt, start and poll the timer interrupt flag directly in the while statement?
Do you mean something like this (as well as scrapping the ISR)?

Rich (BB code):
void delay_ms(UINT8 delay_period) {
    period_elapsed = 0;
    start_timer();
    while (period_elapsed < delay_period) {
        if (INTGetFlag(INT_T1)) {
            period_elapsed++;
            mT1ClearIntFlag();
        }
    }
    CloseTimer1();
}
@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
Rich (BB code):
WriteTimer1(0x0000);
worth adding to the start_timer() function?
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
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:
Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).
So as long as you only use Microchip's code on a Microchip device you're cool.

That works for me.
 

nsaspook

Joined Aug 27, 2009
13,277
Hi nsa. Hi Ernie. Many thanks for the feedback.



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

Rich (BB code):
void delay_ms(UINT8 delay_period) {
    period_elapsed = 0;
    start_timer();
    while (period_elapsed < delay_period) {
        if (INTGetFlag(INT_T1)) {
            period_elapsed++;
            mT1ClearIntFlag();
        }
    }
    CloseTimer1();
}
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.
 
Top