20x4 LCD shows Black boxes

Status
Not open for further replies.

ADGAN

Full Member level 5
Joined
Oct 9, 2013
Messages
295
Helped
4
Reputation
8
Reaction score
4
Trophy points
18
Visit site
Activity points
1,837
Hi! I recently purchased a LCD for my project. After connecting all the wires all I get is black boxes on the 1st & the 3rd line.I'm using a 5K preset to adjust the contrast and the voltage is given by a LM7805 voltage regulator. I used even very simple examples given by MikroC but still nothing happens. I removed the data lines & control lines but still the problem appears. I Google this problem and came to know that it could be a problem with the controller. Is it possible to reset the controller using software? or else what can I do about this?

This is the datasheet of the LCD:
https://elcodis.com/parts/6020704/LMB204BBC.html#datasheet
 

I tried many source codes even simple ones such as displaying "Hello World". This is the code I tested. This not the full code just half of it. I think the problem is not with the source code because even if I remove all the data lines & control it is still there. I simulated this code in Proteus & it worked fine.

Code:
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections


unsigned char sec, min1, hr, week_day, day, mn, year;
int last_date;
char *txt,*txti, tnum[4];
float lastmnth_cnsumption, thismnth_cnsumption,energymeasurment;

char txt1[] = "ENERGY CONSUMPTION";
char txt2[] = "FROM";
char txt3[] = "TO";
char txt4[] = "KWh";

void start1307s(){
//START SIGNAL FOR DS1307***********
I2C1_Start(); // issue start signal
I2C1_Wr(0xD0); // address PCF8530
I2C1_Wr(0); // start from word at address 0
I2C1_Wr(0); // write 0 to config word (enable counting)
I2C1_Stop(); // issue stop signal
//**********************************
}

void Zero_Fill(char *value) { // fill text repesentation
if (value[1] == 0) { // with leading zero
value[1] = value[0];
value[0] = 48;
value[2] = 0;
}
}


//--------------------- Reads time and date information from RTC (DS1307)
void Read_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
I2C1_Start();
I2C1_Wr(0xD0);
I2C1_Wr(0);
I2C1_Repeated_Start();
I2C1_Wr(0xD1);
*sec =I2C1_Rd(1);
*min =I2C1_Rd(1);
*hr =I2C1_Rd(1);
*week_day =I2C1_Rd(1);
*day =I2C1_Rd(1);
*mn =I2C1_Rd(1);
*year =I2C1_Rd(0);
I2C1_Stop();
}

//-------------------- Formats date and time
void Transform_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
*sec = ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
*min = ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
*hr = ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
*week_day =(*week_day & 0x07);
*day = ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
*mn = ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
*year = ((*year & 0xF0)>>4)*10+(*year & 0x0F);
}


//-------------------- Output values to LCD
void Display_Time(char sec, char min, char hr, char week_day, char day, char mn, char year) {
switch(week_day){
case 1: txt="Sun"; break;
case 2: txt="Mon"; break;
case 3: txt="Tue"; break;
case 4: txt="Wed"; break;
case 5: txt="Thu"; break;
case 6: txt="Fri"; break;
case 7: txt="Sat"; break;
}
Lcd_Out(3,4,txt);

ByteToStr(day,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(3,7,txt);

ByteToStr(mn,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(3,11,txt);

ByteToStr(year,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(3,17,txt);

}

//------------------ Performs project-wide init
void Init_Main() {
C1ON_bit = 0;                      // Disable comparators
C2ON_bit = 0;

TRISC=0xFF;
I2C1_Init(100000); // initialize I2C

txt = "20";
Lcd_Out(2,15,txt);
Lcd_Out(3,15,txt);
}

void lastdate_check(char day, char mn, char year, int last_date)
{
if (mn == 1 || mn == 2 || mn ==4 || mn ==6 || mn == 8 || mn ==9 || mn == 11)
{
      last_date = 31;
      ByteToStr(last_date,tnum);
      txt = rtrim(tnum);
      Zero_Fill(txt);
      Lcd_Out(2,7,txt);
}
else
{
 if(mn == 3 )
 {
   if(year%4 == 0)
   {
                last_date = 29;
                ByteToStr(last_date,tnum);
                txt = rtrim(tnum);
                Zero_Fill(txt);
                Lcd_Out(2,7,txt);

   }
   else
   {
                last_date = 28;
                ByteToStr(last_date,tnum);
                txt = rtrim(tnum);
                Zero_Fill(txt);
                Lcd_Out(2,7,txt);

   }
 }

last_date = 30;
ByteToStr(last_date,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(2,7,txt);
}
}

void lastmonth_check(char day, char mn, char year)
{
char last_mn;

if (mn>2)
{
char last_mn = mn - 1;
ByteToStr(last_mn,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(2,11,txt);
}

else
{
last_mn = 12;
ByteToStr(last_mn,tnum);
txt = rtrim(tnum);
Zero_Fill(txt);
Lcd_Out(2,11,txt);
}

}

void lastyear_check(char day,char mn,char year)
{
char last_year;

if (mn == 1)
{
 last_year = year-1;
 ByteToStr(last_year,tnum);
 txt = rtrim(tnum);
 Zero_Fill(txt);
 Lcd_Out(2,17,txt);
}
else
{
 ByteToStr(year,tnum);
 txt = rtrim(tnum);
 Zero_Fill(txt);
 Lcd_Out(2,17,txt);
}
}

float current_energy_cal(float energymeasurment, float lastmnth_cnsumption)
{
return thismnth_cnsumption = energymeasurment - lastmnth_cnsumption;
}

void energy_display(thismnth_cnsumption)
{
Lcd_Chr(4,10,'.');
Lcd_Out(4,13,txt4);
}



//----------------- Main procedure
void main(){
  ANSELB  = 0;                        // Configure AN pins as digital I/O
  C1ON_bit = 0;                      // Disable comparators
  C2ON_bit = 0;

  Lcd_Init();                        // Initialize LCD

  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off

  Init_Main();
  start1307s(); // perform initialization
  
  while (1) {
  Lcd_Out(1,2,txt1);
  Lcd_Out(2,1,txt2);
  Lcd_Out(3,1,txt3);
  Lcd_Chr(2,10,'/');
  Lcd_Chr(2,14,'/');
  Lcd_Chr(3,10,'/');
  Lcd_Chr(3,14,'/');

  Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // read time from RTC(DS1307)
  Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // format date and time
  lastdate_check(day, mn, year, last_date);
  lastmonth_check(day, mn, year);
  lastyear_check(day, mn, year);
  Display_Time(sec, min1, hr, week_day, day, mn, year); // prepare and display on Lcd
  
  }
  }
 

#define LCD_EN RB3
#define LCD_RS RB5
#define LCD_RW RB4
#define LCD_DATA PORTD

Modify you program as per above setting and send hex file
my Fosc = 4Mhz
__CONFIG(0X3F39);
MCU 16f877a
 

The ST7066U chipset timing requirements do differ from the HD44780 chipset in some areas.

The presence of solid boxes on the 1st and 3rd lines as you stated may certainly indicate improper initialization of the LCD, particular on powerup/reset.

Reference: LMB204BBC LCD User Manual, Section: 4.2 Resetting the LCD module, Page: 7
When turning on the VDD and VSS power supply, LCD module will execute the reset routine
automatically. It takes about 80ms.

The above quote indicates a minimum time period of 80ms is required upon powerup or reset for the ST7066U chipset to full initialize and run its powerup/reset routines.

The required minimum time interval of 80ms is significantly longer than some other HD44780 compatible chipsets.

The possible remedies are limited, as you are attempting to use a "canned" MikroC LCD library with no available source code.

However, inserting a 100ms delay before the LCD initialization routine:

Code:
void Lcd_Init();

May provide some relief to the LCD powerup/reset issue.

I do not believe the MikroC LCD libraries utilize/monitor the busy flag, instead utilizes built-in delays within the routines, therefore as whoknows suggested, you may or may not have to insert additional smaller delays before every subsequent LCD routine call.

Reference: ST7066U Datasheet, Section: Instructions, Page: 17

Also be aware the ST7066U chipset required method of placing it into 4-bit mode may differ slightly from other HD44780 compatible chipsets.

The fact the code performs as expected in simulation should bring little comfort when LCDs or many other physical devices are implemented in real hardware as you now know simulations are simply NOT the same as real hardware.

It certainly is not difficult to port one of the myriad of available open source LCD routines to MikroC, which would in turn give you control over the delays and initialization requirements of your device.


BigDog
 
Reactions: ADGAN

    ADGAN

    Points: 2
    Helpful Answer Positive Rating
Thanks for the replies. Even though I'm using a MikroC code for testing my actual project is written in MPLAB. Following is the the LCD lib. This has been written to a 16x2 LCD but not yet compatible with 20x4 LCD. I have a problem about that too. I want to change it support my LCD.

LCD_lib_busy.c
Code:
//##############################################################################
//    filename:        LCD_lib_busy.c
//##############################################################################
//    LCD library for HD44780, HD47780, ST7036 ...
//##############################################################################
//
//      Author:                    V.SchK
//      Company:                HS-Ulm
//
//      Revision:                1.0
//         Date:                         June. 2012
//             Assembled using         C18 3.41+
//
//           todo        - add comments ;-)
//                     -
//
//##############################################################################
//http://sprut.de/electronic/lcd/index.htm#befehle

#include <p18cxxx.h>
#include "LCD_lib_busy.h"

//#pragma udata
union LCDv8bit LCD_data;         // bitfield variable (bitwise acess)
unsigned short LCD_busy_cnt;

// -------------------- LCD-functions ------------------------------------------
#ifdef LCD_ON

void LCD_On (void)
{
    LCD_ON = 1;
    LCD_ON_DIR = 0;
#warning DO NOT FORGET TO SWITCH ON THE DISPLAY AND TO ADD A POWER UP DELAY !
}
#endif


void LCD_Init (void)
{
    LCD_RW = 0; LCD_RW_DIR = 0;
    LCD_RS = 0; LCD_RS_DIR = 0;
    LCD_E  = 0; LCD_E_DIR  = 0;

    LCD_D4_OUT = 0; LCD_D4_DIR = 0;
    LCD_D5_OUT = 0; LCD_D5_DIR = 0;
    LCD_D6_OUT = 0; LCD_D6_DIR = 0;
    LCD_D7_OUT = 0; LCD_D7_DIR = 0;

    LCD_busy_cnt = 1;                // busy_flag time out counter

    LCD_DELAY_5MS();LCD_DELAY_5MS();LCD_DELAY_5MS();    // wait for 15ms
// display reset procedure
    LCD_Write_Nibble(LCD_RESET);    LCD_DELAY_5MS();
    LCD_Write_Nibble(LCD_RESET);    LCD_DELAY_5MS();
    LCD_Write_Nibble(LCD_RESET);    LCD_DELAY_5MS();
// set 4-bit mode always !!!
    LCD_Write_Nibble(FOUR_BIT);     while (LCD_Busy()) {;} // wait


#if defined EXT_LCD_3_3_V
    LCD_Command(FOUR_BIT_TWO_LINE + EXT_INSTR_TBL_1);
    LCD_Command(EXT1_BIAS_1_5);
    LCD_Command(EXT1_CONTRAST + 0x0C);
    LCD_Command(EXT1_BOOST_ICON_C + BOOST_ON + 1);
    LCD_Command(EXT1_FOLLOWER + FOLLOWER_ON + 5);
#elif defined EXT_LCD_5_V
    LCD_Command(FOUR_BIT_TWO_LINE + EXT_INSTR_TBL_1);
    LCD_Command(EXT1_BIAS_1_4);
    LCD_Command(EXT1_CONTRAST + 0x04);
    LCD_Command(EXT1_BOOST_ICON_C + BOOST_OFF + 2);
    LCD_Command(EXT1_FOLLOWER + FOLLOWER_ON + 1);
#else
    LCD_Command(FOUR_BIT_TWO_LINE);
#endif

    LCD_Command(DISPLAY_CTRL + DISPLAY_ON);// + BLINK_ON);
    LCD_Command(ENTRY_MODE + CURSOR_INC + DSHIFT_OFF);
    LCD_Command(CLEAR_DISPLAY);
    LCD_Command(RETURN_HOME);
}
// --------------------------------------------------------------

void LCD_signalsTest()
{
    LCD_RS_DIR = 0;
    LCD_RW_DIR = 0;
    LCD_E_DIR = 0;
    LCD_D4_DIR = 0;
    LCD_D5_DIR = 0;
    LCD_D6_DIR = 0;
    LCD_D7_DIR = 0;

    LCD_RS = 1;
    LCD_RW = 1;
    LCD_ENABLE();
    LCD_D4_OUT = 1;
    LCD_D5_OUT = 1;
    LCD_D6_OUT = 1;
    LCD_D7_OUT = 1;

    LCD_RS = 0;
    LCD_RW = 0;
    LCD_DISABLE();
    LCD_D4_OUT = 0;
    LCD_D5_OUT = 0;
    LCD_D6_OUT = 0;
    LCD_D7_OUT = 0;
}


//****************************************************************************
//     _    ______________________________
// RS  _>--<______________________________
//     _____
// RW       \_____________________________
//                  __________________
// E   ____________/                  \___
//     _____________                ______
// DB  _____________>--------------<______
void LCD_Write_Nibble(unsigned char value)
{
    LCD_data.all = value;
    LCD_RS = LCD_CMD;
    LCD_RW = LCD_WR;

    LCD_D4_OUT = LCD_data.bit4;
    LCD_D5_OUT = LCD_data.bit5;
    LCD_D6_OUT = LCD_data.bit6;
    LCD_D7_OUT = LCD_data.bit7;
    LCD_STROBE();
}
// --------------------------------------------------------------

void LCD_Write(unsigned char value) // command or data
{
    LCD_data.all = value;
    LCD_RW = LCD_WR;

    LCD_D7_OUT = LCD_data.bit7;
    LCD_D6_OUT = LCD_data.bit6;
    LCD_D5_OUT = LCD_data.bit5;
    LCD_D4_OUT = LCD_data.bit4;
    LCD_STROBE();

    LCD_D7_OUT = LCD_data.bit3;
    LCD_D6_OUT = LCD_data.bit2;
    LCD_D5_OUT = LCD_data.bit1;
    LCD_D4_OUT = LCD_data.bit0;
    LCD_STROBE();
}
// --------------------------------------------------------------

void LCD_ValueOut_00(unsigned char row, unsigned char col, short value,
                     unsigned char min_dig)
{
    char chBuffer, leading_0;

    LCD_Command(CURSOR_ADDR + (LINE_OFFSET * row) + col);
    leading_0 = 1;

    if (value < 0){
        chBuffer = '-';
        LCD_CharOut(chBuffer);
        value = -value;
    }
    else if(!leading_0 &&(min_dig == 1)){
        chBuffer = ' ';
        LCD_CharOut(chBuffer);
    }
    chBuffer = value / 10000;
    if(leading_0){
        if((chBuffer != 0)||(min_dig == 5)) leading_0 = 0;
    }
    if(!leading_0){
        LCD_CharOut(chBuffer +0x30);
    }
    value = value - (10000 * chBuffer);
    chBuffer = value / 1000;
    if(leading_0){
        if((chBuffer != 0)||(min_dig == 4)) leading_0 = 0;
    }
    if(!leading_0){
        LCD_CharOut(chBuffer +0x30);
    }
    value = value - (1000 * chBuffer);
    chBuffer = value / 100;
    if(leading_0){
        if((chBuffer != 0)||(min_dig == 3)) leading_0 = 0;
    }
    if(!leading_0){
        LCD_CharOut(chBuffer +0x30);
    }
    value = value - ((short)100 * chBuffer);
    chBuffer = value  / 10;
    if(leading_0){
        if((chBuffer != 0)||(min_dig == 2)) leading_0 = 0;
    }
    if(!leading_0){
        LCD_CharOut(chBuffer +0x30);
    }
    value = value - ((short)10 * chBuffer);
    chBuffer = value;
    LCD_CharOut(chBuffer +0x30);
}
// --------------------------------------------------------------

void LCD_ConstTextOut(unsigned char row, unsigned char col, const char *text)
{
    LCD_Command(CURSOR_ADDR + (LINE_OFFSET *  row) +  col);
    while (*text) {
        LCD_CharOut(*text);
        text++;
    }
}
// --------------------------------------------------------------

void LCD_TextOut(unsigned char row, unsigned char col, unsigned char *text)
{
    LCD_Command(CURSOR_ADDR + (LINE_OFFSET * row) +  col);
    while (*text) {
        LCD_CharOut(*text);
        text++;
    }
}
// --------------------------------------------------------------

//unsigned char LCD_Read(void)
//{
//    LCD_D4_DIR = 1;
//    LCD_D5_DIR = 1;
//    LCD_D6_DIR = 1;
//    LCD_D7_DIR = 1;
//    LCD_RW = LCD_RD; // Set read mode
//
//    LCD_ENABLE(); LCD_DELAY_1US();
//    LCD_data.bit7 = LCD_D7_IN;
//    LCD_data.bit6 = LCD_D6_IN;
//    LCD_data.bit5 = LCD_D5_IN;
//    LCD_data.bit4 = LCD_D4_IN;
//    LCD_DISABLE();
//
//    LCD_ENABLE(); LCD_DELAY_1US();
//    LCD_data.bit3 = LCD_D7_IN;
//    LCD_data.bit2 = LCD_D6_IN;
//    LCD_data.bit1 = LCD_D5_IN;
//    LCD_data.bit0 = LCD_D4_IN;
//    LCD_DISABLE();
//
//    return LCD_data.all;
//}

unsigned char LCD_Busy(void)
{
    if (LCD_busy_cnt >= LCD_TIMEOUT){
        LCD_busy_cnt = 1;
        return 0;                   // return -1 for time out ???????????????
    }

    LCD_RW = LCD_RD;
    LCD_RS = LCD_CMD;
    LCD_D4_DIR = 1; LCD_D5_DIR = 1; LCD_D6_DIR = 1; LCD_D7_DIR = 1;

    LCD_ENABLE(); LCD_DELAY_1US();
    LCD_data.bit7 = LCD_D7_IN;
    LCD_DISABLE();
    LCD_ENABLE(); LCD_DELAY_1US();
    LCD_data.bit3 = LCD_D7_IN;
    LCD_DISABLE();

    LCD_D4_DIR = 0; LCD_D5_DIR = 0; LCD_D6_DIR = 0; LCD_D7_DIR = 0;
    LCD_RW = LCD_WR;

    if (LCD_data.bit7 == LCD_BUSY) {
        LCD_busy_cnt++;
        return 1;
    } else {
        LCD_busy_cnt = 1;
        return 0;
    }
}
// -------------------- END LCD-functions ---------------------------


LCD_lib_busy.h
Code:
//##############################################################################
//    filename:        LCD_lib_busy.h
//##############################################################################
//    header file LCD library for HD44780, HD47780, ST7036 ...
//##############################################################################
//
//      Author:            	V.SchK
//      Company:        	HS-Ulm
//
//      Revision:        	1.0
// 	Date:         		June. 2012
//     	Assembled using		C18 3.41+
//
//   	todo	- add comments ;-)
//             	-
//
//##############################################################################
#ifndef _LCD_LIB_BUSY_H
#define _LCD_LIB_BUSY_H 

#include "lcd_config.h" // pin and power configuration file

#ifdef __18CXX      // MPLAB C18 compiler
  #define const const rom
#endif

union LCDv8bit {
    char all;
    struct {
        unsigned LN : 4;
        unsigned HN : 4;
    };
    struct {
        unsigned bit0 : 1;
        unsigned bit1 : 1;
        unsigned bit2 : 1;
        unsigned bit3 : 1;
        unsigned bit4 : 1;
        unsigned bit5 : 1;
        unsigned bit6 : 1;
        unsigned bit7 : 1;
    };
};

#define LCD_RD      1   // read/write select
#define LCD_WR      0
#define LCD_CMD     0   // register selct
#define LCD_DATA    1

#define LCD_BUSY    1   // busy flag logic

#define LCD_ENABLE()    LCD_E = 1;
#define LCD_DISABLE()   LCD_E = 0;
#define LCD_STROBE()    LCD_E = 1; LCD_DELAY_1US(); LCD_E = 0;


    
#define LINE_OFFSET 0x80  // offset for second line if a 2 line display
    
 
void LCD_Init(void);
#define LCD_Clear() LCD_Command(CLEAR_DISPLAY);
void LCD_Write_Nibble(unsigned char value);
void LCD_Write(unsigned char value);
#define LCD_Command    while(LCD_Busy()){;} LCD_RS = LCD_CMD; LCD_Write
#define LCD_Data       while(LCD_Busy()){;} LCD_RS = LCD_DATA; LCD_Write

#define LCD_CharOut             LCD_Data
#define LCD_SetCursor(r,c)      LCD_Command(CURSOR_ADDR + (LINE_OFFSET * r) + c)

void LCD_TextOut(unsigned char row, unsigned char col, unsigned char *text);
void LCD_ConstTextOut(unsigned char row, unsigned char col, const char *text);

#define LCD_ValueOut(a,b,c) LCD_ValueOut_00(a,b,c,1)
void LCD_ValueOut_00(unsigned char row, unsigned char col, short value,
                     unsigned char min_dig);

//unsigned char LCD_Read(void);
unsigned char LCD_Busy(void);
void LCD_signalsTest(void);

// Instruction Set defines (HD44780 compatible)
//                              RS  R/W |   D7  D6  D5  D4  D3  D2  D1  D0
// Clear display                0   0   |   0   0   0   0   0   0   0   1
    #define CLEAR_DISPLAY       0x01
// Return home                  0   0   |   0   0   0   0   0   0   1   -
    #define RETURN_HOME         0x02
// Entry mode set               0   0   |   0   0   0   0   0   1   I/D S
    #define ENTRY_MODE          0x04
    #define CURSOR_INC          0x02
    #define CURSOR_DEC          0x00
    #define DSHIFT_ON           0x01
    #define DSHIFT_OFF          0x00
// Display ctrl                 0   0   |   0   0   0   0   1   D   C   B
    #define DISPLAY_CTRL        0x08
    #define DISPLAY_ON          0x04
    #define DISPLAY_OFF         0x00
    #define CURSOR_ON           0x02
    #define CURSOR_OFF          0x00
    #define BLINK_ON            0x01
    #define BLINK_OFF           0x00
// Cursor / Display shift       0   0   |   0   0   0   1   S/C R/L -   -
    #define DISPLAY_SHIFT_R     0x1C
    #define DISPLAY_SHIFT_L     0x18
    #define CURSOR_MOVE_R       0x14
    #define CURSOR_MOVE_L       0x14

//                              RS  R/W |   D7  D6  D5  D4  D3  D2  D1  D0
// Function Set                 0   0   |   0   0   1   DL  N   F   *   *
//      DL: 1 = 8-Bit   / 0 = 4-Bit interface
//      N:  1 = 2 lines / 0 = 1 line
//      F:  1 = 5x11    / 0 = 5x8 dots  (double hight bit in extended mode !!!)
    #define LCD_RESET           0x30
    #define FOUR_BIT            0x20  // 4-bit Interface
    #define EIGHT_BIT           0x30  // 8-bit Interface not used !!!
    #define FOUR_BIT_ONE_LINE   0x20
    #define FOUR_BIT_TWO_LINE   0x28
//******************************************************************************
// Extended Function Set        0   0   |   0   0   1   DL  N   F   IT1 IT0
//******************************************************************************
    #define EXT_INSTR_TBL_0     0x00
    #define EXT_INSTR_TBL_1     0x01
    #define EXT_INSTR_TBL_2     0x02
// Bias Set                     0   0   |   0   0   0   1   BS  1   0   FX
    #define EXT1_BIAS_1_4       0x1C
    #define EXT1_BIAS_1_5       0x14
// ICON address                 0   0   |   0   1   0   0   a   a   a   a
    #define EXT1_ICON_ADDR      0x40
// Power/ICON Cntrl/Contrast    0   0   |   0   1   0   1   Ion Bon C5  C4
    #define EXT1_BOOST_ICON_C   0x50
    #define ICON_ON             0x08
    #define BOOST_ON            0x04
    #define BOOST_OFF           0
// Follower Ctrl                0   0   |   0   1   1   0   Fon R_2 R_1 R_0
    #define EXT1_FOLLOWER       0x60
    #define FOLLOWER_ON         0x08
    #define FOLLOWER_OFF        0
// Contrast                     0   0   |   0   1   1   1   C3  C2  C1  C0
    #define EXT1_CONTRAST       0x70

// Double height Position       0   0   |   0   0   0   1   UD  -   -   -
    #define EXT2_DHP_TOP        0x18
    #define EXT2_DHP_BOT        0x10
//******************************************************************************

// Set CGRAM address            0   0   |   0   1   a   a   a   a   a   a
    #define CGRAM_ADDR          0x40
// Set DDRAM address            0   0   |   1   a   a   a   a   a   a   a
    #define CURSOR_ADDR         0x80

// Read busy flag (and address) 0   1   |   BF  a   a   a   a   a   a   a

#endif //_LCD_LIB_BUSY_H

lcd_config.h
Code:
//##############################################################################
//    filename:        lcd_config.h
//##############################################################################
//    configuration file for LCD library (pins, voltage, ...)
//##############################################################################
//
//      Author:            	V.SchK
//      Company:        	HS-Ulm
//
//      Revision:        	1.0
// 	Date:         		June. 2012
//     	Assembled using		C18 3.41+
//
//
//##############################################################################

#include <delays.h>

#ifndef _LCD_CONFIG_H
#define _LCD_CONFIG_H

#define LCD_TIMEOUT 100



#define LCD_DELAY_5MS() Delay10KTCYx(1) // 1tcy = 1us (FOSC 4.000.000)
#define LCD_DELAY_1US() Nop()//;Nop();Nop();Nop();
//#warning "be sure to define LCD-Delays properly !!!"


        
        #define	LCD_E		LATBbits.LATB3
        #define	LCD_E_DIR	TRISBbits.TRISB3
        #define	LCD_RW		LATBbits.LATB2
        #define	LCD_RW_DIR	TRISBbits.TRISB2
        #define	LCD_RS		LATBbits.LATB1
        #define	LCD_RS_DIR	TRISBbits.TRISB1

        #define	LCD_D4_IN	PORTBbits.RB4
        #define	LCD_D5_IN	PORTBbits.RB5
        #define	LCD_D6_IN	PORTBbits.RB6
        #define	LCD_D7_IN	PORTBbits.RB7
        #define	LCD_D4_OUT	LATBbits.LATB4
        #define	LCD_D5_OUT	LATBbits.LATB5
        #define	LCD_D6_OUT	LATBbits.LATB6
        #define	LCD_D7_OUT	LATBbits.LATB7
        #define	LCD_D4_DIR	TRISBbits.TRISB4
        #define	LCD_D5_DIR	TRISBbits.TRISB5
        #define	LCD_D6_DIR	TRISBbits.TRISB6
        #define	LCD_D7_DIR	TRISBbits.TRISB7

 

  
#endif //_LCD_CONFIG_H
 
Last edited:

Check the contrast level. Most LCD support a contrast adjustment, implemented by a simple variable resistor voltage divider. Stick VCC and GND on the outside pins of the potentiometer and the middle pin to the contrast control on the LCD. This is how I've solved this problem in my circuits.
 

Which compiler are you using, XC8, C18, HiTech PICC18, etc with the MPLAB IDE?

What is the specific model of PIC you are utilizing in your design?

Many PICs have a Phase Lock Loop (PLL) which can generate a system clock frequency many times that of the crystal frequency.

When driving a device such as an LCD, it is of utmost importance to know the actual system clock frequency, otherwise the required delays will not be accurately produced.

The actual system clock frequency must also be conveyed to the C compiler, typically through the use of a #define or in the case of MikroC a dialog box, so that the compiler can implement the correct code to produce the required delays.

Also, PA3040, brings up an important issue, make sure your configuration registers are properly configured so that there is not a conflict with a port line utilized as the interface to the LCD.

BigDog
 
Reactions: ADGAN

    ADGAN

    Points: 2
    Helpful Answer Positive Rating
I'm using C18. My PIC is PIC18F45K22 with an 4MHz external crystal. Also I'm using the PLL.
 


Although, it is preferable to use a 10kΩ pot in place of a fixed 5kΩ resistor for convenience of adjustment of the contrast, from ADGAN's description of the solid boxes only on the 1st and 3rd rows most likely indicate contrast in this case is not an issue.

The solid boxes only 1st and 3rd rows is a classic indication of improper initialization.

BigDog

- - - Updated - - -

I'm using C18. My PIC is PIC18F45K22 with an 4MHz external crystal. Also I'm using the PLL.

Without me pulling up the PIC18F45K22 datasheet:

What is the configuration of the PLL?

What is the expected system clock frequency (Fosc)?

In the case of the C18 compiler, the delay routines are based on instruction cycles, therefore you'll need calculate the number of instruction cycles to produce a 100ms delay and use the appropriate delay routine to generate the delay to allow the LCD to fully initialize.

You will also need to examine the LCD routine source code you have posted and modify the delay macros for the appropriate Fosc.

Such as:
Code:
/##############################################################################
//    filename:        lcd_config.h
//##############################################################################
//    configuration file for LCD library (pins, voltage, ...)
//##############################################################################
//
//      Author:            	V.SchK
//      Company:        	HS-Ulm
//
//      Revision:        	1.0
// 	Date:         		June. 2012
//     	Assembled using		C18 3.41+
//
//
//##############################################################################

#include <delays.h>

#ifndef _LCD_CONFIG_H
#define _LCD_CONFIG_H

#define LCD_TIMEOUT 100



[COLOR="#FF0000"]#define LCD_DELAY_5MS() Delay10KTCYx(1) // 1tcy = 1us (FOSC 4.000.000)
#define LCD_DELAY_1US() Nop()//;Nop();Nop();Nop();
//#warning "be sure to define LCD-Delays properly !!!"[/COLOR]

....
....


BigDog
 
Thanks for the reply. I have configured the PLL using the configuration bits window of the MPLAB IDE. Fosc is 16MHz. I'm new to MPLAB have some doubts about using MPLAB. I'm modifying a code given by Microchip. I have attached the project folder. In hardwareProfile_Energymeter.h the clock has been defined. But I'm not sure what they have done.

View attachment PIC18F65J90_V11.rar
 

If the Fosc is 16MHz, the PIC18 generates a single instruction cycle for every four Fosc cycles.

Therefore, with a Fosc of 16MHz the instruction "clock" is 4MHz and the instruction cycle period is 250nS.

I prefer to using the configuration register directives to configure a device, rather than use the MPLAB IDE configuration register feature.

Another nice feature of the C18 LCD routines, is that by default the routines are configured to use the busy flag once the device has been properly initialized, so delay routines after the initialization are no longer utilized.

I would also recommend attempting to initially interface the LCD for 8-bit mode, rather than 4-bit mode, once you have successfully interface, configure, driven the LCD in 8-bit mode, you can then attempt to switch to 4-bit mode.

Several small successful steps are always preferred to large steps which fail.

I'll take a look at the code you've uploaded.

BigDog
 
Reactions: ADGAN

    ADGAN

    Points: 2
    Helpful Answer Positive Rating
Please post Proteus DSN file and mansion version
 

For PIC18F use LATx instead of PORTx and also configute TRISx which is used for LCD connections. I don't have Proteus 8. So, post the screen shot of Schematic.


Try the attached code. It is compiled for PIC18F65J90 at 16 MHz external clock. I have used the same LCD connections used in your mikroC code.

 

Attachments

  • LCD PIC18F65J90.rar
    86.8 KB · Views: 89
  • lcd.png
    40.7 KB · Views: 285
Last edited:
Reactions: ADGAN

    ADGAN

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…