This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

C delay routine

I need to write a delay routine in C for a 80C251 . The delay has got to be about 30 seconds . Any ideas welcomed.

  • Create a timer ISR that fires every 10ms. Then create volatile variables that this ISR decrements every: 1 interrupt, 10 interrupts, and 100 interrupts. Then put volatile gating variables that allow the ISR to decrement the vars.

    In your background (non-ISR code) create functions called delay10ms(), delay100ms(), and delay1s(). Each of these functions will protect their respective counters from the ISR by clearing the gate var, writing the new count down value, setting the gate var to allow counting down via ISR, and pending on the count down var reaching zero.

    Be sure the count down vars. atomically accessible. E.g. an 8-bit quantity on an 8-bit machine. If not, you can use the gate vars for checking countdown complete by just telling the ISR to clear the gate when the countdown var hits zero.

    /* Timer.c
    */
    volatile static Bool s_gate10ms;
    volatile static Bool s_gate100ms;
    volatile static Bool s_gate1s;
    
    volatile static U8 s_countDown10ms;
    volatile static U8 s_countDown100ms;
    volatile static U8 s_countDown1s;
    
    static void timerIsr(void)
    {
        static U16 count10ms;
    
        /* 10ms timing 2.55 second duration max.
        */
        if (s_gate10ms && s_countDown10ms)
        {
            --s_countDown10ms;
        }
    
        if (!(count10ms % 10))
        {
            /* 100ms timing
            */
            if (s_gate100ms && s_countDown100ms)
            {
                --s_countDown100ms;
            }
    
            if (!(count10ms % 100))
            {
                /* 1s timing
                */
                if (s_gate1s && s_countDown1s)
                {
                    --s_countDown1s;
                }
            }
        }
    }
    
    /* Public functions
    */
    void delay10ms(U8 num10msTicks)
    {
        s_gate10ms      = 0;
        s_countDown10ms = num10msTicks;
        s_gate10ms      = !0;
        while (s_countDown10ms);
    }
    
    void delay100ms(U8 num100msTicks)
    {
        s_gate100ms      = 0;
        s_countDown100ms = num100msTicks;
        s_gate100ms      = !0;
        while (s_countDown100ms);
    }
    
    void delay1s(U8 num1sTicks)
    {
        s_gate1s      = 0;
        s_countDown1s = num1sTicks;
        s_gate1s      = !0;
        while (s_countDown1s);
    }
    /* ------------------------------------------------
    */
    
    /* Timer.h
    */
    void delay10ms(U8 num10msTicks);
    void delay100ms(U8 num100msTicks);
    void delay1s(U8 num1sTicks);
    /* ------------------------------------------------
    */
    

    Regards,

    - Mark

  • In my timerIsr(), the count10ms function var. should be incremented before leaving the ISR and modulo'd with 100, thus allowing it to be a U8. Sorry.

    Also, for bonus points, in a real-time system why doesn't it help to do the 1s check inside the 100ms timing region?

    Why would this be desireable in a non-real-time system?

    - Mark

  • Hi Iain,

    you really shouldn't wait 30 seconds and let your processor do nothing else than waiting. That is a no-no for embedded applications.

    You should write an interrupt service routine for a timer (i.e. timer 0) that is invoked like every 10ms. The ISR should count down a volatile variable as long as it is not zero. And when you wait in your main loop, you can set that countdown variable at the beginning of your waiting periode and checking it in every loop for being zero. This way, you can determin the end of a waiting periode and do lotsa useful things while waiting.

    Take care
    Sven

  • you really shouldn't wait 30 seconds and let your processor do nothing else than waiting. That is a no-no for embedded applications.

    Not at all true. In low power applications it is very common to sleep for long periods of time waking up on interrupt to see if there is work to do. Remember, real-time only means you meet all your deadlines. It does not imply fast.

    If you truly need to do other processing while the ISR counts down a variable then you should use a task scheduler. Polling is usually a hack in this sort of situation.

    - Mark