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