通过 I2C 将数据写入 16x2 LCD 的协议

Protocol for writing data to 16x2 LCD via I2C

我是电子学新手,已完成有关如何使用 liquidCrystal_I2C 在 Arduino 中通过 I2C 操作 16x2 字符 LCD 的教程。一切正常,但我对 I2C 和 LCD 之间的低级交互有疑问。查看库的源代码,我注意到在编写 4 位半字节 (LiquidCrystal_I2C::write4bits) 时,代码首先将半字节写入 I2C 扩展器 (LiquidCrystal_I2C::expanderWrite),然后在对启用位施加脉冲时再次写入 。为什么第一个 expanderWrite 是必要的?为什么 write4bits 不能只调用 pulseEnable(设置了 blacklight 位)?

我确定这是有原因的,因为我检查了 RPLCD 等其他库并看到了类似的模式。谁能启发我?谢谢。

datasheet我发现LCD在通信协议中需要特定的时序。 在使能线的上升沿,寄存器 Select 和 Read/Write 线必须已经稳定为 tsu1 (100ns)。在使能线的下降沿,数据必须已经稳定为 tsu2 (60ns)。通过写 _data 他们也写了 RS 和 R/W 行,因为它们是 _data.

的低半字节

This article 非常全面地涵盖了主题。

//**** From LiquidCrystal_I2C.h
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En B00000100  // Enable bit
#define Rw B00000010  // Read/Write bit
#define Rs B00000001  // Register select bit
//              ^--------Backlight bit defined above
//          ^^^^---------Data bits

//**** From LiquidCrystal_I2C.cpp
void LiquidCrystal_I2C::write4bits(uint8_t value) {
    expanderWrite(value);
    pulseEnable(value);
}

void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
    Wire.beginTransmission(_addr);
    Wire.write((int)(_data) | _backlightval);
    Wire.endTransmission();
}

void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
    expanderWrite(_data | En);  // En high
    delayMicroseconds(1);       // enable pulse must be >450ns

    expanderWrite(_data & ~En); // En low
    delayMicroseconds(50);      // commands need > 37us to settle
}