If till now you have used only libraries for 20×4 LCD then it will be more difficult to shifted to the another microcontroller if library is not available for new microcontroller. That time you need to know basic working of LCD. After that you can use this LCD with any microcontroler. I’ll write 20×4 LCD driver code in 4 bit mode with freedom KL02z without help of any librabry. I’ll describe problems I encountered and try to be as descriptive I can be so you can understand how the character LCD works, making you able to interface it with any micro-controller available, and even driving it by hand. But you have to go through the LCD data sheet for better understanding of code.

Pins interfacing of Microcontroller and LCD
First Connect your LCD with KL02 board as given below

  1. VSS–> GND
  2. VCC–> +3.3V
  3. VDD –> Contrast Adjustment
  4. RS –>PTB6
  5. R/W –> GND
  6. E –>PTB7
  7. D0 –>NC
  8. D1–>NC
  9. D2–>NC
  10. D3–>NC
  11. D4 –>PTB8
  12. D5–>PTB9
  13. D6–>PTB10
  14. D7–>PTB11
  15. +LED –>+5v
  16. -LED –>GND

As you are seeing I have selected an LCD which is working on 3.3V.

Source Code

const int LCD_R_select=6, LCD_enable=7, LCD_D4=8, LCD_D5=9, LCD_D6=10, LCD_D7=11;

void LCD_init();
void sendCommand(char opCode);
void digitalWrite(int pin_no, int pin_state);
void sendCommand4Bit(char opCode);
void lcdClear();
void lcdWriteText(char *text);
void lcdGoToXY(char x, char y);
void waiting(int milliseconds );

int main (void)
{ 
    // enable PORT    
    SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK|SIM_SCGC5_PORTB_MASK;	
    // Enable I/O to Digital input/output function
    PORTB_PCR6 &= ~PORT_PCR_MUX_MASK;
    PORTB_PCR7 &= ~PORT_PCR_MUX_MASK;
    PORTB_PCR8 &= ~PORT_PCR_MUX_MASK;	
    PORTB_PCR9 &= ~PORT_PCR_MUX_MASK;
    PORTB_PCR10 &= ~PORT_PCR_MUX_MASK;
    PORTB_PCR11 &= ~PORT_PCR_MUX_MASK;
	
    PORTB_PCR6 = PORT_PCR_MUX(1);
    PORTB_PCR7 = PORT_PCR_MUX(1);
    PORTB_PCR8 = PORT_PCR_MUX(1);
    PORTB_PCR9 = PORT_PCR_MUX(1);
    PORTB_PCR10 = PORT_PCR_MUX(1);
    PORTB_PCR11 = PORT_PCR_MUX(1);

    // Enable Pins as digital output
   GPIOB_PDDR = (1<<LCD_R_select)|(1<<LCD_enable)|(1<<LCD_D4)|(1<<LCD_D5)|(1<<LCD_D6)|(1<<LCD_D7);
   LCD_init();
	
   lcdWriteText("JELLYFISH            "); 
   lcdGoToXY(1,0);
   lcdWriteText("TECHNOLOGIES PVT LTD ");
   lcdGoToXY(2,0);
   lcdWriteText("R&D DEPARTMENT       ");  
   lcdGoToXY(3,0);
   lcdWriteText("THE INDIA            ");   
 	
	while(1)
	{   
          //nothing in while loop
	} 
}

Now I’ll describe all functions which has been used above in the source code.
First we take the LCD initialization function

void LCD_init();
Here in this function I used some terms which may be another function and are described next so don’t make any confusion

void LCD_init()
{	
 //Set all the control pins to logic Zero
  waiting(100);
  GPIOB_PCOR =	(1<<LCD_R_select);
  GPIOB_PCOR = (1<<LCD_enable);
  //Do the wake up call
  waiting(20); //20 milliseconds delay 
 sendCommand(0x30);
  waiting(20);
  sendCommand(0x20);  //Let's make it 4 bit mode
  waiting(20);
  //That's it LCD is initialized in 4 bit mode.
  sendCommand4Bit(0x28); //N = 1 (2 line display) F = 0 (5x8 characters)
  sendCommand4Bit(0x08); //Display on/off control D=0,C=0, B=0 
  sendCommand4Bit(0x01); //Clear Display
  sendCommand4Bit(0x06); //Entry mode set - I/D = 1 (increment cursor) & S = 0 (no shift) 
  sendCommand4Bit(0x0C); //Display on/off control. D = 1, C and B = 0. (Cursor and blink, last two bits)  

}

void sendCommand(char opCode);
This function is used to send 8 bit commands

void sendCommand(char opCode)
{  
 digitalWrite(LCD_D4, opCode & 0x10);
 digitalWrite(LCD_D5, opCode & 0x20);
 digitalWrite(LCD_D6, opCode & 0x40);
 digitalWrite(LCD_D7, opCode & 0x80);	
}

sendCommand4Bit(char opCode);
After setting LCD in 4 bit mode this function is used to send the commands in 4 bit mode.

void sendCommand4Bit(char opCode)
{
 digitalWrite(LCD_D4, opCode & 0x10);
 digitalWrite(LCD_D5, opCode & 0x20);
 digitalWrite(LCD_D6, opCode & 0x40);
 digitalWrite(LCD_D7, opCode & 0x80);

 digitalWrite(LCD_enable, 1);
 digitalWrite(LCD_enable, 0);

 digitalWrite(LCD_D4, opCode & 0x01);
 digitalWrite(LCD_D5, opCode & 0x02);
 digitalWrite(LCD_D6, opCode & 0x04);
 digitalWrite(LCD_D7, opCode & 0x08);
 
 digitalWrite(LCD_enable, 1);
 digitalWrite(LCD_enable, 0);
 waiting(1);
}

void digitalWrite(int pin_no, int pin_state);void
This is used to make the pins high and low

void digitalWrite(int pin_no, int pin_state)
 {
 if(pin_state>0)
    GPIOB_PSOR = (1 << pin_no);
 else
    GPIOB_PCOR = (1 << pin_no);		 
 }

void lcdClear();
This function clears the LCD

void lcdClear()
{
digitalWrite(LCD_R_select, 0);
sendCommand4Bit(0x01);
}

void lcdWriteText(char *text);

 void lcdWriteText(char *text)
 {   
  while( *text){
		digitalWrite(LCD_R_select, 1);
 		sendCommand4Bit(*text++);
 	       }
 }

void lcdGoToXY(char x, char y);
This function is used to bring the cursor on a particular address as you desire.

void lcdGoToXY(char x, char y)
{
  char addr;
  switch(x)
  {
     case 0: addr = 0x00; break; //Starting address of 1st line
     case 1: addr = 0x40; break; //Starting address of 2nd line
     case 2: addr = 0x14; break; //Starting address of 3rd line
     case 3: addr = 0x54; break; //Starting address of 4th line
     default: ; 
  } 
  addr +=y; 
  lcdGoToAddr(addr);
}

void waiting(int milliseconds );
This function is used to provide delay in millisecond.

void waiting(int value)
	{
	int wait;
	while(value)
	{
	for(wait=0; wait<11996; wait++);
	value--;
}
}

I hope, it will be helpful for you.