Matrix Keypad & 16*2 LCD interfacing with PIC

Status
Not open for further replies.

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);
}
 
I have replied on AAC... But make another LCDprint and include R ( ram pointer ) use one for constants and one for variables..
 
Duration is an array so, LCD_Print(Duration); needs an index. Possibly as simple as LCD_Print(Duration[t]);

Mike.
 
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
 
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:
I always write two
One for constants...
C:
LCDprintC( const char* str)
   {
    while(!*str==0)
         LCDchrput(*str++);
   }
And one for variables..
C:
LCDprintR(char* str)
   {
    while(!*str==0)
         LCDchrput(*str++);
   }
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…