HC11 keyboard scanning routine HELP!

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

HC11 keyboard scanning routine HELP!

1,998 Views
mreister
Contributor I

I am tring to write a keyboard scanning routine for a 4x4 keypad in C for my FOX11 HC11 trainer board. I am trying to detect when the values on PORTE and PORTD out changed and process the change accourdingly. The I/O map for the keyboard is shown below.

Pin 2 PD2 connects COL0 of the keypad

Pin 3 PD3 connects COL1 of the keypad

Pin 4 PD4 connects COL2 of the keypad

Pin 5 PD5 connects COL3 of the keypad

Pin 6 PE0 connects ROW0 of the keypad

Pin 7 PE1 connects ROW1 of the keypad

Pin 8 PE2 connects ROW2 of the keypad

 

I have used a default asm program given by the manufacturer to verify that the keyboard physically works. My code is shown below:

/* sample program of mixed C code and asm code */

#include <hc11.h>

#define LED (*(volatile unsigned char*)0x1404)

 

typedef void (*fnptr)();

#define lcd_ini ((fnptr)0x80f)

 

void lcd_line1(char, char*);

void lcd_line2(char, char*);

 

int main()

{

    char characterEntered[] = "Key entered  ";

   

    // set up the registers

    PORTD = 0xFF;

    DDRD  = 0xFE;

   

    while(1)

    {

        if((PORTE != 0x8F) || (PORTD != 0x3F))

        {

             lcd_line1(11, characterEntered);

             delay1ms(10000);

             lcd_ini();

        }

    }

 

    return 0;

}

 

 

When the value on the pins PD2-PD5 and PE0-PE3 change isn’t the change suppose to be reflected in a change in PORTE and PORTD? If so why aren’t the values of PD or PE changed from their default values 0x8F and 0x3F? Even if I try to assign a new value to PORTE or PORTD they do not change?

Labels (1)
0 Kudos
4 Replies

393 Views
mreister
Contributor I
Thank you both for your replies. I had just figured it out about an hour after i posted, but your solutions seems to be more effcient than mine. Thank you very much. I am new!
0 Kudos

393 Views
bigmac
Specialist III
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 -
  1. Set all columns active - if the row inputs all remain high, no key is pressed.
  2. If a keypress is sensed, it is usual to allow a switch debounce period, say 50-100 milliseconds.
  3. 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.
  4. The combination of column and row associated with the keypress, will then need to be translated to a character value for display.
  5. 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 AM

Message Edited by bigmac on 2008-04-07 12:42 AM
0 Kudos

393 Views
JimDon
Senior Contributor III
The nice thing about the code I pointed you to is that it uses a table to decode the keys, so in the case of the dragon12 you can plug the key board in with way and rearrange the table to decode.
This table give you a hex value, 0-f, the routine also detects double key presses, and has de-bounce built into it.



Code:
#ifndef INV_KEYPADbyte _kbdecoder[4][4]={{0xf,0xb,0x7,0x3},{0xe,0xa,0x6,0x2},{0xd,0x9,0x5,0x1},{0xc,0x8,0x4,0x0},};#else  // Use this for dragon12-Plusconst byte _kbdecoder[4][4]={{0xd,0xc,0xb,0xa},{0xe,0x9,0x6,0x3},{0x0,0x8,0x5,0x2},{0xf,0x7,0x4,0x1},};#endif

 

0 Kudos

393 Views
JimDon
Senior Contributor III
This is sample code to scan the keyboard on a dragon12. It should give you an idea how might you might do this in "C".



http://www.evbplus.com/download_hcs12/Dragon12_CW_TestC_1_1.zip
0 Kudos