Hello,
Can I assume that the low nybble of PORTE is set as inputs, and you have either internal pullups enabled, or alternatively external pullups? If so, the active state for each column output should be low, so that when a key is pressed, one of the PORTE inputs will also be driven low.
I would strongly recommend that, when a column becomes inactive, that you set the column as an input (high-Z) state. This will avoid potential conflict between two outputs, should two keys in different columns be simultaneously pressed.
The procedure to read a keypress would then be -
- Set all columns active - if the row inputs all remain high, no key is pressed.
- If a keypress is sensed, it is usual to allow a switch debounce period, say 50-100 milliseconds.
- At the conclusion of the debounce period, the keypress will then need to be identified by activating a single column at a time, until the actual keypress is found.
- The combination of column and row associated with the keypress, will then need to be translated to a character value for display.
- You might then choose to wait until all keys are released, before allowing detection of another keypress.
Here is some untested code -
#define COLMASK 0x3C /* PD2-PD5 */
#define ROWMASK 0x0F /* PE0-PE3 */
/* Key translation table */
const byte keytable[] = {
"147*2580369#ABCD"
};
void main( void)
{
byte col, val;
...
...
while (1) {
PORTD &= ~COLMASK; /* Set all columns active low */
DDRD |= COLMASK; /* Set all columns to output */
if ((PORTE & ROWMASK) != ROWMASK) { /* Test for a keypress */
delay1ms(50); /* Delay 50ms debounce */
/* Scan individual columns */
for (col = 0; col < 4; col++) {
val = scan_col( col);
if (val)
break;
}
/* Display keypress value here */
DDRD |= COLMASK; /* Set all columns to output */
while ((PORTE & ROWMASK) != ROWMASK); /* Wait for key release */ delay1ms(50); /* Just in case there is key release bounce */
}
...
...
}
}
byte scan_col( byte column)
{
byte key, i;
column &= 0x03; /* Ensure range 0-3 */
DDRD &= ~COLMASK; /* Set all colunmns inactive (high-Z) */
DDRD |= (0x04 << column); /* Set specified column active low */
key = ~PORTE & ROWMASK; /* Mask inverted row status */
if (key == 0)
return 0; /* No keypress in column */
i = 0;
while ((key >> 1) != 0)
i++;
return (key_table[column*4 + i]);
}
Regards,
Mac
Message Edited by bigmac on
2008-04-07 12:37 AMMessage Edited by bigmac on
2008-04-07 12:42 AM