• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Matrix Keypad & 16*2 LCD interfacing with PIC

Swsean

New Member
Hi, guys. I am working on my final year project. I've been trying to interface the Matrix Keypad & 16*2 LCD along the with PIC. However, I wasn't able to get it to work. The LCD is able to display the 'Enter Duration' text but does not display the content of the 'Duration' array. The microcontroller I used is PIC16F887. My current code is listed below. Please help me check my code.
Code:
#pragma config CONFIG1 = 0x2CD4
#pragma config CONFIG2 = 0x0700
 
#include
#include
 
//LCD module connections
#define LCD_RS       RD0
#define LCD_EN       RD1
#define LCD_D4       RD2
#define LCD_D5       RD3
#define LCD_D6       RD4
#define LCD_D7       RD5
#define LCD_RS_DIR   TRISD0
#define LCD_EN_DIR   TRISD1
#define LCD_D4_DIR   TRISD2
#define LCD_D5_DIR   TRISD3
#define LCD_D6_DIR   TRISD4
#define LCD_D7_DIR   TRISD5
//End LCD module connections
 
//matrix keypad connections
#define X_1    RB0
#define X_2    RB1
#define X_3    RB2
#define X_4    RB3
#define Y_1    RB4
#define Y_2    RB5
#define Y_3    RB6
#define Y_4    RB7
#define Keypad_PORT          PORTB
#define Keypad_PORT_Direction     TRISB   

#include
#define _XTAL_FREQ 8000000
#include         // include stdint header
#include "LCD_Lib.c"       // include LCD driver source file
 

// Function declarations
void InitKeypad(void);
char switch_press_scan(void);

void InitKeypad(void)
{
    Keypad_PORT        = 0x00;    // Set Keypad port pin values zero
    Keypad_PORT_Direction = 0xF0;    // Last 4 pins input, First 4 pins output
    
    OPTION_REG &= 0x7F;
}

char keypad_scanner(void)   
{   
    X_1 = 0; X_2 = 1; X_3 = 1; X_4 = 1;     

    if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '1'; }
    if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '2'; }
    if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '3'; }
    if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'A'; }

    X_1 = 1; X_2 = 0; X_3 = 1; X_4 = 1;     

    if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '4'; }
    if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '5'; }
    if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '6'; }
    if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'B'; }
    
    X_1 = 1; X_2 = 1; X_3 = 0; X_4 = 1;     

    if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '7'; }
    if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '8'; }
    if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '9'; }
    if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'C'; }
    
    X_1 = 1; X_2 = 1; X_3 = 1; X_4 = 0;     

    if (Y_1 == 0) { __delay_ms(100); while (Y_1==0); return '*'; }
    if (Y_2 == 0) { __delay_ms(100); while (Y_2==0); return '0'; }
    if (Y_3 == 0) { __delay_ms(100); while (Y_3==0); return '#'; }
    if (Y_4 == 0) { __delay_ms(100); while (Y_4==0); return 'D'; }

    return 'n';   
}


// Function name: GetKey
// Read pressed key value from keypad and return its value
char switch_press_scan(void)                // Get key from user
{
    char key = 'n';              // Assume no key pressed

    while(key=='n')              // Wait until a key is pressed
        key = keypad_scanner();   // Scan the keys again and again

    return key;                  //when key pressed then return its value
}

void main(void)
{
    LCD_Begin();
    uint8_t t = 0;
    static char Duration[10];
    char Key = 'n';
    InitKeypad();
    LCD_Goto(1, 1);
    LCD_Print("Enter Duration");
    LCD_Goto(1, 2);
    while(t<9){
        Key = switch_press_scan();
        Duration[t]=Key;
        LCD_Goto(t+1, 2);
        LCD_Print(Duration);
        t++;
    }
}
The library I used for the LCD is provided below:
Code:
#pragma warning disable 520

#include

#define LCD_FIRST_ROW          0x80
#define LCD_SECOND_ROW         0xC0
#define LCD_THIRD_ROW          0x94
#define LCD_FOURTH_ROW         0xD4
#define LCD_CLEAR              0x01
#define LCD_RETURN_HOME        0x02
#define LCD_ENTRY_MODE_SET     0x04
#define LCD_CURSOR_OFF         0x0C
#define LCD_UNDERLINE_ON       0x0E
#define LCD_BLINK_CURSOR_ON    0x0F
#define LCD_MOVE_CURSOR_LEFT   0x10
#define LCD_MOVE_CURSOR_RIGHT  0x14
#define LCD_TURN_ON            0x0C
#define LCD_TURN_OFF           0x08
#define LCD_SHIFT_LEFT         0x18
#define LCD_SHIFT_RIGHT        0x1E

#ifndef LCD_TYPE
   #define LCD_TYPE 2           // 0=5x7, 1=5x10, 2=2 lines
#endif

__bit RS;

void LCD_Write_Nibble(uint8_t n);
void LCD_Cmd(uint8_t Command);
void LCD_Goto(uint8_t col, uint8_t row);
void LCD_PutC(char LCD_Char);
void LCD_Print(char* LCD_Str);
void LCD_Begin();

void LCD_Write_Nibble(uint8_t n)
{
  LCD_RS = RS;
  LCD_D4 = n & 0x01;
  LCD_D5 = (n >> 1) & 0x01;
  LCD_D6 = (n >> 2) & 0x01;
  LCD_D7 = (n >> 3) & 0x01;

  // send enable pulse
  LCD_EN = 0;
  __delay_us(1);
  LCD_EN = 1;
  __delay_us(1);
  LCD_EN = 0;
  __delay_us(100);
}

void LCD_Cmd(uint8_t Command)
{
  RS = 0;
  LCD_Write_Nibble(Command >> 4);
  LCD_Write_Nibble(Command);
  if((Command == LCD_CLEAR) || (Command == LCD_RETURN_HOME))
    __delay_ms(2);
}

void LCD_Goto(uint8_t col, uint8_t row)
{
  switch(row)
  {
    case 2:
      LCD_Cmd(LCD_SECOND_ROW + col - 1);
      break;
    case 3:
      LCD_Cmd(LCD_THIRD_ROW  + col - 1);
      break;
    case 4:
      LCD_Cmd(LCD_FOURTH_ROW + col - 1);
    break;
    default:      // case 1:
      LCD_Cmd(LCD_FIRST_ROW  + col - 1);
  }

}

void LCD_PutC(char LCD_Char)
{
  RS = 1;
  LCD_Write_Nibble(LCD_Char >> 4);
  LCD_Write_Nibble(LCD_Char );
}

void LCD_Print(char* LCD_Str)
{
  uint8_t i = 0;
  RS = 1;
  while(LCD_Str[i] != '\0')
  {
    LCD_Write_Nibble(LCD_Str[i] >> 4);
    LCD_Write_Nibble(LCD_Str[i++] );
  }
}

void LCD_Begin()
{
  RS = 0;

  LCD_RS     = 0;
  LCD_EN     = 0;
  LCD_D4     = 0;
  LCD_D5     = 0;
  LCD_D6     = 0;
  LCD_D7     = 0;
  LCD_RS_DIR = 0;
  LCD_EN_DIR = 0;
  LCD_D4_DIR = 0;
  LCD_D5_DIR = 0;
  LCD_D6_DIR = 0;
  LCD_D7_DIR = 0;

  __delay_ms(40);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(LCD_RETURN_HOME);
  __delay_ms(5);
  LCD_Cmd(0x20 | (LCD_TYPE << 2));
  __delay_ms(50);
  LCD_Cmd(LCD_TURN_ON);
  __delay_ms(50);
  LCD_Cmd(LCD_CLEAR);
  __delay_ms(50);
  LCD_Cmd(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
  __delay_ms(50);
}
 

Pommie

Well-Known Member
Most Helpful Member
Duration is an array so, LCD_Print(Duration); needs an index. Possibly as simple as LCD_Print(Duration[t]);

Mike.
 

Swsean

New Member
Ian Rogers is this correct?
Code:
void LCD_PRINTS(char LCD_Str)
{
  uint8_t i = 0;
  RS = 1;
  while(LCD_Str[i] != '\0')
  {
    LCD_Write_Nibble(LCD_Str[i] >> 4);
    LCD_Write_Nibble(LCD_Str[i++] );
  }
}
This produced an error
error: subscripted value is not an array, pointer, or vector
 

Pommie

Well-Known Member
Most Helpful Member
Your code above is using LCD_Print() which expects a string to be passed but you're passing a Char.

Try changing the above code to,
Code:
    while(t<9){
        Key = switch_press_scan();
        Duration[t]=Key;
        LCD_Goto(t+1, 2);
        LCD_PutC(Key);
        t++;
    }
The only addition code you may need is to print from a ROM string but you don't need it yet.

Mike.
Edit, code to print from flash
Code:
//Write a string to the LCD from flash
void PutMessage(const char *Message){
    while(*Message!=0)
        LCD_PutC(*Message++);
}
And you would call it simply as,
PutMessage("Hello World!!");
Note the const directive tells the compiler to put the message in flash.
 
Last edited:

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
not one for variables, that's for strings stored in ram.
Yup.. But by definition you can modify RAM strings that makes it variable.. But I see where you are coming from
 

Latest threads

EE World Online Articles

Loading

 
Top