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
/* * 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 outputTRISB = 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 tosecond 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