This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

KEY PAD INTERFACING WITH I/O EXPANDER

Other Parts Discussed in Thread: TCA6408A

Hi,

i am trying to interface key pad to my evalution board which has a i/o expander. am using i/o expander(TCA6408a) pins to interface. i/o expander has a interrupt pin which is connected to pin number 11 of the controller lx4f232.... now my doubt is how to generate and handle interrupts. do not mind if this doubt silly.

thanku

chethan kumar 

  • Hi,

    How many keys has your keypad? be prepared to implement/use keys scanning to read a real keypad - all does that - this is because you need to debounce keys first. Scanning is done by arranging keys at the intersections of rows and columns - so some pins of the expander should be inputs, some other outputs - with your circuit you can manage up to 16 keys (4 x 4).

    Now about interrupts - can be avoided if you scan the keypad at time intervals of 10...50 ms. 

    Do a internet search first to find out some explanation of the concept and routines to see how to do it (there are a lot..).

    Petrei

  • Hi,

    16 keys... i read some concepts about interfacing key pad... i can use 4 pins as input and 4 pins as outputs... i will make output pins high and ill scan for inputs pins for there input... ill compare this inputs pins so that i can come to conclusion that which key is pressed.... this what i understood.... but we have use interrupts for input pins am not clear abt that interrupts part.... 

  • Why are you using interrupts for the input pins?  When you scan a keyboard, you send a signal down an output, and read the inputs to see which keys on that line were pressed (if any), and this is most easily coded w/o interrupts for the inputs, you can just read the input pins directly after you set the output pin.

  • slandrum said:
    Why are you using interrupts for the input pins?

    Might a single interrupt - resulting from the "And" of the 4 keypad "inputs" - eliminate the need to constantly scan the matrix keypad?  And might that reduce burden upon the MCU while potentially lessening EMI and conserving power?

    That said - indeed you are correct via, "interrupts for each input pin!"  Serve far less purpose than a single interrupt - which is not direct part of keypad input.

    Assume the following: 

    a) drive all keypad output lines low

    b) pull-up all keypad input lines

    c) connect these input lines both to "And" gate and to MCU GPIO inputs

    d) connect "And" gate's output to GPIO input - said input set to interrupt upon "high to low" signal transition (Note: this input is not part of keypad input array)

    Assumed is the matrix keypad's conduction - between one column and row during keypress - thus transferring the output low to one and only one input.  And - this action also triggers an interrupt - which signals the MCU to start its keypad scan - driving one and only one output low (i.e. "walking 0's") - and then debouncing & reading the inputs to determine the proper row-column match (thus decoding)...

    This "non constant scan" method has proved especially useful when some form of serial, MCU keypad scan was employed.  (eliminated the requirement to constantly scan, debounce & decode the keypad - even though long periods of, "keypad inactivity" totally dominate any keypad's usage cycle - rendering constant keypad scan very wasteful - especially in light of the technique herein presented...

    Update: Just dawned - "And" gate can be eliminated by instead using each/every keypad input as an interrupt trigger.  When individual port pins cannot signal an interrupt - the interrupt service routine can be "port-interrupt triggered" and the quick/fast interrupt service can then call/signal the necessary keypad "scan, debounce, decode" code block.  (residing outside of the interrupt service)

     

  • Hi,

    i am not using interrupts... using scanning method... slave has 8 pins, am configuring 4 pins as input and 4 as output. how to check whether pins are configured as input pins.....

    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/i2c.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "utils/uartstdio.h"
    #include "driverlib/rom.h"
    #include "driverlib/UART.h"

    unsigned long I2CRead();
    void delay (void);
    unsigned char getkey(void);
    unsigned char key1;
    void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount);

    extern void FPUEnable(void);
    extern void FPULazyStackingEnable(void);

    #define SLAVE_ADDRESS2 0x19
    #define SLAVE_ADDRESS 0x20
    unsigned long Temp2;
    unsigned char key[4][4]={ '0','1','2','3',
    '4','5','6','7',
    '8','9','A','B',
    'C','D','E','F'};

    //*****************************************************************************/

    void delay ()
    {
    unsigned char t=50;
    unsigned int i,j;
    for(i=0;i<t;i++)
    for(j=0;j<2000;j++);
    }

    //************************************* main() ********************************************************/

    int main(void)
    {
    unsigned int i;

    FPUEnable();
    FPULazyStackingEnable();

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_8MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_2);

    I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), false);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);

    ROM_GPIOPinConfigure(GPIO_PE1_U7TX);
    ROM_GPIOPinConfigure(GPIO_PE0_U7RX);
    ROM_GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    ROM_UARTConfigSetExpClk(UART7_BASE, ROM_SysCtlClockGet(), 115200,UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE);

    /* Configure the Port pins as (OUTPUT) by writing 0x00 to Configuration register */
    //UARTSend((unsigned char *)"enter1", 16);
    //UARTSend((unsigned char *)"entry", 16);
    /***************************** i2c write *****************************************
    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);
    Temp2 = I2CMasterErr(I2C0_MASTER_BASE);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    Temp2 = I2CMasterErr(I2C0_MASTER_BASE);
    I2CMasterDataPut(I2C0_MASTER_BASE, 0x03);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, 0xFF);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    // Wait for the first write/transaction to complete
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }*/


    ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);
    Temp2 = ROM_I2CMasterErr(I2C0_MASTER_BASE);
    ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    Temp2 = ROM_I2CMasterErr(I2C0_MASTER_BASE);
    ROM_I2CMasterDataPut(I2C0_MASTER_BASE, 0x03);
    while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }

    ROM_I2CMasterDataPut(I2C0_MASTER_BASE, 0xF0);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    // W0ait for the first write/transaction to complete
    while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);
    Temp2 = I2CMasterErr(I2C0_MASTER_BASE);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    Temp2 = I2CMasterErr(I2C0_MASTER_BASE);
    I2CMasterDataPut(I2C0_MASTER_BASE, 0x01);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, 0xfb);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    // Wait for the first write/transaction to complete
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    //UARTSend((unsigned char *)"enter2", 16);
    while(1)
    {
    //UARTSend((unsigned char *)"enter3", 16);
    key1=getkey();
    }
    }
    unsigned char getkey(void)
    {

    int col,i,j;
    unsigned char p;
    unsigned long PO,col1,col2,col3,col4;
    UARTSend((unsigned char *)"....", 16);

    {
    PO=I2CRead();
    for(i=0;i<500;i++);
    for (j=0;j<2000;j++);
    for(i=0;i<500;i++);
    for (j=0;j<2000;j++);
    p=(unsigned char)PO;
    /*ROM_UARTCharPutNonBlocking(UART7_BASE, p);
    // if(p==0xFF)
    {
    UARTSend((unsigned char *)"1", 2);
    }*/
    if(p==0xfd)
    {
    //UARTSend((unsigned char *)" ", 19);
    col1= (p & 0x10);
    col=4;
    if(col1==0)
    {
    col=0;
    UARTSend((unsigned char *)"key pressed is one ", 20);
    }
    col2= (p & 0x20);
    if(col2 == 0)
    {
    col=1;
    UARTSend((unsigned char *)"2", 16);
    }
    col3= (p & 0x30);
    if(col3==0)
    {
    col=2;
    UARTSend((unsigned char *)"3", 16);
    }
    col4= (p & 0x40);
    if(col4==0)

    {
    col=3;
    UARTSend((unsigned char *)"4", 16);
    }
    if(col<=3)
    return(key[0][col]);
    }

    else if (p==0xfb)
    {

    col1= (p & 0x10);
    col=4;
    if(col1==0)
    {
    col=0;
    UARTSend((unsigned char *)"key pressed is 4 ", 20);
    }
    col2= (p & 0x20);
    if(col2 == 0)
    {
    col=1;
    UARTSend((unsigned char *)"5", 16);
    }
    col3= (p & 0x30);
    if(col3==0)
    {
    col=2;
    UARTSend((unsigned char *)"6", 16);
    }
    col4= (p & 0x40);
    if(col4==0)

    {
    col=3;
    UARTSend((unsigned char *)"7", 16);
    }
    if(col<=3)
    return(key[0][col]);

    }

    else if ( p==0xf7)
    {
    col1= (p & 0x10);
    col=4;
    if(col1==0)
    {
    col=0;
    UARTSend((unsigned char *)"key pressed is 8 ", 20);
    }
    col2= (p & 0x20);
    if(col2 == 0)
    {
    col=1;
    UARTSend((unsigned char *)"9", 16);
    }
    col3= (p & 0x30);
    if(col3==0)
    {
    col=2;
    UARTSend((unsigned char *)"10", 16);
    }
    col4= (p & 0x40);
    if(col4==0)

    {
    col=3;
    UARTSend((unsigned char *)"11", 16);
    }
    if(col<=3)
    return(key[0][col]);
    }

    else if (p==0xfe)
    {
    col1= (p & 0x10);
    col=4;
    if(col1==0)
    {
    col=0;
    UARTSend((unsigned char *)"12 ", 15);
    }
    col2= (p & 0x20);
    if(col2 == 0)
    {
    col=1;
    UARTSend((unsigned char *)"13", 16);
    }
    col3= (p & 0x30);
    if(col3==0)
    {
    col=2;
    UARTSend((unsigned char *)"14", 16);
    }
    col4= (p & 0x40);
    if(col4==0)

    {
    col=3;
    UARTSend((unsigned char *)"15", 16);
    }
    if(col<=3)
    return(key[0][col]);
    }

    }
    }

    unsigned long I2CRead()
    {
    unsigned long Temp2;
    unsigned char temp;
    unsigned short iVal, Temp;
    unsigned long Temp3,Temp4;
    int i,j;
    temp=0;
    Temp=0;
    //temp=(unsigned char)Temp3;
    //ROM_UARTCharPutNonBlocking(UART7_BASE, temp);
    /* ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);

    Temp2 = ROM_I2CMasterErr(I2C0_MASTER_BASE);

    ROM_I2CMasterDataPut(I2C0_MASTER_BASE, 0x00);
    while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }

    /*ROM_I2CMasterDataPut(I2C0_MASTER_BASE, 0xFF);
    while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }*/
    ROM_I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, true);


    ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    Temp2 = ROM_I2CMasterErr(I2C0_MASTER_BASE);



    Temp3=ROM_I2CMasterDataGet(I2C0_MASTER_BASE);
    while(ROM_I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    //ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    temp=(unsigned char)Temp3;
    if(temp==0xFE)
    {
    UARTSend((unsigned char *)"successfull read", 15);
    for(i=0;i<500;i++);
    for (j=0;j<2000;j++);
    }
    if(temp==0xF0)
    {
    UARTSend((unsigned char *)"successfull read1", 15);
    }
    temp=(unsigned char)Temp3;
    //ROM_UARTCharPutNonBlocking(UART7_BASE, temp);
    UARTSend((unsigned char *)"reading\n", 16);

    return(temp);
    }
    void
    UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
    {
    //
    // Loop while there are more characters to send.
    //
    while(ulCount--)
    {
    //
    // Write the next character to the UART.

    ROM_UARTCharPutNonBlocking(UART7_BASE, *pucBuffer++);
    delay();
    delay();
    delay();
    delay();
    delay();
    delay();
     
    }
    }

    this is how am trying to interface. whats happening here is if i press any key its not reading value or status of the pins. if i write some values to pins and reading it.. it is reading correctly. 

     

  • Hi Petrei

    I have a TCA6408A connected to a Rohm MCU.  I manage to get port 1 to 7 working.  However port 0 (We configured it as a output port) is always at held low (logic 0) no mater how we set it on the I2C.

    We have many of our production boards here having this condition.

    We have try to troubleshoot and verify on the hardware side.  Hardware seem ok.

    Is there anything I may need to check on my code, especially on the timing of the SCL and SDA, and Reset timing.

    Really appreciate, Thank you

    Mark

  • Hi,

    Are you sure there is not a hardware problem? You can set P0 as input and apply some levels and see if you can read it. Should work OK if no hardware problem.

    Next, in software: have you configured this pin with register 3 and then write the needed level with register 1? 

    Petrei

  • Hi Petrei

    Thank you very much for your reply.  We double check on the register setting and now it is able to function.

    Thanks

    Mark Tan