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 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