#lcd #嵌入式-hal #hd44780

无-std liquid_crystal

一个可定制的库,用于与HD44780控制器兼容的字母数字LCD显示器协同工作

7个版本

0.2.0 2024年4月13日
0.1.6 2023年4月24日
0.1.2 2022年12月28日

110嵌入式开发

Download history 175/week @ 2024-04-09 13/week @ 2024-04-16 7/week @ 2024-05-21 1/week @ 2024-06-11

342 每月下载量

MIT 协议

37KB
632 代码行

liquid_crystal

liquid crystal 是一个模块化库,用于与HD44780控制器兼容的字母数字LCD显示器,使用Rust和Embedded_hal API编写

如何使用

第一步

首先,您必须选择一个显示通信接口,该库提供两个内置接口,并行和I2C(您可以在此处 创建自己的接口)

然后,您必须选择通信中的位数,可以是:Bus4Bits或Bus8Bits

最后,您必须选择一个布局(您可以在此处 创建自己的布局)

    let mut lcd_interface = Parallel::new(D4, D5, D6, D7, rs, en, en2);
    let mut lcd = LiquidCrystal::new(&mut interface, Bus4Bits, LCD16X2);

(默认情况下,LCD实现使用阻塞延迟,使用async方法创建具有异步支持的LCD,请记住在库功能中启用异步)

并非所有接口都支持8位通信,但所有支持8位通信的接口都可以支持4位

发送命令和文本

(这可能在将来发生变化,请参阅此处

首先,您必须配置显示。

为此,您必须调用“begin”函数。(您可以直接使用低级“send”函数进行配置,如果您不了解如何配置HD44780,则不推荐这样做)

    lcd.begin(&mut delay);

您可以通过“write”函数发送文本和命令,该函数接收来自延迟函数的引用和一个名为“SendType”的枚举,可以是文本或命令

要发送文本,传递一个 &str 到“Text”变体

要发送命令,从命令列表中传递一个命令到“Command”变体

    lcd.write(&mut delay,Command(Clear))
        .write(&mut delay,Text("hello World!"));

您可以通过“CustomChar”变体发送自定义字符,但首先您需要通过“custom_char”函数创建自定义字符,该函数接收与所有其他函数相同的延迟,一个指向大小为8的u8数组的引用以及它将占据的插槽

HD44780 允许您创建 8 个自定义字符(槽位 0 - 7),您可以在任何时间创建和修改这些槽位,但一次只能同时在显示屏上写入 8 个不同的字符。(创建这些字符会将显示屏返回到初始位置,然后在创建这些字符后使用 "set_cursor")

使用带字符槽位的 CustomChar 变体来发送

    let lightning: [u8; 8] = [0x03, 0x06, 0x0C, 0x1F, 0x1F, 0x03, 0x06, 0x0C];

    lcd.custom_char(&mut delay, &lightning, 0);
    lcd.write(&mut delay, CustomChar(0));

示例

exemple/stm32f1xx/hello.rs

#![no_std]
#![no_main]

use panic_halt as _;
use cortex_m_rt::entry;
use stm32f1xx_hal::{pac, prelude::*};
use liquid_crystal::{prelude::*};
use liquid_crystal::Parallel;

#[entry]
fn main() -> ! {

    //Rust logo
    let rust1: [u8; 8] = [0b00001,0b00011,0b00011,0b01110,0b11100,0b11000,0b01000,0b01000];
    let rust2: [u8; 8] = [0b10001,0b11111,0b00000,0b00000,0b11110,0b10001,0b10001,0b11110];
    let rust3: [u8; 8] = [0b10000,0b11000,0b11000,0b01110,0b00111,0b00011,0b00010,0b000010];

    let rust4: [u8; 8] = [0b01000,0b01000,0b11000,0b11100,0b01110,0b00011,0b00011,0b00001];
    let rust5: [u8; 8] = [0b11000,0b10100,0b10010,0b00000,0b00000,0b00000,0b11111,0b10001];
    let rust6: [u8; 8] = [0b00010,0b00010,0b00011,0b00111,0b01110,0b11000,0b11000,0b10000];

    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = pac::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr);


    let mut gpioc = dp.GPIOC.split();
    let mut gpioa = dp.GPIOA.split();


    let en = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
    let rs = gpioc.pc14.into_push_pull_output(&mut gpioc.crh);
    let d4 = gpioc.pc15.into_push_pull_output(&mut gpioc.crh);
    let d5 = gpioa.pa0.into_push_pull_output(&mut gpioa.crl);
    let d6 = gpioa.pa1.into_push_pull_output(&mut gpioa.crl);
    let d7 = gpioa.pa2.into_push_pull_output(&mut gpioa.crl);

    let mut delay = cp.SYST.delay(&clocks);

    let mut lcd_interface = Parallel::new(d4, d5, d6, d7, rs, en, lcd_dummy);
    let mut lcd = LiquidCrystal::new(&mut lcd_interface, Bus4Bits, LCD16X2);

    lcd.begin(&mut delay);
    lcd.custom_char(&mut delay, &rust1, 0);
    lcd.custom_char(&mut delay, &rust2, 1);
    lcd.custom_char(&mut delay, &rust3, 2);
    lcd.custom_char(&mut delay, &rust4, 3);
    lcd.custom_char(&mut delay, &rust5, 4);
    lcd.custom_char(&mut delay, &rust6, 5);

    lcd.write(&mut delay,Text("hello World!"))
        .write(&mut delay,Command(MoveLine2))
        .write(&mut delay,Text("made in Rust!"));
    lcd.set_cursor(&mut delay, 0, 13)
        .write(&mut delay, CustomChar(0))
        .write(&mut delay, CustomChar(1))
        .write(&mut delay, CustomChar(2));

    lcd.set_cursor(&mut delay, 1, 13)
        .write(&mut delay, CustomChar(3))
        .write(&mut delay, CustomChar(4))
        .write(&mut delay, CustomChar(5));
    loop {}
}

创建自己的接口

要创建自己的接口,您必须实现包含 "send" 函数的 "Interface" Trait

"send" 函数接收两个 u8 参数,"data" 和 "config",其中它们的位表示

BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0
DATA D7 D6 D5 D4 D3 D2 D1 D0
CONFIG 保留 保留 保留 保留 EN2 EN R/W RS

(目前还没有读取功能,所以将 R/W 引脚拉低)(Reserved对应于 I2C 模块中的显示屏背光)

其中 0 和 1 表示引脚的状态 1:HIGH 0:LOW 将位连接到相应的端口,并祝贺您已创建自己的接口

(要使用 PCF8574,您可以复制此行 let package = (config & 0b00000111) | (data & 0xF0) | 0x08; 并通过您选择的 I2C 库发送它)

命令列表

Clear 清除显示屏

Reset 重置显示屏的内部变量

ShiftCursotLeft 将光标移到左边

ShiftCursotRight 将光标移到右边

ShiftDisplayLeft 将显示屏向左移动

ShiftDisplayRight 将显示屏向右移动

MoveLine1 将光标移动到控制器的第一行开头

MoveLine2 将光标移动到控制器的第二行开头

配置函数

echo 启用所有显示屏

select_lcd 选择显示屏(0 = EN1 | 1 = EN2)

enable_blink 启用闪烁光标

enable_cursor 启用光标

enable_display 启用显示屏

enable_autoscroll 启用自动滚动

disable_blink 禁用闪烁光标

disable_cursor 禁用光标

disable_display 禁用显示屏

disable_autoscroll 禁用自动滚动

set_autoscroll_increment 自动滚动增加位置

set_autoscroll_decrement 自动滚动减少位置

update_config 将配置发送到显示屏

布局

您可以使用 Layout 结构体创建自定义布局。

创建自定义布局非常有用,如果您想使用数字字母 LCD 创建用户界面。

HD44780 支持总共 2 行和最多 40 列,每行都有一个地址。

行 1 = 0x80 行 2 = 0xC0

许多 LCD 将这些行和列重新排列以更改布局,例如

针对20X4显示屏的工作,每行的40列分为两个20列,访问它需要使用行地址加上20的偏移量,因此行组织如下

行1 = 0x80 行2 = 0xC0 行3 = 0x80 + 20 行4 = 0xC0 + 20

您可以使用struct Layout创建它!

Layout接受两个泛型参数COLUMNS和LINES,在这个struct内部有一个u8数组和LINE大小

每个位置代表Layout中的一行,只需按照下面的示例放置地址即可

const LCD16X2: Layout<16,2> = Layout{
    addrs: [0x80, 0xC0],
};

const LCD20X4: Layout<20,4> = Layout{
    addrs: [0x80, 0xC0, 0x80+20, 0xC0+20],
};

(注意,如果您不想使用所有40列,则不必使用)

为什么是这个API?

我长期使用lcd显示屏,每次需要使用一些IO扩展器时,我总是需要重写驱动程序,因为当前API没有提供简单的通信移植方式。

此API目前是使用嵌入式_hal进行个人测试,当前语法可能会根据用户反馈而更改。

  • "write"方法可能被分成几个函数,包括新的写入数据方法,就像其C++版本:"omnicrystal"(Arduino)和UniversalLCD。

  • 正在审查对使用保留的"config"位进行用户自定义功能的支持(这个主要想法是多色显示屏的使用)

依赖项

~62KB