Tool/software: TI C/C++ Compiler
Hi,
I am interfacing a 2x3 matrix keypad with my TM4C123 microcontroller. The program what I wrote is working correctly for first row, Because whenever I was pressing the button in first row,corresonding data is displayed on LCD. The issue I was facing is related to second row.
Row 0 PORTE PIN7, Row1 PORTF PIN0
Column PORTF Pin1,2,3 respectively
RS is connected to portG pin 4,Enable pin is connected to portG pin 5,D0 to D4 are connected to portG pin0 to pin 4 respectively.The LCD I am using is 4 bit mode LCD.
Given below is my program
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/systick.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
volatile uint32_t msTicks = 0;
unsigned char temp;
/******************************************************************************************************************
Systick interrupt function
******************************************************************************************************************/
void SysTick_Handler(void)
{
//
// Update the Systick interrupt counter.
//
/* Increment counter necessary in Delay()*/
msTicks++;
}
void Delay(uint32_t dlyTicks)
{
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks )< dlyTicks) ;
}
/*****************************************************************************************************************************
End of systick interrupt
******************************************************************************************************************************/
void Lcd_command(unsigned char cmd)
{
//send higher four bit
temp= cmd;
temp=((temp>>4)& 0x0F); //shift the data right by four bits, thus bringing the higher nibble in the lower nibble location
//temp=(temp & 0x0F);
//Delay(1000);
//GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0,com);//LCD mode
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, temp);//LCD data
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_4,0);// RS=0GPIO pin-4,E=0 GPIO pin 5
Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);//Make E=0
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,GPIO_PIN_5);// RS=0,E=1 enabling lcd by high to low pulse
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);// RS=0,E=0
//Delay(50);
//send lower 4bit
temp=cmd; // send lower nibble
//temp=temp>>4; //shift the data right by four bits, thus bringing the higher nibble in the lower nibble location
temp=(temp & 0x0F);
//GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_4|GPIO_PIN_5,0x00);// RS=0GPIO pin-4,E=0 GPIO pin 5
//Delay(1000);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, temp);//write data
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);//Make E=0
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,GPIO_PIN_5);// RS=0,E=1 enabling lcd by high to low pulse
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);// RS=0,E=0
Delay(50);
}
void Lcd_data(unsigned char data)
{
temp= data;
temp=((temp>>4)& 0x0F); //shift the data right by four bits, thus bringing the higher nibble in the lower nibble location
//temp=(temp & 0x0F);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, temp);//LCD data
//GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0,com);//LCD mode
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_4, GPIO_PIN_4);// RS=1 GPIO pin-4,E=0 GPIO pin 5
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);//Make E=0
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5, GPIO_PIN_5);//E=1 enabling lcd by high to low pulse
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);//Make E=0
//Delay(50);
temp= data;// // send lower nibble
//temp=temp>>4;
temp=(temp & 0x0F);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, temp);//LCD data
//Delay(1000);
//GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0,com);//LCD mode
//GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_4|GPIO_PIN_5,0x10);//Make RS=1GPIO pin-4,E=0 GPIO pin 5
//Delay(1000);
//
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5,0);//Make E=0
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5, GPIO_PIN_5);//make RS=1,E=1 enabling lcd by high to low pulse
//Delay(50);
GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_5, 0);//Make RS=1,E=0
Delay(50);
}
void Lcd_Init()
{
Lcd_command(0x28); //4-bit mode lcd having 2 lines and character shape between 5x7 matrix.
Delay(50); //provide 500ms delay
Lcd_command(0x06); //Display ON, cursor OFF / entry mode it tells the lcd that we are going to use.
Delay(50); //provide 500ms delay
//Lcd_command(0x0E); //displays cursor on and dispaly on.
//Delay(50); //provide 500ms delay
Lcd_command(0x01); //Clear screen
Delay(50); //provide 500ms delay
Lcd_command(0x0F); //displays cursor on and dispaly on.
Delay(50); //provide 500ms delay
}
void Lcd_String_Display(unsigned char *str)
{
while(*str!='\0')
{
Lcd_data(*str);
str++;
}
}
/*********************************************************************************************************************************
Keypad function
*********************************************************************************************************************************/
void key_detect(unsigned char value)
{
if(value ==1) //column 1 key pressed
{
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 , GPIO_PIN_7); //Make Row 0 as HIGH
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1)==0x02) //column 1 status is changing from low to high
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row0 colmn1");
Delay(50);
}
else
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0 , GPIO_PIN_0); //Make Row 1 as HIGH
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1)==0x02) //column 1 status is changing from low to high
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row 1 colm 1");//check Row 1 status is changing to low
}
}
}
if(value ==2) //column 1 key pressed
{
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 , GPIO_PIN_7); //Make Row 0 as HIGH
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0 , GPIO_PIN_0);
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2)==0x04)//column 2 status is changing from low to high
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row 0 colm 2");
}
else
{
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2)==0x04)//column 2 status is changing from low to high
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row 1 colm 2");
}
}
}
if(value == 3) //column 1 key pressed
{
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 , GPIO_PIN_7); //Make Row 0 as HIGH
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0 , GPIO_PIN_0);
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3)==0x08)
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row 0 colm 3");//column 3 status is changing from low to high
}
else
{
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3)==0x08) //column 3 status is changing from low to high
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Row 1 colm 3");
}
}
}
Delay(50);
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 ,0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
}
/*********************************************************************************************************
End of keypad function
**********************************************************************************************************/
/*********************************************************************************************************
Main
**********************************************************************************************************/
int main()
{
SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC |SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN);//8MHz crystall oscilator
IntMasterEnable();// Enable interrupts to the processor.
SysTickPeriodSet(7997); // Set up the period for the SysTick timer of 1ms.
SysTickIntEnable(); // Enable the SysTick Interrupt.
SysTickEnable();
//ENABLING PORTS
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
//while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOG));
//DEFINING THE PINS
GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
//pins of PORT F are connected to rows 1,2 of the keypad
GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_7 );
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 );
GPIODirModeSet(GPIO_PORTE_BASE, GPIO_PIN_7,GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_0,GPIO_DIR_MODE_OUT);
//GPIOPadConfigSet(GPIO_PORTE_BASE,GPIO_PIN_7,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_OD);
//GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_OD);
//PORTF pin 1,2,3 are input
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2 | GPIO_PIN_3);
//GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2 | GPIO_PIN_3,GPIO_DIR_MODE_HW);
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2 | GPIO_PIN_3,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
Lcd_command(0x01); //Clear screen
Delay(50);
Lcd_Init();
Lcd_String_Display("Welcome...");
Lcd_command(0x01); //Clear screen
Delay(50);
//Make Row pin as low
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7 ,0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
//make column pin as high
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2| GPIO_PIN_3, 0x0E);
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 , 0);
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2 , 0);
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3 , 0);
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 , 0);
while(1)
{
//check any key pressed/if any of the column changing to low then get in to that function and check which row key pressed
//uint8_t A =GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1);
//uint8_t B =GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2);
//uint8_t C =GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3);
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1)==0x00)//check column 1 is low and other columns are one
{
//Lcd_data('1');
key_detect(1);
Delay(50);
}
else if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2)==0x00)//check column 2 is low and other columns are one
{
//Lcd_data('2');
key_detect(2);
Delay(50);
}
else if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3)==0x00)//check column 3 is low and other columns are one
{
//Lcd_data('3');
key_detect(3);
Delay(50);
}
else if((GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1)!=0x0C)&&(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2)!=0x0A)&&(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_3)!=0x06))
{
Lcd_command(0x01); //Clear screen
Lcd_command(0xC0);
Lcd_String_Display("Key not pressed...");
}
}
}
The procedure I was following is,
Making row as output and column as input and making row pin as logic 'LOW' and column as 'HIGH' in initial stage.
1. press the button read all column, check any column is zero.
2. once it find the column then it will search for row.
3. for finding row I will make each Row high and read status of column.
4. column red as high means that row button pressed
I am little bit doubtful about my pin configuration, because the first row is connected to PORTE Pin7 & second row is connected to PORTF pin0. The column Pin are connected to same PORTF Pin 1,2,3 respectively.
I checked the Rows are changing its state or not and what I found is the first row is changing its state from high to low, but second row is not . It was in Low state only.
I cant change the row pin to any other port , the board was already designed for my project.
Please let me know is there any way to solve this issue.
Looking forward for a quick reply...
Regards,
Alphy