I have been using a 16x2 LCD display no. MC1602F-SYR for some time and
I think I understand its features. However, I hit a new one today.
I am sending data to the display 4 bits (one nibble) at a time, and I
know I must wait 40us between each transmission. What I am doing is
sending the first nibble, going off to do something else, and then
coming back to send the second nibble. The sequence is:
Set up first nibble
Enable LCD (make EN = 1), wait short time, disable LCD (make EN = 0)
Do something else that takes at least 40us
Set up second nibble
Enable LCD, wait short time, disable LCD
The problem arises when I am doing something else. The LCD is on
a bus so while I am doing something else its inputs may change.
However, so long as EN = 0 I would have thought that would be OK.
But it's not.
I have reduced the problem to this short section of assembler
(PIC18F4550):
(**) Problem instruction
The instruction time is 83.33ns and I am sending a special
character I made up in CG RAM address 0.
This fails. The reason is that I change R/W half way through (see (**)).
It also fails if I change RS half way through. I can change DB7-4 without
a problem. If I replace the "btg LCD_R_W" with a "nop" it all works fine.
I would really like to be able to do something else between writing
each of the nibbles because I cannot afford to wait for 40us doing
nothing. Is there any way around this problem?
Martin
I think I understand its features. However, I hit a new one today.
I am sending data to the display 4 bits (one nibble) at a time, and I
know I must wait 40us between each transmission. What I am doing is
sending the first nibble, going off to do something else, and then
coming back to send the second nibble. The sequence is:
Set up first nibble
Enable LCD (make EN = 1), wait short time, disable LCD (make EN = 0)
Do something else that takes at least 40us
Set up second nibble
Enable LCD, wait short time, disable LCD
The problem arises when I am doing something else. The LCD is on
a bus so while I am doing something else its inputs may change.
However, so long as EN = 0 I would have thought that would be OK.
But it's not.
I have reduced the problem to this short section of assembler
(PIC18F4550):
Code:
bcf DB7 ; Set bits DB7-4 to 0000
bcf DB6
bcf DB5
bcf DB4
bcf LCD_R_W ; Make R_W = 0
bsf LCD_RS ; Make R/S = 1
nop ; Short extra wait to ensure data is stable
bsf EN_LCD ; Set enable bit, EN_LCD
nop ; Short extra wait
nop
nop
nop
nop
bcf EN_LCD ; Clear enable bit, EN_LCD
call Delay20us ; 20us delay. Half of 40us
[COLOR="Red"]btg LCD_R_W ; Toggle R/W. EN is 0 at this point (**)[/COLOR]
nop
[COLOR="red"]btg LCD_R_W ; Toggle R/W again. EN is still zero (**)[/COLOR]
nop
call Delay20us ; 20us delay. The other half of 40us
bcf DB7 ; Set bits DB7-4 to 0000
bcf DB6
bcf DB5
bcf DB4
bcf LCD_R_W ; Make R/W = 0
bsf LCD_RS ; Make RS = 1
nop ; Short extra wait to ensure data is stable
bsf EN_LCD ; Set enable bit, EN_LCD
nop ; Short extra wait
nop
nop
nop
nop
bcf EN_LCD ; Clear enable bit, EN_LCD
The instruction time is 83.33ns and I am sending a special
character I made up in CG RAM address 0.
This fails. The reason is that I change R/W half way through (see (**)).
It also fails if I change RS half way through. I can change DB7-4 without
a problem. If I replace the "btg LCD_R_W" with a "nop" it all works fine.
I would really like to be able to do something else between writing
each of the nibbles because I cannot afford to wait for 40us doing
nothing. Is there any way around this problem?
Martin
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.