Help controlling a flashing LED through a 3x4 keypad

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys,

This is probably a pretty newbie question, but I can't for the life of me figure out whats going wrong.

I'm trying to control the flashing of the leds on the STK500 through a 3x4 keypad. Basically, the user presses a key between 0 to 7 to select which led to flash, followed by the # key. Then, they press another key between 1 and 8 to decide the period of the flashing led (in seconds). This period is controlled through Timer 1 overflow interrupt. The ATMega16 is being used with its internal 1MHz oscillator.

So say for example I pressed 2, #, 1, #; this would select led02 on the stk500 to flash on-and-off once a second.

For some reason after I enter my first number and press the hash key, the led selected starts flashing automatically, before I enter the period and before interrupts have even been enabled, which I cannot understand why. Can anyone think of why it is doing this? It is probably something really simple :roll:

Here is my code.

// Global variables
volatile unsigned char led;
volatile unsigned int overflow_limit;
volatile unsigned int overflow_count = 0;

ISR(TIMER1_OVF_vect)
{
	overflow_count++;
	if(overflow_count >= overflow_limit)
	{
		PORTB ^= (1<<led);
		overflow_count = 0;
	}
}

int main(void)
{
	unsigned char key = 0;
	unsigned char delay = 0;

	// Port B for LED output
	DDRB = 0xFF;
	PORTB = 0xFF;

	TCCR1B |= (1<<CS10);	// Set the prescaler = 1
	TIMSK |= (1<<TOIE1);	// Enable the Timer1 overflow interrupt

	for(;;)
	{
		// Read the keypad until # is pressed. This gets the LED to flash
		do
		{
			key = read_keypad();
			if(key >= '0' && key <= '7')
				led = key - '0';
		}while(key != '#');

		// Read the keypad until # is pressed. This gets the time to flash the LED
		do
		{
			key = read_keypad();
			if(key >= '1' && key <= '8')
				delay = key - '0';
		}while(key != '#');

		overflow_limit = (unsigned int)(delay*1000000UL/65536UL);

		sei();
	}
}

// Function to read the 4x3 keypad and return the ASCII code
unsigned char read_keypad(void)
{
	unsigned char key;            // key press
	unsigned char porta_value;    // to store input value port A
	
	// Array to make scanning the keypad more efficient
	unsigned char keypad_col_bit[3] = {6, 5, 4};
	unsigned char keypad_row_bit[4] = {3, 2, 1, 0};
	unsigned char keypad_key[3][4] = {{'1', '4', '7', '*'}, 
	                                  {'2', '5', '8', '0'},
							  		  {'3', '6', '9', '#'}};
	unsigned char col; // column on keypad 1, 2, 3
	unsigned char row; // row on keypad 1, 2, 3, 4

    // Configure port A
	DDRA = 0b11110000; // PORTA pins 0-3 for input and pins 4-7 for output

	/* Scan the keypad to find which key has been pressed */
	key = 0;
	for (col = 1; col <= 3; col++){
		
		// Send binary ZERO to corresponding port A pin for the column
		PORTA = ~(1 << (keypad_col_bit[col-1]));

		// Create a short delay
		asm volatile("nop");
		asm volatile("nop");

        // Read back from port A
		porta_value = PINA;
        
		for (row = 1; row <= 4; row ++){
		    // Check corresponding port A pin for the row
			if ((porta_value & (1 << (keypad_row_bit[row-1]))) ==0)
				key = keypad_key[col-1][row-1];	
		}
	}
	return key;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First thing I would try is a key read loop in between the existing key read loops to make sure '#' is released before going to read the delay.

David.

edit: Also, do you have any kind of debounce on the keypad?