keypad question

Discussion in 'Embedded Systems and Microcontrollers' started by conanav, Jun 15, 2008.

  1. conanav

    Thread Starter Member

    Jun 14, 2008

    I have written a program in mikroC that reads in keypad keys pressed and displays the value on the LCD. However, i have a question. How should i code it in order to allow the user to input let's say 2 digit numbers? As of right now, i have it coded in such way that each key on the 4x4 corresponds to either 0-9 or A-D however when the user presses 9 twice, I don't get 99, just the value 9 pressed twice.
  2. hgmjr


    Jan 28, 2005
    I think you are going to need to see your source code.

  3. conanav

    Thread Starter Member

    Jun 14, 2008
    I'm using the pre-existing libraries in mikroC for keypads and they seem to work when i program it.

    unsigned short kp, cnt, oldstate = 0;
    char txt[5];

    void main() {
    cnt = 0;
    Keypad_Init(&PORTC); // Initialize keypad on PORTC
    Lcd_Config(&PORTB, 4, 5, 6, 3, 2, 1, 0); // Lcd_Init_EP5
    Lcd_Cmd(LCD_CLEAR); // Clear display
    Lcd_Cmd(LCD_CURSOR_OFF); // Cursor off
    Lcd_Out(1, 1, "Key :");
    Lcd_Out(2, 1, "Times:");
    do {
    kp = 0;
    // Wait for key to be pressed
    //kp = Keypad_Released();
    kp = Keypad_Read();
    while (!kp);
    // Prepare value for output
    switch (kp) {

    case 1: kp = 49; break; // 1
    case 2: kp = 50; break; // 2
    case 3: kp = 51; break; // 3
    case 4: kp = 65; break; // A
    case 5: kp = 52; break; // 4
    case 6: kp = 53; break; // 5
    case 7: kp = 54; break; // 6
    case 8: kp = 66; break; // B
    case 9: kp = 55; break; // 7
    case 10: kp = 56; break; // 8
    case 11: kp = 57; break; // 9
    case 12: kp = 67; break; // C
    case 13: kp = 42; break; // *
    case 14: kp = 48; break; // 0
    case 15: kp = 35; break; // #
    case 16: kp = 68; break; // D
    if (kp != oldstate) {
    cnt = 1;
    oldstate = kp;
    asm nop;
    else {
    asm nop;
    // Print on LCD
    Lcd_Chr(1, 10, kp);
    if (cnt == 255) {
    cnt = 0;
    Lcd_Out(2, 10, " ");
    WordToStr(cnt, txt);
    Lcd_Out(2, 10, txt);
    } while (1);
  4. m.majid

    Active Member

    May 28, 2008
    your code prints appropriate character of pressed key, in ROW:1, COL:10 of lcd
    you should change your code to do following:
    print character of old key (oldstate) in ROW:1, COL:10 of lcd
    print character of current key (kp) in ROW:1, COL:11 of lcd

    so eliminate this code from your program:
    Lcd_Chr(1, 10, kp);

    and add these codes instead of eliminated code:
    Lcd_Chr(1, 10, oldstate);
    Lcd_Chr(1, 11, kp);

    and change the init value of oldstate to char '0' or 48 as following:
    unsigned short kp, cnt, oldstate = 48;
    Last edited: Jun 16, 2008
  5. conanav

    Thread Starter Member

    Jun 14, 2008
    Thank You that definately helps in terms of display but will it also do the trick in terms of actual input? If the user wants to enter 99 on the keypad, he has to press nine twice and with the oldstate function you mentioned, the lcd should properly display "99" but isnt the actual mathematic input going to be just "9" or the second digit?Is there a way i can convert the string("99") back to an integer.
  6. conanav

    Thread Starter Member

    Jun 14, 2008
    So I changed the code but now when the lcd outputs the same number twice: basically kp and oldstate have the same value even though the number of times a key is pressed = 1.
  7. m.majid

    Active Member

    May 28, 2008
    it is very easy,
    declare a variable to keep integer value, like this:
    int value = 0;

    calculate the integer value any where you need in following order:
    value = oldstate * 10 + kp;
  8. conanav

    Thread Starter Member

    Jun 14, 2008
    Thank You for your help guys, I finally got it to about where i want it to be in terms of the matrix input. I guess I have one last general question: What determines the size of the input? Is it the bit capacity of the microcontroller? Let's say i have a string that is "100000" when i convert it to an integer i need at least 17bits to hold that value(16-bits giving me 65536). Does this mean that if I want to simulate a calculator that can deal in millions i need a 32-bit microcontroller, or am I not looking at this correctly?
  9. bookman413

    New Member

    Jun 28, 2008
    Hi, even if it was a one-bit microcontroller, you could perform arithmetic on a 17-bit number.

    I haven't read the whole thread, so I don't know the details of the microprocessor, and to some extent I'm just thinking as I type, but I think this will help:

    The secret here is that data representation is different from data input per se-it's an abstraction that you create in your data storage design.

    If you want to have the capacity to use 17 bit arithmetic, one way to do it is to represent the data as 3-byte (24 bit) representations. So the digital number "1" will be represented as "00000000 00000000 00000001" (that's 3 bytes).

    That means you will probably want at least 9 total bytes of memory to allow you to perform an arithmetic operation :

    bytes 0-2 store input number one
    bytes 3-5 store input number two
    bytes 6-8 store the result of the calculation

    I'ts been a while since I've done this kind of program, but you could probably use the microprocessor stack to store these if you don't have RAM (it will certainly be faster than RAM ).

    so the logic could look like this:

    use your existing program logic to construct the number that is being entered, pushing each byte of the number's representation onto the stack as it is created
    if the keypad indicates an arithmetic operation has been entered (meaning plus, minus, or whatever), finish filling out the data representation. So if you've only had one number keypress and so filled only part of one byte that has been pushed on the stack, you need to push two more empty bytes onto the stack to finish the 3-byte representation of the number:

    for the number "1," the stack will then look like this:

    00000000-data byte 3 - #together these 3 make
    00000000 -data byte 2- #up an "artificial" 3-byte
    00000001-data byte 1- #number

    once you have pushed 3 bytes, stop taking number input and wait for the operator to select an operation.

    if the operator presses an arithmetic operation before 3 bytes have been entered, then "fill out" the data representation by pushing on the remaining placeholder bytes.

    Then, you take the operation and take that into account somehow. you could store the operation somewhere (even on the stack) but it would seem cleaner to have a separate subroutine for each operation.

    so if the person presses "add", you jump to that subroutine, which then takes the next 3 byte entry and performs a division once the next operation entry is made.

    00000000-data byte 3 - #together these 3 make
    00000000 -data byte 2- #up an "artificial" 3-byte
    00000001-data byte 1- #number

    skip to adding subroutine & take next 3-byte number: (let's say the number 5:

    then then the entire stack looks like this (top to bottom)

    00000000-data byte 6 - #together these 3 make
    00000000 -data byte 5- #up an "artificial" 3-byte
    00000101-data byte 4- #number--1
    00000000-data byte 3 - #together these 3 make
    00000000 -data byte 2- #up an "artificial" 3-byte
    00000001-data byte 1- #number--5

    the next stage is to add the numbers together and store the result.

    You'd have to pop them off the stack, so you'll have to keep in mind that in this example you'd need to add byte 6 to byte 4 and store the result as the leftmost byte of a 3-byte result. Then you add byte 5 and 2 together, and store that as the middle byte. then add 4 and 1 together and store the result as the rightmost byte. This could potentially be an unsolvable problem, depending on the microprocessor, and might mean you need to use RAM to store the data rather than the stack.

    All in all, this shows that storing the inputs in RAM would be a lot easier, because you can access RAM randomly and can just select the bytes that you want easily. If you are using the stack , you are limited by the number of registers you have available to store stuff that's coming off the stack.

    (like when you pop off the top (6th byte) from the stack, you need to pop off the 5th and 4th and save them somewhere as you pop off byte 3. )

    working with RAM, you can just store the data in sequential addresses in RAM, then later access each byte as you need it, and have a separate dedicated RAM area for the result.

    if you are doing division, you need to decide if you are going to go into floating point representations for the data, which I know next to nothing about.

    ok, I hope that helps. Maybe someone else who's more current can give a less abstract solution.

  10. loosewire

    AAC Fanatic!

    Apr 25, 2008
    The key board in a home computer does it have the ability to
    convert to programing digit's. Short explaination.