MC13213 : Problem using KBI interrupt

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC13213 : Problem using KBI interrupt

4,946 Views
Spell
Contributor I
Hi,
I'm trying to use keyboard interrupt without success. I must count a number of pulse on PTA7 pin using interrupt routine.

This is my simply code:
Code:
KBI_Init(){  KBISC = 0x02;  // Interrupt enable, KBEDG7 falling edges  KBIPE = 0x80;  // Pin 7 enable}__interrupt void PulseDetected(){  KBISC = 0x04; // Interrupt disable, KBACK = 1  pulse++;  KBISC = 0x02; // re-enable interrupt}

 My problem is that after first interrupt the micro can't trigger another edge and don't call the interrupt routine anymore...
Anyone can help me?
thanks,
filippo

Labels (1)
0 Kudos
9 Replies

770 Views
hek
Contributor I
I have a similar problem.
I have some buttons that i want to decode using my S08QE128. Depending on how long the buttons are pushed different actions should be taken. I thought this would be a piece of cake, until i realized that KBI cant be set to trigger both rising and falling edge at the same time.
Fair enough, lets reconfigure the KBI after a falling edge to trigger on rising edge... but that doesnt work either! Am I doing something terribly wrong?

This is what i do:
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */ void KBIInit(void); void main(void) {   SOPT1 = 0x07;  EnableInterrupts;  /* enable interrupts */  KBIInit();  PTEDD = 0xFF;      // Set leds to output   for(;;) {  } /* loop forever */} void KBIInit(void){  KBI2SC_KBIE = 0;   // Clear mask to prevent false interrupts  KBI2ES = 0x00;     // Detect falling edge  KBI2PE = 0xF0;     // Enable keyboard interrupt on pins  PTDPE = 0xF0;      // Internal pull up  KBI2SC_KBACK = 1;  // Clear any false interrupts  KBI2SC_KBIE = 1;   // Enable Keyboard interrupt request   } void interrupt VectorNumber_Vkeyboard KBI_ISR(void){  KBI2SC_KBACK = 1;  // Clear interrupt flag  KBI2ES = 0xF0;     // Enable rising edge detect  PTETOG = 0xFF;     // Toggle Port E   KBI2SC_KBACK = 1;  // Clear any false interrupt }

Can you see any obvious problem?

Best regards
Henrik
 

0 Kudos

770 Views
bigmac
Specialist III
Hello Henrik,
 
Firstly, I think your initialisation code should explicitly clear the KBIMOD bit, for edge sensitivity only.  Initially writing all bits to KBI2SC, rather than a succession of individual bits, would be preferred.
 
To avoid the problem that fjrg76 has outlined, one solution may be to do the following:
  1. Initially all required KBI pins would be enabled, and an interrupt will occur for the first key pressed.
  2. Within the ISR, determine which pin is active, and disable all other pins.  Then setup a timing delay of say 50 ms to allow for key debounce.  Finally disable KBI interrupt, clear the flag and exit.
  3. When the debounce timeout has expired (as determined by interrupt or polling), test that the key is still active, and if so set KBI module for rising edge next, clear the KBI flag, and re-enable the KBI interrupt.  If the key is not still active, return to the initial state with all required KBI pins enabled.
  4. When the next interrupt occurs for the positive edge, determine the delay since the first interrupt, and restore the initial state with all required KBI pins enabled for negative edge.  Just in case there is any bounce on key release, perhaps the re-enabling of interrupts should be delayed, as for the key press situation.
This method does not allow the detection of any other key press, once the first key has been detected, and until this key has been released.  On the other hand, it also means that no other key can interfere with the key release detection.
 
Of course, this does not explain Filippo's original problem with only a single input pin at PTA7.
 
Regards,
Mac
 
0 Kudos

770 Views
hek
Contributor I
Thank you guys for your responses!!

First of all. The KBI will only be used to determine buttons, and i wont permit more then one button at a time, so what fjrg76 mentioned about KBIs behaviour doesnt really matter (good info though! :smileyhappy:).

My biggest problem here is that I cant detect ANY interrupt on rising egde. Even if I just change
Code:
KBI2ES = 0x00; // Detect falling edge
to
Code:
KBI2ES = 0xF0; // Detect rising edge
 in the KBIInit and just listens after the first interrupt (on release of the first key press)

I suspect something about pull-ups/pull-downs, but im not sure how. The reference manual says that when edge select is set to 1 for a pin, "A pull-down device is connected to to the associated pin and detects rising edge...". In that case, should internal pull-up be enabled?? Since there is no external pull-up/pull-down, that will leave the pin floating...

The hardware im talking about is the EVBQE128 Starter Kit.
0 Kudos

770 Views
bigmac
Specialist III
Hello Henrik,
 
For the MCU you are using, check whether pull-ups are automatically enabled when a KBI input is selected (for negative edge).  Also clarify whether the pull-up gets converted to a pull-down, when positive edge is selected, as seems to be your case.  I seem to recall that the KBI module for some MCUs did behave in this manner.
 
If the second condition is applicable, you will need to use external pull-up resistors.  If the internal pull-up/pull-down cannot be disabled, the external pull-up will need to be of sufficiently low resistance to over-ride the internal pull-down current.
 
Unless you have implemented key debounce delay, it may also be possible for the ISR to execute multiple times for each key press, and possibly also for the key release.  This may produce confusing results.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-02-21 12:56 AM
0 Kudos

770 Views
JimDon
Senior Contributor III
"First of all. The KBI will only be used to determine buttons" - Determine what about the buttons?
"and i wont permit more then one button at a time" - And you will enforce this how?

As for the pull up situation, write a quick routine that reads the input bit - is it 1 when not pushed?
Is it 0 when pushed?

You see, to use the interrupts to de bounce the switches, you will need a timer with a counter to determine the time between interrupts. So while you are at it, just do it on the timer interrupt using the counter that you will need anyway.

If you need to wake the processor on a key push fine, but other than that you need to poll the switches.

0 Kudos

770 Views
fjrg76
Contributor IV
Hi!!
 
Your code seems to be ok, however you must be aware the way the KBI works. The KBI module will NOT assert a new interrupt request until there are no pins on active state!! That was a nightmare first time I faced it.
 
For example, suppose you have two pins for requesting an interrupt, A0 and A1, on falling edges only. On normal state A0 and A1 are at high level. When A0 goes to low level then an interrupt request asserts, and you service it, and then, while A0 is still at low level, A1 asserts (e.g. going to low level). This last request won't be serviced!! :smileysad: In order for a new request to be serviced ALL kbi pins MUST be on inactive state, e.g. all must be at high level before a new request interrupt must be asserted. Awesome!! :smileyhappy:
 
Please verify that your applications is not doing what I said. If so, you may look for alternatives, e.g. using the IRQ interrupt, and  the input capture timer pins as well. I remember I tried to disable a pin like KBI interrupt in order to assert other request for other pin, but that didn't work for me ( I intended to do a quadrature decoder), but you can try it.
 
By the way, for the original user that posted this thread: if you only want to count pulses you may use the IRQ pin or the input capture timer pin, it will be easier and cleaner.
0 Kudos

770 Views
JimDon
Senior Contributor III
Polling on say the RTI, 1-10 ms will work just fine for buttons.
It does not take up much time, and is not a problem.
Noisy inputs , like key bounce, do not do well with edge interrupts.
Timed interrupts give you a good way to filter as well.

0 Kudos

770 Views
tonyp
Senior Contributor II

Spell wrote:
__interrupt void PulseDetected(){  KBISC = 0x04; // Interrupt disable, KBACK = 1  pulse++;  KBISC = 0x02; // re-enable interrupt}
 My problem is that after first interrupt the micro can't trigger another edge and don't call the interrupt routine anymore...

(To better meet the specs, try to either initialize or acknowledge with this statement: KBISC = 0x06:smileywink:

Are you using external or enabling internal pullups?


Message Edited by tonyp on 2008-02-19 01:04 PM
0 Kudos

770 Views
fjrg76
Contributor IV
Hi

 Adapt this code to your needs and try it!!

void kbInit(void){
    PTADD&=0xF0;        /* set direction */
    PTAPE|=0x0F;        /* enable pull-ups */
    
    KBISC_KBACK=1;   /* for avoiding false trigering */
    KBIPE|=0x0F;         /* enable as interrupt source in those pins */
    KBIES&=0xF0;      /* set edge/level */
    KBISC_KBIE=1;      /* enable KBI interrupt */
}

interrupt 18 void kbISR(void){
    KBISC_KBACK=1;
   
    /* your code here*/
}
0 Kudos