作者: Levent S。 翻译:Aweay
编码
在你开始编码前,你需要了解基本的HD44780控制器指令。下表是来自日立网站上的介绍,为了好理解,我加入了一些额外的信息。
Instruction
Code
Description
Execution time**
RS
R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
Clear display
0
0
0
0
0
0
0
0
0
1
Clears display and returns cursor to the home position (address 0)。
1。64mS
Cursor home
0
0
0
0
0
0
0
0
1
*
Returns cursor to home position (address 0)。 Also returns display being shifted to the original position。 DDRAM contents remains unchanged。
1。64mS
Entry mode set
0
0
0
0
0
0
0
1
I/D
S
Sets cursor move direction (I/D), specifies to shift the display (S)。 These operations are performed during data read/write。 I/D = 0 --> cursor is in decrement position。 I/D = 1 --> cursor is in increment position。 S = 0 --> Shift is invisible。 S = 1 --> Shift is visible
40uS
Display On/Off control
0
0
0
0
0
0
1
D
C
B
Sets On/Off of all display (D), cursor On/Off (C) and blink of cursor position character (B)。 D = 0 --> Display off。 D = 1 --> Displan on。 C = 0 --> Cursor off。 C = 1 --> Cursor on。 B = 0 --> Cursor blink off。 B = 1 --> Cursor blink on。
40uS
Cursor/display shift
0
0
0
0
0
1
S/C
R/L
*
*
Sets cursor-move or display-shift (S/C), shift direction (R/L)。 DDRAM contents remains unchanged。 S/C = 0 --> Move cursor。 S/C = 1 --> Shift display。 R/L = 0 --> Shift left。 R/L = 1 --> Shift right
40uS
Function set
0
0
0
0
1
DL
N
F
*
*
Sets interface data length (DL), number of display line (N) and character font(F)。 DL = 0 --> 4 bit interface。 DL = 1 --> 8 bit interface。 N = 0 --> 1/8 or 1/11 Duty (1 line)。 N = 1 --> 1/16 Duty (2 lines)。 F = 0 --> 5x7 dots。 F = 1 --> 5x10 dots。
40uS
Set CGRAM address
0
0
0
1
CGRAM address
Sets the CGRAM address。 CGRAM data is sent and received after this setting。
40uS
Set DDRAM address
0
0
1
DDRAM address
Sets the DDRAM address。 DDRAM data is sent and received after this setting。
40uS
Read busy-flag and address counter
0
1
BF
CGRAM / DDRAM address
Reads Busy-flag (BF) indicating internal operation is being performed and reads CGRAM or DDRAM address counter contents (depending on previous instruction)。 I used some delay functions in my code which are ThreadSleep if you don't want to use these you can check the Busy Flag and make your LCD speedy。 BF = 0 --> Can accept instruction。 BF = 1 --> Internal operation in progress no additional operation can be accepted。
0uS
Write to CGRAM or DDRAM
1
0
write data
Writes data to CGRAM or DDRAM。
40uS
Read from CGRAM or DDRAM
1
1
read data
Reads data from CGRAM or DDRAM。
40uS
* = Not important, Can be "1" or "0"
** = Execution Time is a time needed which the LCD needs for the operation。
CGRAM is character generator RAM, this ram can hold user defined graphic characters。 This capability gains these modules popularity because of this you can make bargraphs and your own language's special characters(Maybe Chinese, Korean, Turkish, Greek, etc。)。
DDRAM is the Display Data RAM for these modules which represents the hexadecimal Display data adresses。 See below:
Char。
Line 1
Line 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
80
81
82
83
84
85
86
87
88
89
8A
8B
8C
8D
8E
8F
C0
C1
C2
C3
C4
C5
C6
C7
C8
C9
CA
CB
CC
CD
CE
CF
至此,我们已经知道了足够的信息,现在我们可以编写代码让我们的LCD活动起来了。在我的程序里,有三个非常重要的函数:Prepare_LCD|move_to_specific|button_Write_to_Screen_Click。
下面的代码是Prepare_LCD函数:
private void Prepare_LCD(int cursor_status)
{
/* Look at the instruction table to make these comments make sense */
/* Thread。Sleep() function is not needed for some type of LCD instructions
* and also this is changeable from an LCD
* to another so tryout the best for your module */
/* Sends 12(d) = 1100 binary to open the entire display and
* makes a delay that LCD needs for execution */
if(cursor_status == 0)
PortAccess。Output(data, 12); //Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Sends 14(d) = 1110 binary to open the entire display
* and makes the cursor active and also
* makes a delay that LCD needs for execution */
if(cursor_status == 1)
PortAccess。Output(data, 14); //Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Sends 15(d) = 1111 binary to open the entire display, makes
* the cursor active and blink and also
* makes a delay that LCD needs for execution */
if(cursor_status == 2)
PortAccess。Output(data, 15); //Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess。Output(control, 8); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess。Output(control, 9); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Clears entire display and sets DDRAM address
* 0 in address counter */
PortAccess。Output(data, 1); //Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess。Output(control, 8); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess。Output(control, 9); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* We are setting the interface data length to 8 bits
* with selecting 2-line display and 5 x 7-dot character font。
* Lets turn the display on so we have to send */
PortAccess。Output(data, 56); //Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess。Output(control, 8); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess。Output(control, 9); Thread。Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
}
move_to_specific函数可以移动光标到屏幕上任何位置:
private void move_to_specific(int line, int column)
{
/* Makes the RS pin low */
PortAccess。Output(control, 8); //Thread。Sleep(1);
if(line == 1)
{
/* Sets RAM address so that the cursor is positioned
* at a specific column of the 1st line。 */
PortAccess。Output(data, 127+column); //Thread。Sleep(1);
}
if(line == 2)
{
/* Sets RAM address so that the cursor
* is positioned at a specific column of the 2nd line。 */
PortAccess。Output(data, 191+column); //Thread。Sleep(1);
}
}
看下面的Ascii码和二进制码转换表,你可以明白button_Write_to_screen_Click函数的作用:
现在你可以看看这个函数到底是如何实现的,我不打算把代码放在这里,因为我不想让我的这篇文章难于阅读。
注意:如果LCD执行的时间非常快,你可以激活Thread。Sleep函数。
写在最后
有人可能要问“我自己编写程序控制LCD有什么好处?”其实这完全是个人爱好,但如果想象一下,我们用自己编写的LCD显示从网络上获取的CodeProject的新闻,那是多么美妙的事情。
关于译者Aweay
是学生。他目前大四,对基于组件技术的软件设计有深入研究。任CSDN C++Builder板块版主,可以通过 siney@yeah。net 与他联系,同时欢迎你访问他的网站 http://siney。yeah。net。