Hempl/LCD
Mizar32 LCD 显示屏是一个附加硬件模块,可以插入 Mizar32 主板的六个总线连接器中的任何一个。它有一个 16 列 2 行的液晶显示屏,每个位置可以显示一系列字符中的一个,它有六个按钮:左、右、上、下、选择和重置。
红色重置按钮会重置控制显示屏的板载 PIC 微控制器,而五个按钮可以通过 I2C 总线由主处理器读取。
LCD 显示屏由一个 PIC 16F84 微控制器运行,这是一个低功耗处理器,运行一个由 Simplemachines 编写的程序,该程序与 Ampire 162B LCD 面板对话,检测按钮按下并通过 I2C 总线与主 AVR32 处理器通信。
LCD 面板本身托管另一个微处理器,SED 1278,它接收来自 PIC 的命令,为 LCD 面板生成字符,并保持显示屏刷新。它有一个 40 个字符 2 行的内部字符内存,其中 16x2 在任何时候都显示在 LCD 屏幕上。SED 1278 的程序在 ROM 中,无法更改。
通过 I2C 与 LCD 显示屏通信时,Mizar32 的 I2C 总线速度必须设置为不快于 50kHz。如果 Mizar32 以高达 100kHz 的速度与其他 I2C 设备通信,这不会混淆 LCD 显示屏:它能够以高达 100kHz 的速度识别自己的地址(并拒绝所有其他地址),但只能以最高 50kHz 的速度处理数据包。
LCD 显示屏模块需要 Mizar32 从其 7.2 伏直流电源插座供电。如果你希望从 Mizar32 的 USB 电源供电,你可以在 LCD 板的下方焊接一根电线,从 BUS5 连接器的引脚 1(靠近板边缘的中心)到 LCD1 连接器的引脚 2(靠近“左”按钮)。
该板响应 8 位 I2C 命令字节 0x7C 到 0x7F(7 位从机地址 62 和 63)
命令 | 功能 |
---|---|
0x7C |
向 LCD 发送命令 |
0x7D |
读取 LCD RAM 地址 |
0x7E |
向 LCD 发送数据字节 |
0x7F |
读取按钮开关 |
从物理上来说,LCD 显示屏有 2 行 16 个字符,但从内部来说,它有一个字符内存,它每行保存 40 个字符,而 16x2 可见显示屏只显示内部字符内存的一部分。
打印超出第一行字符内存的第 40 个字符会自动传递到第二行的开头,而超出第二行的第 40 个字符会从第一行的开头继续。类似地,当光标从任何一行的第一个字符向左移动时,会将其移动到另一行的第 40 个位置。
对于 SED1278,命令字节 0 是一个无操作命令。在这里,相反,PIC 将其识别为一个特殊情况,并重置 SED
- 清除屏幕
- 无光标显示器
- 两行字符
- 8x5 像素字符字体
- 发送字符数据时光标向右移动;显示屏不移动
你可以使用以下函数来完成此操作
(mizar32-lcd-reset)
命令字节 1 将空格写入字符内存的每个位置,将光标移动到字符内存的第一行第一列,并重置显示屏移动,以便内部字符内存的每一行的第一个字符与物理显示屏的第一个字符对齐。
(mizar32-lcd-clear)
命令字节 2:返回首页
[edit | edit source]命令字节 2 将光标移动到字符存储区的首行首列,并重置显示屏滚动。它等同于“清除显示屏”,但不会清除字符存储区的内容。
(mizar32-lcd-home)
数据输入模式
[edit | edit source]命令字节 4:打印时,光标向右移动
[edit | edit source]发送命令字节 4 后,在 LCD 显示屏上打印字符会使光标向右移动一个位置:如果光标移出物理显示屏的右边缘,它将继续写入内部字符存储区,但光标以及这些字符不会显示在物理显示屏上。
命令字节 5:打印时,显示屏向右滚动
[edit | edit source]这是另一种反向打印文本的方式,这次保持光标在显示屏上的相同位置,并在每次打印字符时将文本向右滚动一个位置。如果您处于这种模式,光标位于 (1,1),并打印“Hello
”,最终将在第一行的第五个位置得到 H
,并在第二行的前四个位置得到“olle
”,因为从 40 列字符存储区的任何一端移出都会在另一行的另一端继续。
命令字节 6:打印时,光标向左移动
[edit | edit source]发送命令字节 6 后,打印字符会使光标向左移动一个位置,因此如果您打印“Hello”,写入的内容将在显示屏上反向显示为“olleH
”,光标停留在最后一个字符的左侧。要看到这一点,您首先需要将光标移动到显示屏的右侧,否则它会立即移出显示屏的左边缘,只留下一个可见的“H”,并在第二行的末尾打印“olle
”(超出屏幕)。
命令字节 7:打印时,显示屏向左滚动
[edit | edit source]发送命令字节 7 后,每次将字符发送到显示屏时,光标都将停留在相同的物理位置,所有显示的字符都将向左移动一个位置。另一种理解方式是 16x2 的物理显示屏在虚拟显示屏上向右移动一个位置,例如,如果它显示的是 1-16 列,那么它将显示 2-17 列。要看到打印的文本,您首先需要将光标移动到显示屏的右侧,否则您显示的所有内容都将立即从显示屏的左边缘移出,并且只有在打印了另外 24 个字符(24 个是因为虚拟显示屏有 40 个字符宽,而物理显示屏有 16 个字符宽)之后才会在右边缘重新出现。
在 Hempl 中,可以使用以下函数选择这四种选项:
功能 | 函数域 |
---|---|
(mizar32-lcd-setup display-shift right-to-left) |
{T, NIL}
|
默认情况下,显示屏不滚动,字符从左到右打印。
光标模式
[edit | edit source]同时开启或关闭显示屏,并指定想要显示的光标类型。
命令字节 8:关闭显示屏
[edit | edit source]这将关闭显示屏,显示一个空白面板。但是,它会记住 40x2 字符存储区中的数据、用户定义的字符、光标位置以及在物理显示屏上显示的字符存储区的哪一部分。
命令字节 12:开启显示屏,但不显示光标
[edit | edit source]如果显示屏已关闭,则将其重新开启,但不会显示光标。
命令字节 13:开启显示屏并显示闪烁的块状光标
[edit | edit source]如果显示屏已关闭,则将其重新开启,并在光标位置显示一个闪烁的黑块。
命令字节 14:开启显示屏并显示下划线光标
[edit | edit source]如果显示屏已关闭,则将其重新开启,并在光标位置显示字符单元的底线全黑。
命令字节 15:开启显示屏,并显示下划线和闪烁的块状光标
[edit | edit source]在这种情况下,您将获得恒定的下划线和闪烁的块状光标。我不确定您为什么要这样做...
在 Hempl 中,可以使用以下函数选择光标类型:
功能 | 函数域 |
---|---|
(mizar32-lcd-cursor 'what) |
what = {none, line, block}
|
您还可以使用以下代码开启或关闭 LCD 显示屏:
功能 | 函数域 |
---|---|
(mizar32-lcd-display 'what) |
what = {on, off}
|
当您重新开启显示屏时,Alcor6L 会记住光标类型并将其恢复。这适用于所有 Alcor6L 语言。
光标或显示屏滚动
[edit | edit source]还有一种方法可以左右滚动 40 列存储区的可见部分,并将光标左右移动一个位置。
命令字节 16:将光标向左移动一个位置
[edit | edit source]这将光标在存储区和显示屏上同时向左移动一个字符位置。如果它移出显示屏的可见部分,光标将不可见,如果它从第 1 列向左移动,它将移动到另一行的第 40 列。
命令字节 20:将光标向右移动一个位置
[edit | edit source]这将光标在存储区和显示屏上同时向右移动一个字符位置。如果它移出显示屏的可见部分,光标将不可见,如果它从第 40 列向右移动,它将移动到另一行的第 1 列。
在 Hempl 中,可以使用以下代码执行这些操作:
功能 | 函数域 |
---|---|
(mizar32-lcd-cursor 'dir) |
dir = {left, right}
|
命令字节 24:将显示屏向左滚动一个位置
[edit | edit source]这将改变虚拟显示屏的哪一部分在物理显示屏上可见。它将所有可见的字符向左滚动一个位置,并在右边缘显示来自虚拟显示屏的一列新字符。
当移动显示屏时,光标在内部字符内存中的位置保持不变,因此在物理显示屏上也看到它向左移动了一位。
使用命令 28 可以获得相反的效果,它将显示的字符和光标向右移动一位,并在左侧显示两个新字符。同样,光标始终停留在之前所在的字符上。
在 Hempl 中,可以使用以下命令:
功能 | 函数域 |
---|---|
(mizar32-lcd-display 'dir) |
dir = {left, right}
|
这些命令的位 4、8 和 16 设置显示屏的操作模式
位 | 含义 | 值 | |
---|---|---|---|
0 | 1 | ||
4 | 显示字体类型 | 5x8 | 5x11 |
8 | 显示行数 | 1 行 | 2 行 |
16 | 接口数据长度 | 4 位 | 8 位 |
对于 Mizar32 显示模块,您需要 5x8、2 行、4 位,这是上电时的默认设置。
命令字节 64 到 127 将光标从显示屏移动到字符生成器 RAM。以下数据字节不会在屏幕上显示任何内容,而是说明 8 个用户定义字符(代码 0 到 7(以及 8 到 15))中哪些点是透明的,哪些是黑色的。
第一个用户定义字符的定义位于位置 64 到 71,第二个位于 72 到 79,依此类推。每个字节定义一个字符行,从上到下工作,其中 5 个最低有效位定义每行的 5 个像素,按从左到右的顺序 16、8、4、2、1。 "1" 位显示为黑色。
例如,要将字符 0 和 1 定义为指向左边的黑色三角形和指向右边的黑色三角形
1 6 |
8 | 4 | 2 | 1 | 总计 | 1 6 |
8 | 4 | 2 | 1 | 总计 |
---|---|---|---|---|---|---|---|---|---|---|---|
* | 1 | * | 16 | ||||||||
* | * | 3 = 2 + 1 | * | * | 24 = 16 + 8 | ||||||
* | * | * | 7 = 4 + 2 + 1 | * | * | * | 28 = 16 + 8 + 4 | ||||
* | * | * | * | 15 = 8 + 4 + 2 + 1 | * | * | * | * | 30 = 16 + 8 + 4 + 2 | ||
* | * | * | 7 = 4 + 2 + 1 | * | * | * | 28 = 16 + 8 + 4 | ||||
* | * | 3 = 2 + 1 | * | * | 24 = 16 + 8 | ||||||
* | 1 | * | 16 | ||||||||
0 | 0 |
您需要发送命令字节 64,后跟 1、3、7、15、7、3、1、0、16、24、28、30、28、24、16、0,要返回到常规字符写入模式以显示它们,您需要发出 "设置 DD RAM 地址" 命令字节(参见下一条目)。如果字符已显示在屏幕上,则在重新定义时,其形状会立即更改。在 Alcor6L 中,您可以使用以下函数调用完成所有这些操作
对于指向左边的三角形,
(mizar32-lcd-definechar 0 (1 3 7 15 7 3 1) )
对于指向右边的三角形,
(mizar32-lcd-definechar 1 (16 24 28 30 28 24 16) )
与命令字节接口不同,Hempl 的 definechar
函数用于 LCD 会将您切换回正常字符写入模式,并将文本光标保留在其所在的位置。
如果命令字节的最高位被设置,则较低的 7 位设置光标在数据内存中的位置,数据内存是下一个字符将在显示屏的字符内存中存储的位置(以及在显示屏移动时显示该部分字符内存时显示在屏幕上)。
代码 | 光标将移动到的位置 |
---|---|
128-167 | 第一行 40 个字符 |
192-231 | 第二行 40 个字符 |
我不知道如果设置 DD RAM 地址为 168-191 或 232-255 会发生什么。
在 Hempl 中,您可以使用以下命令:
功能 | 函数域 |
---|---|
(mizar32-lcd-goto row column) |
row = {1, 2}, column = {1, 2, .., 40}
|
I2C 命令 0x7D
读取光标在字符内存中的当前位置,并将其通过 I2C 总线发送回。
这是在您发送数据字节时下一个字符将存储的内部内存地址。返回的字节是从 0 到 127 的值,对应于上述 "设置 DD RAM 地址" 命令中使用的代码的较低的 7 位。在 PicoLisp 中,以下函数将返回一个列表,其 car
为 1 或 2,其 cadr
为 1 到 40 之间的值。
(setq pos-tab (mizar32-lcd-getpos) ) (setq row (car pos-tab) # Row number col (cadr pos-tab) ) # Column number
I2C 命令 0x7E
将数据发送到 LCD 显示屏。
您发送的每个数据字节通常都会在 LCD 显示屏上显示一个字符,并将光标向右移动一个位置。
代码 | 它们显示的内容 |
---|---|
0-7 | 8 个用户定义字符 |
8-15 | 相同的 8 个用户定义字符 |
16-31 | 空白 |
32-126 | 标准 ASCII 字符 |
127 | |
128-159 | 空白 |
160-255 | 汉字和特殊符号 |
唯一的例外是当您刚刚发送了命令字节 64-127 之一,这将使以下数据字节设置用户定义字符的像素(参见上面的 "设置 CG RAM 地址")。
在 Hempl 中,您可以使用以下命令:
(mizar32-lcd-prinl data)
其中 data
是一个或多个字符串和数字的列表,以逗号分隔。字符串是显示 ASCII 文本消息的正常方式,而数值数据应具有 0 到 255 之间的值,并显示上述表格中的单个字符。相反,要以十进制形式打印一个整数,您需要先对其进行格式化。例如,如果变量 gen
包含一个适合 3 个字符(0-999)的整数,则可以使用
(mizar32-lcd-prinl (format gen) )
I2C 命令 0x7F
获取 LCD 模块的按钮开关的当前状态,这是一个字节,其中一些组合的较低的 5 位被设置为指示当前按下了哪些按钮。
键 | 选择 | 左 | 右 | 上 | 下 |
位 | 1 | 2 | 4 | 8 | 16 |
显示屏可以可靠地检测到选择按钮是否被按下以及其他四个按钮中的任意两个是否被按下。如果其他三个按钮被按下,模块将返回一个字节,表示所有四个按钮都被按下(这是按钮在电路板上连接方式的结果,使用只有四根线的五根按钮)。
在 Hempl 中,您可以执行以下操作:
(setq lcd-buttons (mizar32-lcd-buttons) )
每个函数都返回一个字符串,其中包含字符 L
、R
、U
、D
和 S
的选择,以说明当前是否按下了左、右、上、下和选择按钮。如果未按下任何按钮,则返回一个空字符串。硬件允许可靠地检测到选择按钮以及其他四个按钮中的最多两个,但如果按下左、右、上和下中的三个按钮,则返回所有四个按钮。
如果您敢于尝试,可以使用上述代码和 eLua 的 i2c
平台模块基元与 LCD 显示模块进行通信。例如,要显示 "Hello
",您可以说
(de mizar32-lcd-write-i2c (x) (i2c-setup 0 50000) (i2c-start 0) (if (not (= 0 (i2c-address 0 63 *i2c-transmitter*))) (i2c-write 0 x) ) (i2c-stop 0) ) (mizar32-lcd-write-i2c 'Hello)
SimpleMachines 在 Hempl 中添加了一个平台模块(Mizar32 的 LCD 模块),如上文所述,它为您完成了所有 I2C 幻术和特殊计时。使用此模块来实现上述功能,您只需说
(mizar32-lcd-prinl 'Hello)
它提供以下函数。
(mizar32-lcd-reset)
初始化显示器,将所有内容重置为初始状态:清除屏幕,无光标,显示 40 列内存中的第 1-16 列,准备在 (1,1) 位置打印,从左到右写入文本,并在每个字符后将光标向右移动一个位置。您不必在程序开始时调用重置,但这样做可以确保即使显示器因先前运行而处于奇怪状态,您的程序仍然可以正常工作。
(mizar32-lcd-setup display-shift right-to-left)
这可以用于设置 LCD 显示器的一些奇怪的操作模式。两个参数都是可选的,如果您省略它们,它们默认值为 false,这将设置合理的模式。
display_shift
:如果为 true,则在您随后打印的每个字符中,光标将像往常一样在字符内存中移动一个位置,但显示器的内容也会在水平方向上向相反方向移动一个位置,以便光标保持在物理显示器的同一列。这可用于实现“滚动文本”效果。但是请注意,当光标从第 40 列移至第 1 列或反之亦然时,它会翻转到另一行。
right_to_left
:如果为 true,则文本将从右到左打印:光标将在字符内存中向左移动一个位置,并且如果也启用了显示器移动,则显示器的内容将向右移动,以便光标保持在屏幕上的同一列。
(mizar32-lcd-clear)
清除显示器,将光标移动到左上角(位置 1,1)并重置显示器移动以显示第 1 到第 16 列。
(mizar32-lcd-home)
将光标移动到左上角(位置 1,1)并重置显示器移动。
(mizar32-lcd-goto row column)
将光标移动到指定的行和列。
row
:一个数字(1 或 2),表示您要移动到的行。column
:一个数字(1 到 40),表示该行中字符内存中的位置。
示例 | 返回值 |
---|---|
(setq lcd-pos (mizar32-lcd-getpos) ) |
(car lcd-pos), (cadr lcd-pos)
|
返回当前光标位置。
符号 | 含义 |
---|---|
row |
一个数字(1 或 2),表示当前行。 |
column |
一个数字(1 到 40),表示字符内存中当前列。 |
(mizar32-lcd-prinl [data1] [data2] ... [datan])
从当前光标位置开始写入 LCD 字符内存。光标将为每个打印的字符前进一个位置。当它超过第 40 列时,它会移动到另一行的第 1 列(反之亦然,当从右到左打印时)。
每个数据项可以是字符串或整数。字符串是显示 ASCII 文本消息的正常方式。整数参数应具有从 0 到 255 的值以显示单个字符,该字符可以是用户定义的字符 0-7、常规 ASCII 字符 32-125 以及 126 和 127(分别用于向右和向左箭头)以及具有代码 160-255 的中文、希腊语和数学符号。
(mizar32-lcd-cursor what)
设置在光标位置显示的光标类型或将光标向左或向右移动。
what
是一个字符串,用于说明应该执行的操作。
- "none"、"line" 或 "block" 将分别在光标位置显示无可见光标、恒定下划线或闪烁的实心方块。
- "left" 或 "right" 将光标在字符内存和显示器上向左或向右移动一个位置,而不会改变底层字符。在这种情况下,显示器永远不会移动,并且像往常一样,光标会在一行的第 40 列和另一行的第 1 列之间包裹。
(mizar32-lcd-display what)
打开或关闭物理显示器,或将显示的字符向左或向右移动。
what
是一个字符串,用于说明应该执行的操作。
- "off" 和 "on" 分别关闭和打开物理显示器。当显示器关闭时,它看起来是空白的,但字符内存的内容、光标的位置和类型、用户定义的字符和设置模式都会被记住,并且您可以在显示器关闭时写入字符内存并执行所有其他操作。这使您能够更新显示器,而不会让观众看到太多闪烁。
- "left" 或 "right" 将显示的字符向左或向右移动一个位置。例如,如果它显示的是通常的第 1-16 列,并且您说 mizar32.lcd.display("left")(或其他语言中的等效代码),那么它将显示第 2-17 列:可见字符向左移动,但字符内存上的窗口向右移动。
(mizar32-lcd-definechar code glyph)
对八个用户可定义字符中的一个进行编程,这些字符的代码为 0 到 7。定义后,可以使用 mizar32.lcd.print(n) 显示字符,其中 n 是从 0 到 7 的数字。如果正在显示的字符是正在显示的字符,则其可见形式将在显示器上立即发生更改。在开机时,8 个字符被定义为随机垃圾。
code
:一个数字(0 到 7),表示您要重新定义的字符。glyph
:一个最多包含八个数字的表,表示字符的八行的位模式,从上到下按顺序排列。这些数字中的每一个都是一个从 0 到 31 的值,用于定义该行中哪个 5 位应该是黑色的。像素从左到右的值分别为 16、8、4、2 和 1。例如,{1, 3, 7, 15, 31, 15, 7, 3, 1, 0} 将在上面的 7 行中定义一个左指的实心三角形。额外的行将被忽略,缺少的行将被空白。
若要使用 PicoLisp 以法语打印,您可以尝试以下操作
# A PicoLisp program to demonstrate # user defined characters. (de print-msg () # clear screen first (mizar32-lcd-clear) # define the French accent character `é'. (mizar32-lcd-definechar 0 (1 2 14 17 31 16 14 0)) # print "Liberté, égalité". (mizar32-lcd-prinl 'Libert 0 ",") (mizar32-lcd-prinl 0 'galit 0 ",") # print fraternité in the next line· (mizar32-lcd-goto 2 1) (mizar32-lcd-prinl 'fraternit 0) ) (print-msg)
请注意:您还可以从我们在 github 上的示例存储库中下载上述代码 french.l
。
(setq buttons (mizar32-lcd-buttons) )
说明当前按下五个用户按钮中的哪一个。
buttons
是一个字符串(在 PicoLisp 中,buttons 是一个列表),包含最多五个字符 L、R、U、D 和 S,表示当前是否按下左、右、上、下和选择按钮。如果没有按下,则返回空字符串。硬件允许可靠地检测选择以及其他四个按钮中的最多两个:如果按下左、右、上和下中的三个,则返回所有四个按钮。
例如,在游戏中使用的代码片段可以是(在 PicoLisp 中)
(setq buttons (mizar32-lcd-buttons)) (if (member "S" (chop buttons)) (do-select) )
- LCD 模块的电路图
- Ampire 的 162B LCD 模块的数据手册
- 将 LCD 与 8051 接口,一篇由 Parveen Kumar 撰写的关于 162B 的文章
- Mizar32 显示模块固件的源代码