Creat easily Multiple non-blocking delays with 1 timer


This example shows you how to create multiple non-blocking delays with only one timer, using :
  • timer 1
  • interrupts
  • arrays of pointers to functions
  • structures
It is made for a P18F452 but it could be used with others pics with just minor adjustments.

/*
 * this source code shows how to use pic timers, interrupts, 
and arrays of pointers to functions
 * and how to make non-blocking multiples delays, using a single timer
 *
 * Bruno Gavand, march 2006
 * www.micro-examples.com
 *
 * P18F452 @8Mhz, HS clock, EASYPIC2 / EASYPIC3
 * pull-down on PORTB
 * pull-up on keyboard
 * enable PORTB, PORTC and PORTD LEDs
 *
 * pressing RB0 key will toggle PORTC after a 2s non-blocking delay
 * pressing RB1 key will toggle PORTD after a 3s non-blocking delay
 *
 * used ROM : 1676 bytes
 */

More click on title../*
 * number of delayed keys, up to 255
 */
#define NBKEYS  2

/*
 * struct for one key
 */
typedef struct
        {
        unsigned char   flag ;          // active = 1, 0 otherwise
        unsigned char   ctr ;           // counter of timer1 overflows
        void            (*stop)() ;     // pointer to a function to 
call after delay
        } KEY_STRUCT ;
        
KEY_STRUCT      keys[NBKEYS] ;          // struct array

/*
 * functions that do something visible for the example
 */
void    toggleC()
        {
        PORTC = ~PORTC ;        // invert PORTC (toggle LEDs)
        }

void    toggleD()
        {
        PORTD = ~PORTD ;        // invert PORTD (toggle LEDs)
        }

/*
 * start to count down d milliseconds for key i
 */
void    keyStart(unsigned char i, unsigned long d)
        {
        KEY_STRUCT *k ;
        
        k = &keys[i] ;                          // struct pointer
        if(k->flag == 0)                        // if free ?
                {
                d <<= 18 ;                      // multiply by 4 * 2 ^ 16
                d /= 1000 ;                     // divide by 1000 because
                d /= (long)Clock_Khz() ;        // clock frequency is known in Khz
                k->ctr = d ;                    // assign counter
                k->flag = 1 ;                   // set flag to start countdown in 
interrupt
                }
        }

/*
 * interrupt vector
 */
void    interrupt()
        {
        if(PIR1.TMR1IF)         // timer1 overflow, Fosc/(4 * 2^16)
times per second
                {
                unsigned char i ;
                
                for(i = 0 ; i < NBKEYS ; i++)   // for each keys
                        {
                        KEY_STRUCT      *k ;
                        
                        k = &keys[i] ;          // get pointer to the key struct
                        if(k->flag)             // if key countdown activated
                                {
                                if(k->ctr)      // if countdown in progress
                                        {
                                        k->ctr-- ;      // count down
                                        }
                                else
                                        {
                                        k->flag = 0 ;   // count down reached 0,
disable
                                        (k->stop)() ;   // call user's function
                                        }
                                }
                        }
                PIR1.TMR1IF = 0 ;               // reset timer1 interrupt flag
                }
        }

/*
 * program starts here
 */
void main()
        {
        unsigned char   i ;
        
        ADCON1 |= 0x07;                         //  PORTA as digital I/O
        PORTA = PORTB = PORTC = PORTD = 0 ;     //  clear ports
        TRISA = 0 ;                             // PORTA as output
TRISB = 0b00000011 ;                    // 2 LSB of PORTB as inputs, 
others as outputs
        TRISC = 0 ;                             // PORTC as output
        TRISD = 0 ;                             // PORTD as output

        keys[0].stop = toggleC ;                // assign user's function to 
first key
        keys[1].stop = toggleD ;                // assign user's function to
second key
        
        for(i = 0 ; i < NBKEYS ; i++)           // for each keys
                {
                keys[i].flag = 0 ;              // reset struct
                keys[i].ctr = 0 ;
                }
        
        T1CON.T1CKPS1 = 0 ;                     // no prescaler
        T1CON.T1CKPS0 = 0 ;                     // on timer1
        T1CON.T1OSCEN = 0 ;                     // disable timer1 oscillator
        T1CON.TMR1CS = 0 ;                      // timer1 is on Fosc
        T1CON.TMR1ON = 1 ;                      // start timer1

        INTCON.GIE = 1 ;                        // enable global interrupts
        INTCON.PEIE = 1 ;                       // enable peripheral interrupts

        PIE1.TMR1IE = 1 ;                       // enable timer1 overflow 
interrupts

        for(;;)                                 // forever
                {
                if(PORTB.F0)                    // if RB0 key pressed
                        {
                        keyStart(0, 2000) ;     // start key #0 countdown for 
2000 ms
                        }
                else if(PORTB.F1)               // if RB1 key pressed
                        {
                        keyStart(1, 3000) ;     // start key #1 countdown for 
3000 ms
                        }
                }
        }

0 comments:

Post a Comment

 

Free Download Engineering Books - IEEE Books | Copyright 2009-2013 All right reserved | Design by BMW Automobiles | Created by Umair Sheikh