Forums

Keyboard Interrupt

Started by eneloop May 4, 2011
Hello, my name is Sammy. 

I try to write an interrupt service routine for the keyboard interrupt.
I'm using a Motorola 68HC08 and freescale's Codewarrior.
Port A is connected with a button. Port B is connected with LED. 
If I push the button, LED should switch on. If I push it again LED should
switch off.
I'm very unexperienced with C and don't know how to do this. 



#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

void KBI_init(void) 
{
  /* This procedure is to prevent False Interrupts at initialisation*/
      KBSCR_IMASKK = 1;     /* Mask Keyboard interrupts */
      KBIER_KBIE2 = 1;      /* Enables pin2 of KBI by setting KBIE2(PTA2)
*/
      KBSCR_ACKK = 1;       /* Clear any false interrupts */
      KBSCR_IMASKK = 0;     /* Unmask Keyboard interrupts */
      
  /* END Avoidance of False Interrupts */
                            /* Configures KBI Status & Control Register */
      KBSCR = 0;            /* IMASKK=0: Clears KBI Mask Bit (Enable Ints)
*/
                            /* MODEK=0: Interrupt requests on Falling Edge
Only */
}

interrupt 15 void _KB_Interrupt (void) 
{
  KBSCR_ACKK = 1;            /* Acknowledge KB Interrupts */
  PTA_PTA1 = ~PTA_PTA1;      /* Toggles the LED */
}


// IO_Ports
int delay = 5000;

static void Delay(void) {
  int cnt = 0;
  while (cnt <delay) {
    __RESET_WATCHDOG();  /* feeds the dog */
    cnt++;
  }
}

static void LED(void) {
  unsigned char i;
    for (i = 1; i > 0; i<<=1) {
      PTB = i;          
      Delay();  
    }
}

// Main
void main(void) {
  EnableInterrupts; /* enable interrupts */

  DDRB = 0xFF;      // Data Direction Register Port B
             
  while(1) {
       LED();
       for(;;){
           LED();
       }
  }

  /* please make sure that you never leave this function */
}


Thanks in advance
Sammy

	   
					
---------------------------------------		
Posted through http://www.EmbeddedRelated.com
On 4.5.11 9:13 , eneloop wrote:
> Hello, my name is Sammy. > > I try to write an interrupt service routine for the keyboard interrupt. > I'm using a Motorola 68HC08 and freescale's Codewarrior. > Port A is connected with a button. Port B is connected with LED. > If I push the button, LED should switch on. If I push it again LED should > switch off. > I'm very unexperienced with C and don't know how to do this.
A button does not switch cleanly, if there are no special measures to handle a thing called contact bounce: The contacts close and open several times in the time scale of some milliseconds. The exact number and timing depends on the mechanical structure of the button and how it is pushed. Due to the bounce, you will get a burst of very quick pushes. -- Tauno Voipio
On 05/04/2011 11:13 AM, eneloop wrote:
> Hello, my name is Sammy. > > I try to write an interrupt service routine for the keyboard interrupt. > I'm using a Motorola 68HC08 and freescale's Codewarrior. > Port A is connected with a button. Port B is connected with LED. > If I push the button, LED should switch on. If I push it again LED should > switch off. > I'm very unexperienced with C and don't know how to do this. > > > > #include<hidef.h> /* for EnableInterrupts macro */ > #include "derivative.h" /* include peripheral declarations */ > > void KBI_init(void) > { > /* This procedure is to prevent False Interrupts at initialisation*/ > KBSCR_IMASKK = 1; /* Mask Keyboard interrupts */ > KBIER_KBIE2 = 1; /* Enables pin2 of KBI by setting KBIE2(PTA2) > */ > KBSCR_ACKK = 1; /* Clear any false interrupts */ > KBSCR_IMASKK = 0; /* Unmask Keyboard interrupts */ > > /* END Avoidance of False Interrupts */ > /* Configures KBI Status& Control Register */ > KBSCR = 0; /* IMASKK=0: Clears KBI Mask Bit (Enable Ints) > */ > /* MODEK=0: Interrupt requests on Falling Edge > Only */ > } > > interrupt 15 void _KB_Interrupt (void) > { > KBSCR_ACKK = 1; /* Acknowledge KB Interrupts */ > PTA_PTA1 = ~PTA_PTA1; /* Toggles the LED */ > } > > > // IO_Ports > int delay = 5000; > > static void Delay(void) { > int cnt = 0; > while (cnt<delay) { > __RESET_WATCHDOG(); /* feeds the dog */ > cnt++; > } > } > > static void LED(void) { > unsigned char i; > for (i = 1; i> 0; i<<=1) { > PTB = i; > Delay(); > } > } > > // Main > void main(void) { > EnableInterrupts; /* enable interrupts */ > > DDRB = 0xFF; // Data Direction Register Port B > > while(1) { > LED(); > for(;;){ > LED(); > } > } > > /* please make sure that you never leave this function */ > } > > > Thanks in advance > Sammy > > > > --------------------------------------- > Posted through http://www.EmbeddedRelated.com
So, what's actually happening? What else have you done? This looks good on the surface, except that you have done nothing to debounce the switch. If you push the button and the light sometimes changes and sometimes doesn't, then you need debounce. You're depending on getting too many things right all at once. One of the characteristics of this sort of task is that you've got all sorts of things that have to be set up correctly, and sometimes the documentation is only clear after the fact. You want to try to separate the problem into small bits and get each little bit working before you move on to the next. In your case, you're trying to do three things: light an LED when you want to, read the state of a button, and make interrupts work. I _strongly suggest_ that you do those three things _separately_ in precisely the order I'm giving: first, try to make the LED blink under software control in the main loop -- don't mess with interrupts, or buttons: just do this with a delay loop. Then, make the LED follow the button (i.e., button down = LED on, button up = LED off). If you want to be fancy change the blink rate with the button -- but don't do anything in your code other then checking the button bit. Finally, when you've gotten all that working and verified, _then_ do the last increment and make it work with interrupts. Note that in a real system things like button presses are often better monitored in a task that repeats every 10ms or faster. You're not getting an interrupt every time the switch bounces, you're not trying to debounce things in interrupt space, you're not consuming lots of interrupt time reacting to a human pushing a button, etc. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" was written for you. See details at http://www.wescottdesign.com/actfes/actfes.html
On Wed, 04 May 2011 13:13:34 -0500, "eneloop"
<eneloop1@n_o_s_p_a_m.gmx.de> wrote:

>Hello, my name is Sammy. > >I try to write an interrupt service routine for the keyboard interrupt. >I'm using a Motorola 68HC08 and freescale's Codewarrior. >Port A is connected with a button. Port B is connected with LED. >If I push the button, LED should switch on. If I push it again LED should >switch off. >I'm very unexperienced with C and don't know how to do this.
[snippety snip] Without wading through the Moto-specific registers (haven't touched one of those since Noah was a seaman) you might want to consider a couple of things. Firstly, one very, very rarely wants to tie an external interrupt line directly to a mechanical switch. Switches (and buttons and relays etc.) bounce multiple times before they reach steady-state, causing multiple interrupts, which is probably not the desired behavior. For switches operating at "human speed" a response that occurs in less than, say, 100 msec should be perceived as instantaneous. One approach (there are many; do a 'net search on "switch debouncing") is to have your program run a system tick that fires every 10 msec or so. When it fires, poll the state of the switch. If the switch has changed state since it was last stable *and* if it has been stable in the new state for at least one polling interval, then declare that the switch has "switched" and handle it appropriately. The program should still toggle the port A bit as is, it just may do so a lot of times... Other observations: You've got two infinite loops in main(); you'll never leave the inner (for(;;)) loop. If setting DDRB to 0xFF is needed to configure the port as an output (told you it's been forever since I looked at one of these chips), don't you also need to set the bit for the LED attached to port A? It looks like you intend to see a "walking bit" on the LEDs (plural) attached to port B and a toggle of the one LED on port A. True? -- Rich Webb Norfolk, VA