Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[51] 16x2 LCD black boxes!

Status
Not open for further replies.

darkfall94

Newbie level 6
Joined
Nov 8, 2014
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
126
Hello,
My project is interfacing a keypad & LCD with microcontroller i.e i press the button on my keypad and the LCD displays the number and number of times the key is pressed.


If you see the above code,it uses a header file lcd.h
The code for the header file is:


Code dot - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//LCD Module Connections
extern bit RS;                                                                   
extern bit EN;                           
extern bit D0;
extern bit D1;
extern bit D2;
extern bit D3;
extern bit D4;
extern bit D5;
extern bit D6;
extern bit D7;
//End LCD Module Connections 
 
 
void Lcd_Delay(int a)
{
    int j;
    int i;
    for(i=0;i<a;i++)
    {
        for(j=0;j<100;j++)
        {
        }
    }
}
 
//LCD 8 Bit Interfacing Functions
void Lcd8_Port(char a)
{
    if(a & 1)
        D0 = 1;
    else 
        D0 = 0;
    
    if(a & 2)
        D1 = 1;
    else
        D1 = 0;
    
    if(a & 4)
        D2 = 1;
    else
        D2 = 0;
    
    if(a & 8)
        D3 = 1;
    else
        D3 = 0;
    
    if(a & 16)
        D4 = 1;
    else
        D4 = 0;
 
    if(a & 32)
        D5 = 1;
    else
        D5 = 0;
    
    if(a & 64)
        D6 = 1;
    else 
        D6 = 0;
    
    if(a & 128)
        D7 = 1;
    else
        D7 = 0;
}
void Lcd8_Cmd(char a)
{ 
  RS = 0;             // => RS = 0
  Lcd8_Port(a);             //Data transfer
  EN  = 1;             // => E = 1
  Lcd_Delay(5);
  EN  = 0;             // => E = 0
}
 
Lcd8_Clear()
{
      Lcd8_Cmd(1);
}
 
void Lcd8_Set_Cursor(char a, char b)
{
    if(a == 1)
      Lcd8_Cmd(0x80 + b);
    else if(a == 2)
        Lcd8_Cmd(0xC0 + b);
}
 
void Lcd8_Init()
{
    Lcd8_Port(0x00);
    RS = 0;
    Lcd_Delay(200);
    ///////////// Reset process from datasheet /////////
  Lcd8_Cmd(0x30);
    Lcd_Delay(50);
  Lcd8_Cmd(0x30);
    Lcd_Delay(110);
  Lcd8_Cmd(0x30);
  /////////////////////////////////////////////////////
  Lcd8_Cmd(0x38);    //function set
  Lcd8_Cmd(0x0C);    //display on,cursor off,blink off
  Lcd8_Cmd(0x01);    //clear display
  Lcd8_Cmd(0x06);    //entry mode, set increment
}
 
void Lcd8_Write_Char(char a)
{
   RS = 1;             // => RS = 1
   Lcd8_Port(a);             //Data transfer
   EN  = 1;             // => E = 1
   Lcd_Delay(5);
   EN  = 0;             // => E = 04
}
 
void Lcd8_Write_String(char *a)
{
    int i;
    for(i=0;a[i]!='\0';i++)
     Lcd8_Write_Char(a[i]);
}
 
void Lcd8_Shift_Right()
{
    Lcd8_Cmd(0x1C);
}
 
void Lcd8_Shift_Left()
{
    Lcd8_Cmd(0x18);
}
//End LCD 8 Bit Interfacing Functions





The only change i made is connect pin 3 of lcd i.e vee to +VCC=5V due to unavailability of a potentiometer.
I simulated the circuit with the code on Proteus software and it works like a charm--perfect!

but now when i supply power to circuit, the lcd displays black boxes..

lcd is jhd162a

here's the link for its datasheet:

http://www.itron.com.cn/PDF_file/JHD162A%20SERIES.pdf

i gave pin16 of lcd gnd and pin15 VCC for the backlight.

what could be the problem?
 
Last edited by a moderator:

Hi,

Try putting Vee down to 0v , or create a potential divider with 2 resistors to give about 0.7v to Vee.

Don't think Proteus uses Vee even if you place a voltage on it.


Always triple check your lcd wiring, its probably the most common cause of errors.
 

vee is a voltage proportionaly to brighness
that's why you see nothing. Try to connect it to gnd. Sometimes it works fine, but usually need some voltage devider. I'm using PWM with RC chain to make an programmable brighness from menu.
 

but now when i supply power to circuit, the lcd displays black boxes..

what could be the problem?

Are the black boxes only visible on the top row? A single row like the following image?



If so, it is most likely a configuration or initialization issue.

If not, i.e., all rows are filled with black boxes, then the issue maybe related to the contrast control as mentioned previously by the other members.

One possible cause of an initialization issue is the following sections of code:


Delay Routine
Code:
void Lcd_Delay(int a)
{
    int j;
    int i;
    for(i=0;i<a;i++)
    {
        for(j=0;j<100;j++)
        {
        }
    }
}

LCD Initialization Routine
Code:
void Lcd8_Init()
{
    Lcd8_Port(0x00);
    RS = 0;
    [COLOR="#FF0000"]Lcd_Delay(200);[/COLOR]
    ///////////// Reset process from datasheet /////////
  Lcd8_Cmd(0x30);
    Lcd_Delay(50);
  Lcd8_Cmd(0x30);
    Lcd_Delay(110);
  Lcd8_Cmd(0x30);
  /////////////////////////////////////////////////////
  Lcd8_Cmd(0x38);    //function set
  Lcd8_Cmd(0x0C);    //display on,cursor off,blink off
  Lcd8_Cmd(0x01);    //clear display
  Lcd8_Cmd(0x06);    //entry mode, set increment
}

The initial delay highlighted in RED essentially allows the LCD controller to fully initialize and arrive at a know state, while the required delay for the controller to fully initialize varies from manufacturer, supply voltage, temperature, etc, a good starting point is 50ms, supplying a longer delay than required has not ill effects, however a shorter delay than required can often result in a single row of black boxes across the top row of the display.

Generating a delay with C language loop structures can often lead to unexpected results. Some compilers have been known to optimize such delay routines essentially out of existence.

I do not see the specific microcontroller or compiler used mentioned. What are they?


BigDog
 

Its a AT89C51 Microcontroller
I am using keil uvision as my compiler as it also allows me to create hex file for programming the device.

As far as the black boxes are concerned, its a bit strange coz
ideally when i should power on the circuit, the Lcd should initialize with the following message:

Keys pressed:
Times:

Thus it should occupy both the rows of lcd as soon as i power on the ckt,
but in my case the black boxes appear only on the 2nd row, there is absolutely no display on the first row.

So, what do you think is the problem?

- - - Updated - - -

ok...i will try connecting vee to ground...
as far as the black boxes are concerned,
ideally when i power on the ckt, the foll message should appear on lcd

Keys pressed:
Times:

Thus occupying both rows on powering the ckt.
But in my case I get black boxes only on the second row,and absolutely no display on the first one!

I find it strange, what do you think?

For reference,
i am using AT89C51 microcontroller and
Keil uVision as the compiler which allows me to compile and also create the HEX file for programming the microcontroller.
 

I do not see the specific microcontroller or compiler used mentioned. What are they?


BigDog

Its a AT89C51 Microcontroller
I am using keil uvision as my compiler as it also allows me to create hex file for programming the device.

- - -updated - -

Are the black boxes only visible on the top row? A single row like the following image?



If so, it is most likely a configuration or initialization issue.

If not, i.e., all rows are filled with black boxes, then the issue maybe related to the contrast control as mentioned previously by the other members.

One possible cause of an initialization issue is the following sections of code:


Delay Routine
Code:
void Lcd_Delay(int a)
{
    int j;
    int i;
    for(i=0;i<a;i++)
    {
        for(j=0;j<100;j++)
        {
        }
    }
}

LCD Initialization Routine
Code:
void Lcd8_Init()
{
    Lcd8_Port(0x00);
    RS = 0;
    [COLOR="#FF0000"]Lcd_Delay(200);[/COLOR]
    ///////////// Reset process from datasheet /////////
  Lcd8_Cmd(0x30);
    Lcd_Delay(50);
  Lcd8_Cmd(0x30);
    Lcd_Delay(110);
  Lcd8_Cmd(0x30);
  /////////////////////////////////////////////////////
  Lcd8_Cmd(0x38);    //function set
  Lcd8_Cmd(0x0C);    //display on,cursor off,blink off
  Lcd8_Cmd(0x01);    //clear display
  Lcd8_Cmd(0x06);    //entry mode, set increment
}

The initial delay highlighted in RED essentially allows the LCD controller to fully initialize and arrive at a know state, while the required delay for the controller to fully initialize varies from manufacturer, supply voltage, temperature, etc, a good starting point is 50ms, supplying a longer delay than required has not ill effects, however a shorter delay than required can often result in a single row of black boxes across the top row of the display.

Generating a delay with C language loop structures can often lead to unexpected results. Some compilers have been known to optimize such delay routines essentially out of existence.


BigDog

i will try connecting vee to ground...
as far as the black boxes are concerned,
ideally when i power on the ckt, the following message should appear on lcd

Keys pressed:
Times:

Thus occupying both rows on powering the ckt.
But in my case I get black boxes only on the second row,and absolutely no display on the first one!

I find it strange, what do you think?
 
Last edited by a moderator:

After studying the linked datasheet it seems your LCD does not a usual type.

(1) It expects a serial resistor between its Vee (pin 3) and the ground, named as RLCD on the circuit, and no any resistor divider. May be 1...10k? Try it.

(2) Here are pullup resistors also on the LCD data bus, named as RESx8, but I think only if P0 is used since it doesn't have internal pullups.

(3) The datasheet contains an example C code also (AT89C51 running at 12 MHz). Look at the recommended delays, maybe this is your main problem.

Seems it is not an efficient program but shows the basic differencies compared to an usual LCD, especially the RAM addressing of the cursor positioning function (can be used with larger LCDs too):


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//from the source in datasheet:
void lcd_moveto(char position) { 
  register cmd=0x80;
  lcdcounter=position;
  if (position > 59)
    position += 0x18;
  else {
    if (position > 39)
      position -= 0x14;
    else {
      if (position > 19)
        position += 0x2c; // !!
    }
  }
  cmd=cmd|position;
  lcd_wrcmd(cmd); 
}

 
Last edited:

Use this LCD code but adjust the Delay_us() and Delay_Ms() functions to generate proper delays. For strobe 500 us is enough.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <regx52.h>
 
sbit LCD_RS = P2^0;
sbit LCD_EN = P2^1;
sbit LCD_D7 = P2^5;
sbit LCD_D6 = P2^4;
sbit LCD_D5 = P2^3;
sbit LCD_D4 = P2^2;
 
#define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
#define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
#define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
#define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
#define _LCD_CLEAR              0x01     //Clear display
#define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a shifted display to
                                         //its original position. Display data RAM is unaffected.
#define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
#define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
#define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
#define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing display data RAM
#define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing display data RAM
#define _LCD_TURN_ON            0x0C     //Turn Lcd display on
#define _LCD_TURN_OFF           0x08     //Turn Lcd display off
#define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing display data RAM
#define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing display data RAM
 
#define EN_Delay 500
 
char strLCDData[7];
 
void Delay_us(unsigned int value) {
 
        unsigned int x,y;
    
        for(x=0;x<value;x++)
            for(y=0;y<1;y++);
}
 
#define LCD_STROBE {LCD_EN = 1; Delay_us(EN_Delay); LCD_EN = 0; Delay_us(EN_Delay);};
 
void Delay_ms(unsigned int value) {
 
        unsigned int x,y;
    
        for(x=0;x<value;x++)
            for(y=0;y<2;y++);
}
 
void LCD_Cmd(unsigned char Command) {
 
    LCD_RS = 0;           // It is a command
 
    LCD_D4 = (Command & 0x10)?1:0;
    LCD_D5 = (Command & 0x20)?1:0;
    LCD_D6 = (Command & 0x40)?1:0;
    LCD_D7 = (Command & 0x80)?1:0;
    LCD_STROBE
    LCD_D4 = (Command & 0x01)?1:0;
    LCD_D5 = (Command & 0x02)?1:0;
    LCD_D6 = (Command & 0x04)?1:0;
    LCD_D7 = (Command & 0x08)?1:0;
    LCD_STROBE
 
    if(Command == 0x01)
    Delay_ms(2);              // Delay for cursor to return at zero position
}
 
 
void LCD_Ch(unsigned int row, unsigned int col, char LCDChar) {
 
    switch(row){
 
        case 1:
        LCD_Cmd(0x80 + col-1);
        break;
        case 2:
        LCD_Cmd(0xC0 + col-1);
        break;
        case 3:
        LCD_Cmd(0x94 + col-1);
        break;
        case 4:
        LCD_Cmd(0xD4 + col-1);
        break;
    }
 
    LCD_RS = 1;               // It is data
 
    LCD_D4 = (LCDChar & 0x10)?1:0;
    LCD_D5 = (LCDChar & 0x20)?1:0;
    LCD_D6 = (LCDChar & 0x40)?1:0;
    LCD_D7 = (LCDChar & 0x80)?1:0;
    LCD_STROBE
    LCD_D4 = (LCDChar & 0x01)?1:0;
    LCD_D5 = (LCDChar & 0x02)?1:0;
    LCD_D6 = (LCDChar & 0x04)?1:0;
    LCD_D7 = (LCDChar & 0x08)?1:0;
    LCD_EN = 1;
    LCD_STROBE
}
 
 
void LCD_Init() {
 
    LCD_RS = 0;
    LCD_EN = 0;
    
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    ///////////////// Reset process from datasheet //////////////
    Delay_ms(30);
 
    //Make Data pins zero
 
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    //Write 0x3 value on data bus
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(6);
 
    //Make Data pins zero
 
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    //Write 0x3 value on data bus
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(3);
 
    //Make Data pins zero
 
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    //Write 0x3 value on data bus
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(2);
 
    //Make Data pins zero
 
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    //Write 0x2 value on data bus
    LCD_D4 = 0;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    Delay_ms(2);
    /////////////// Reset Process End ////////////////
    LCD_Cmd(0x28);    //function set
    LCD_Cmd(0x0C);    //display on,cursor off,blink off
    LCD_Cmd(0x06);    //entry mode, set increment
}
 
void LCD_Out(unsigned int row, unsigned int col, char *str)
{
    while(*str)
    LCD_Ch(row,col++,*str++);   // print first character on LCD
    row = 1;
    col = 1;
}
 
void main() {
 
     P0 = 0x00;
     P1 = 0xFF;
 
     P2 = 0x00;
     P3 = 0x00;
     
     LCD_Init();
     LCD_Cmd(_LCD_CURSOR_OFF);
     LCD_Cmd(_LCD_CLEAR);
     LCD_Out(1,1,"LCD 4 bit");
     
     while(1) {
 
     }
}

 

as far as the black boxes are concerned,
ideally when i power on the ckt, the following message should appear on lcd

Keys pressed:
Times:

Thus occupying both rows on powering the ckt.
But in my case I get black boxes only on the second row,and absolutely no display on the first one!

I find it strange, what do you think?

In other words the situation is exactly opposite of the image I posted?

If so, that is odd.

Are you sure your LCD is not mounted upside down?

BigDog
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top