You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Arduino非I2C版LCD1602驱动函数的技术咨询

Arduino驱动无I2C接口LCD1602代码详解

我正在学习Arduino,使用不带I2C接口的LCD1602显示屏,手里有一段可实现显示的示例代码,但对其原理尤其是LcdCommandWrite函数的引脚数据传输逻辑存在疑问,希望搞清楚以下问题:

  1. 解释函数循环里的digitalWrite(i,value & 01);和value >>= 1;的作用;
  2. 是否必须按如下方式操作LCD的Enable引脚:
digitalWrite(Enable,LOW);
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1);
digitalWrite(Enable,LOW);
delayMicroseconds(1);
  1. 为什么要用value & 01这类位运算,而不是直接给数字引脚传输HIGH/LOW;
  2. LCD1602执行显示、像素切换的特定命令或序列是什么;
  3. ASCII编码字符如何通过驱动函数传输至LCD1602。

附完整驱动代码:

int DI = 12;
int RW = 11;
int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};// 用数组定义数据总线引脚
int Enable = 2;
void LcdCommandWrite(int value) {
// 配置所有引脚
int i = 0;
for (i=DB[0]; i <= DI; i++) // 给总线赋值
{
digitalWrite(i,value & 01);// 注:1602 LCD实际用D7-D0识别信号,此处做了信号反转
value >>= 1;
}
digitalWrite(Enable,LOW);
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1); // 等待1ms
digitalWrite(Enable,LOW);
delayMicroseconds(1); // 等待1ms
}
void LcdDataWrite(int value) {
// 初始化所有引脚
int i = 0;
digitalWrite(DI, HIGH);
digitalWrite(RW, LOW);
for (i=DB[0]; i <= DB[7]; i++) {
digitalWrite(i,value & 01);
value >>= 1;
}
digitalWrite(Enable,LOW);
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1);
digitalWrite(Enable,LOW);
delayMicroseconds(1); // 等待1ms
}
void setup (void) {
int i = 0;
for (i=Enable; i <= DI; i++) {
pinMode(i,OUTPUT);
}
delay(100);
// 短暂延时后初始化LCD
// LCD控制指令
LcdCommandWrite(0x38); // 8位接口,2行显示,5x7字符尺寸
delay(64);
LcdCommandWrite(0x38); // 重复设置确保初始化成功
delay(50);
LcdCommandWrite(0x38);
delay(20);
LcdCommandWrite(0x06); // 设置输入模式:光标自动递增,不移动显示
delay(20);
LcdCommandWrite(0x0E); // 显示设置:开显示,显示光标,光标不闪烁
delay(20);
LcdCommandWrite(0x01); // 清屏,光标返回初始位置
delay(100);
LcdCommandWrite(0x80); // 设置光标到第一行首位置
delay(20);
}
void loop (void) {
LcdCommandWrite(0x01); // 清屏
delay(10);
LcdCommandWrite(0x80+3); // 光标移到第一行第4个位置(从0开始计数)
delay(10);
// 写入欢迎信息
LcdDataWrite('W');
LcdDataWrite('e');
LcdDataWrite('l');
LcdDataWrite('c');
LcdDataWrite('o');
LcdDataWrite('m');
LcdDataWrite('e');
LcdDataWrite(' ');
LcdDataWrite('t');
LcdDataWrite('o');
delay(10);
LcdCommandWrite(0xc0+1); // 光标移到第二行第2个位置
delay(10);
LcdDataWrite('g');
LcdDataWrite('e');
LcdDataWrite('e');
LcdDataWrite('k');
LcdDataWrite('-');
LcdDataWrite('w');
LcdDataWrite('o');
LcdDataWrite('r');
LcdDataWrite('k');
LcdDataWrite('s');
LcdDataWrite('h');
LcdDataWrite('o');
LcdDataWrite('p');
delay(5000);
LcdCommandWrite(0x01); // 清屏
delay(10);
LcdDataWrite('i');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('m');
LcdDataWrite(' ');
LcdDataWrite('n');
LcdDataWrite('i');
LcdDataWrite('k');
LcdDataWrite('i');
LcdDataWrite('t');
LcdDataWrite('a');
delay(3000);
LcdCommandWrite(0x02); // 设置光标返回 home 位置(不移动显示内容)
delay(10);
LcdCommandWrite(0x80+5); // 光标移到第一行第6个位置
delay(10);
LcdDataWrite('t');
LcdDataWrite('h');
LcdDataWrite('e');
LcdDataWrite(' ');
LcdDataWrite('a');
LcdDataWrite('d');
LcdDataWrite('m');
LcdDataWrite('i');
LcdDataWrite('n');
delay(5000);
}

电路连接图:
LCD1602与Arduino连接电路图


问题解答

1. digitalWrite(i,value & 01); 和 value >>= 1; 的作用

  • value & 01:01是八进制的1,对应二进制00000001,按位与操作会提取value的最低位(第0位),结果要么是1要么是0,刚好匹配Arduino引脚的HIGH/LOW状态。
  • value >>= 1:把value的所有二进制位右移一位,原第1位变为新的最低位,第2位变为第1位,以此类推。配合循环,能依次将value的8个二进制位从最低位到最高位,逐个输出到DB数据总线的引脚。
  • 结合代码注释:LCD1602实际按D7到D0的顺序识别信号,这里循环从DB[0]到DB[7]输出,相当于做了位反转,把原value的最低位传到LCD的D7,最高位传到D0,刚好匹配LCD的信号识别逻辑。

2. 是否必须按指定方式操作Enable引脚

不需要完全照搬,但核心时序逻辑不能改:先拉低Enable,再拉高,最后拉低,这是LCD1602的标准触发机制:

  • 拉低→拉高:触发LCD读取数据总线的内容(命令或数据);
  • 最后拉低:结束触发,让LCD执行对应操作。
  • 代码中的delayMicroseconds(1)是给LCD留响应时间,可根据实际情况调整,但低→高→低的脉冲时序必须保证,否则LCD无法正确读取数据。

3. 为什么用位运算而不是直接传HIGH/LOW

主要有两个原因:

  • 代码简洁高效:一个8位的命令或ASCII码,通过循环+位运算就能一次性把8个二进制位分配到8个DB引脚,不用手动写8次digitalWrite,代码更易维护。
  • 保证时序一致性:LCD1602的DB总线是并行8位,需要同时传输一个字节的所有位,位运算能精准拆分每个位的状态,避免手动赋值时出现的时序偏差,确保数据传输准确。

4. LCD1602执行显示、像素切换的命令/序列

核心显示相关命令:

  • 显示开关控制:0x0C(开显示,无光标)、0x0E(开显示,有光标)、0x0F(开显示,光标闪烁)、0x08(关显示)
  • 清屏:0x01,清除所有显示内容,光标回到初始位置
  • 移位控制:0x18(显示左移)、0x1C(显示右移)、0x10(光标左移)、0x14(光标右移)
  • 像素级操作:LCD1602是字符型显示屏,无法直接单独切换像素,只能通过自定义字符(命令0x40开始写入自定义字符的点阵数据)实现特殊像素组合,或通过显示/隐藏字符间接控制像素。

标准初始化序列(代码已实现):

重复发送0x38(8位接口、2行、5x7字符)3次,然后设置输入模式0x06,开显示0x0E,清屏0x01,最后设置光标起始位置0x80。

5. ASCII字符的传输流程

ASCII字符本质是一个8位字节(比如'W'的ASCII码是0x57),传输流程如下:

  1. 调用LcdDataWrite函数,传入ASCII字符(会自动转为对应的字节值);
  2. 函数先设置DI=HIGH(告知LCD当前传输的是数据而非命令),RW=LOW(设置为写模式);
  3. 通过循环+位运算,将ASCII字节的8个二进制位逐个输出到DB0-DB7引脚(代码中做了反转,对应LCD的D7-D0);
  4. 触发Enable引脚的脉冲,让LCD读取DB总线上的字节;
  5. LCD根据ASCII码从内部字符库中找到对应的5x7点阵,显示在当前光标位置,随后光标自动后移(因初始化时设置了0x06:光标自动递增)。

内容的提问来源于stack exchange,提问作者Nizier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 20:07:02