关于Arduino非I2C版LCD1602驱动函数的技术咨询
Arduino驱动无I2C接口LCD1602代码详解
我正在学习Arduino,使用不带I2C接口的LCD1602显示屏,手里有一段可实现显示的示例代码,但对其原理尤其是LcdCommandWrite函数的引脚数据传输逻辑存在疑问,希望搞清楚以下问题:
- 解释函数循环里的
digitalWrite(i,value & 01);和value >>= 1;的作用; - 是否必须按如下方式操作LCD的Enable引脚:
digitalWrite(Enable,LOW); delayMicroseconds(1); digitalWrite(Enable,HIGH); delayMicroseconds(1); digitalWrite(Enable,LOW); delayMicroseconds(1);
- 为什么要用
value & 01这类位运算,而不是直接给数字引脚传输HIGH/LOW; - LCD1602执行显示、像素切换的特定命令或序列是什么;
- 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); }
电路连接图:
问题解答
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),传输流程如下:
- 调用
LcdDataWrite函数,传入ASCII字符(会自动转为对应的字节值); - 函数先设置
DI=HIGH(告知LCD当前传输的是数据而非命令),RW=LOW(设置为写模式); - 通过循环+位运算,将ASCII字节的8个二进制位逐个输出到DB0-DB7引脚(代码中做了反转,对应LCD的D7-D0);
- 触发Enable引脚的脉冲,让LCD读取DB总线上的字节;
- LCD根据ASCII码从内部字符库中找到对应的5x7点阵,显示在当前光标位置,随后光标自动后移(因初始化时设置了
0x06:光标自动递增)。
内容的提问来源于stack exchange,提问作者Nizier
相关产品推荐
相关产品推荐

