Andre, I wrote some code to show how the wake-up can be done by the CNI and the scanning by a timer interrupt. The code compiles but there are lots of TODOs: /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ #include /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ int InactivityTimeOut =3D 0; /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ void __attribute__((interrupt,auto_psv)) _CNInterrupt( void ) { /* Clear the CNI interrupt flag to avoid recursive interrupts */ IFS1bits.CNIF =3D 0; /* Disable the CNI interrupt so we don't get a flood of interrupts due to contact bounces */ IEC1bits.CNIE =3D 0; } /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ void __attribute__((interrupt,auto_psv)) _T1Interrupt( void ) { /* Clear the TMR1 interrupt flag to avoid recursive interrupts */ IFS0bits.T1IF =3D 0; /* TODO: Scan the keypad */ } /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ void WaitForKeypress( void ) { /* Clear the CNI interrupt flag so we don't get a spurious wake-up */ IFS1bits.CNIF =3D 0; /* Enable the CNI interrupt so it can wake-up the processor */ IEC1bits.CNIE =3D 1; /* Enter sleep mode */ Sleep(); } /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ int main( void ) { /* TODO: Initializa the hardware */ while( 1 ) { ClrWdt(); if( InactivityTimeOut ) WaitForKeypress(); /* Do something */ } } /*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D*/ Em 6/10/2011 17:41, Andre Abelian escreveu: > Isaac, > > > thanks for your replay. > > keypad is the only connection for CNI interrupt. I can assign columns ins= tead of raws then > in this case it will create interrupt every 1.5 ms that's how fast the ke= ypad is running. the only > reason I wanted to use CNI is to save battery. this project is portable u= ses 2xAA battery with boost. > I can setup other timer to call the routine 20 times in 1 second but firs= t I want to see if we can fix > what I have. > > thanks > AA > > > ________________________________ > From: Isaac Marino Bavaresco > To: Microcontroller discussion list - Public. > Sent: Thursday, October 6, 2011 1:08 PM > Subject: Re: [PIC]: keypad debounce issue > > Em 6/10/2011 16:33, Andre Abelian escreveu: >> Isaac, >> >> >> port change interrupt is like once after key is pressed. > > Perhaps in an ideal world, not in ours. Remember that > interrupt-on-change may be fouled by reading the port exactly at the > same time of the keypress, so beware if you use the same port for other > uses. > > >> the only time it creates more interrupt when bounces. > > Did you ever watch a key press/release on an oscilloscope? Some switches > produce a "shower of pulses" on the line for several (tens of) ms, many > of them would be able to trigger an interrupt. > > >> I can put caps but what value do you suggest? > > It all depends on the characteristics of the switch, and it is good to > add some resistance also. > I don't suggest this approach, because I don't like to add unnecessary > parts to a circuit, and on value may not be good for all instances. I > would suggest you to stop using the interrupt-on-change and use a timed > scan of the keypad. > If you need the interrupt to wake-up the processor, then OK, use it only > for the first press so the CPU is awaken but disable the interrupt > inside the ISR and afterwards use the timed scan. > > > Best regards, > > Isaac > >> thanks >> >> Andre >> >> >> ________________________________ >> From: Isaac Marino Bavaresco >> To: Microcontroller discussion list - Public. >> Sent: Thursday, October 6, 2011 11:22 AM >> Subject: Re: [PIC]: keypad debounce issue >> >> I don't like to use interrupts for key scanning exactly because of >> bouncing. It would be safe only if you put some (electronic) low pass >> filtering in the lines. >> It is much simpler to use a timer interrupt to scan the keypad >> periodically, and if your scan rate is appropriate you don't need any >> debouncing at all. >> >> I usually scan 20 times per second. It uses minimal CPU time and is fast >> enough even for very fast typing. >> >> Remember that if you use interrupts, the interrupt rate may be several >> kHz for some ms. That's a lot of processing and interrupt servicing. >> >> I often use a software prescaler in my system tick's interrupt to call >> the scanning routine at an appropriate rate. >> >> >> Best regards, >> >> Isaac >> >> >> >> Em 6/10/2011 14:57, Andre Abelian escreveu: >>> Hi all, >>> >>> I am reading a keypad that is connected to other board. I am using PIC2= 4FJ256GB110 >>> with CCS PICC compiler. I am using CNI interrupt "port on change" and c= onnetced to all 4 rows. >>> any time any row goes low it create interrupt but also when it goes hig= h creates interrupt too. >>> the problem I am having is that I am getting duplicated key "debounce i= ssue". Normally >>> I used a counter to deal with debouning or adding a delay. Since CNI in= terrupt is not looping >>> is like one time shot unless there is a port change using a counter is = not working. I also have option >>> using columns but this will create interrupt every 1.5 ms none stop. us= ing rows will create interupt >>> only when keys are pushed. >>> >>> any idea? or suggestions will appreciate >>> here is the code. >>> >>> >>> // Keypad layout: >>> char const KEYS[4][4] =3D >>> {{'1','2','3','A'}, >>> {'4','5','6','B'}, >>> {'7','8','9','C'}, >>> {'*','0','#','D'}}; >>> >>> // check all rows and return 1 when pushed else return 0 >>> int1 ALL_ROWS(void) >>> { >>> if((input(row0)) & (input(row1)) & (input(row2)) & (input(row3))) // i= f any of them pushed return 1 >>> { >>> return (0); >>> } >>> else >>> { >>> return (1); >>> } >>> } >>> >>> >>> >>> >>> // read keypad but from other board. keypad is connected to other PCB >>> #int_cni //level=3D7 >>> void keypad_interrupt() >>> { >>> //int32 prg_counter=3D0,data_prg=3D0,read_index_counter[3]; // al= l this is for other routine that is removed for now >>> restart_wdt(); >>> >>> delay_ms(5); // for debounce purpose >>> >>> if((ALL_ROWS())&&(system_keypad_send_once =3D=3D 1)) // any o= f 4 inputs are pressed? row0 & row1 & row2 & row3 >>> { >>> redled_on; >>> // col0 1,4,7,* >>> if((!input(row0))&&(!input(col0))) >>> { >>> row=3D0; col=3D0; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> if((!input(row1))&&(!input(col0))) >>> { >>> row=3D1; col=3D0; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> if((!input(row2))&&(!input(col0))) >>> { >>> row=3D2; col=3D0; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> if((!input(row3))&&(!input(col0))) >>> { >>> row=3D3; col=3D0; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> >>> // col1 2,5,8,0 >>> if((!input(row0))&&(!input(col1))) >>> { >>> row=3D0; col=3D1; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row1))&&(!input(col1))) >>> { >>> row=3D1; col=3D1; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row2))&&(!input(col1))) >>> { >>> row=3D2; col=3D1; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row3))&&(!input(col1))) >>> { >>> row=3D3; col=3D1; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> // col2 3,6,9,# >>> if((!input(row0))&&(!input(col2))) >>> { >>> row=3D0; col=3D2; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row1))&&(!input(col2))) >>> { >>> row=3D1; col=3D2; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row2))&&(!input(col2))) >>> { >>> row=3D2; col=3D2; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> >>> if((!input(row3))&&(!input(col2))) >>> { >>> row=3D3; col=3D2; >>> kbd_down =3D true; >>> key_pressed =3DKEYS[row][col]; >>> system_keypad_send_once =3D 0; >>> } >>> fprintf(ZBEE,"%c", key_pressed); // print for test norm= ally not used >>> >>> } >>> else >>> { >>> redled_off; >>> kbd_down =3D false; // >>> system_keypad_send_once =3D 1; >>> } >>> >>> >>> thanks >>> >>> Andre -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .