|
发表于 2010-1-10 21:30:04
|
显示全部楼层
here is an example of how it can be done with a mcu (12F675, 8pdip).
the basic thought process is to use a timer to count the time since the last time a switch has been pressed. Once that timer has reached a preset limit, you flip an output pin.
the detection of switch is done via a polling method. But you can switch it to interrupt as well.
All done in < 30 minutes, taken less than 10% of the resources on a 12F675 (less than a dollar each, and likely cheaper in China).
here is the code. CNT controls how long the delay is. since we are setting the prescaler to 256:1, the timer offset to 55. With the mcu running at 4Mhz, the 8-bit timer trips once every 256*(256-55)=50ms. with CNT at 40, that means the output pin (GPIO4) will flip once every 40*50ms=2s, which the simulation confirms.
=============code=================
#include <htc.h>
#define SW (1<<3) //GPIO3 as switch
#define PORT GPIO //switch on gpio port. for portability
#define OP (1<<4) //output pin on Gpio4
#define CNT 40 //timer0 interrupt count required to achieve desire time delay.
#define T0_Offset 55 //Timer0 offset. timer0 interrupts once every 256us*(256-55)
#define T0_Scaler 0b111 //timer0 prescaler at 0b111 = 256:1
#define IO_SET(x) PORT |= (x) //set xth bit on port
#define IO_CLR(x) PORT &=~(x) //clear xth bit on port
#define IO_FLP(x) PORT ^= (x) //flip xth bit on port
unsigned long T0_Cnt; //timer0 count
__CONFIG(MCLRDIS & BORDIS & WDTDIS & PWRTEN & INTIO);
void interrupt ISR(void) {
if (T0IE & T0IF) { //timer0 has triggered an interrupt
T0IF=0; //clear timer0 interrupt flag
TMR0+=T0_Offset; //load up the timer0 offset
T0_Cnt++; //advance T0_Cnt by 1
}
}
void mcu_init(void) {
ANSEL=0x00; //all ports digital
CMCON=0x07; //all analog comparators off
TRISIO |= SW; //SW pin as input;
TRISIO &= ~OP; //output pin as output;
// GPPU=0; WPU |= SW; //turn on week pull-up
T0CS=0; //timer0 using internal clock
PSA=0; //prescaller assigned to timer0
PS2=(T0_Scaler & 0b100)>>2; //set up Ps2
PS1=(T0_Scaler & 0b010)>>1; //set up Ps1
PS0=(T0_Scaler & 0b001)>>0; //set up Ps0
GIE=1; //turn on global interrupt
T0IE=0; //timer0 interrupt NOT enabled yet
T0_Cnt=0; //initialize T0_Cnt
}
void main(void)
{
mcu_init();
while (1){
//TODO Auto-generated main function
if (T0_Cnt > CNT) { //SW_Cnt cycles elapsed since the last key pressed
T0IE=0; //timer0 interrupt disabled
T0_Cnt=0; //reset T0_Cnt
IO_FLP(OP); //flip the OP pin
}
if (PORT & SW) { //SW pressed
T0_Cnt=0; //initialize T0_Cnt
TMR0=T0_Offset; //load up the timer0 offset
T0IE=1; //enable the timer
}
}
}
(原文件名:12F675 SW debouncing.PNG)
the code is written for picc 9.x, I think. |
|