一起玩转树莓派(11)——使用LCD屏

简介: 通过本系列博客前几篇文章的介绍,我们已经体验过了许多传感器元件,它们大多非常简单,可以直接对其进行数据读取或写入,无需复杂的指令配置。本篇博客,我们将介绍一个相对复杂的元件:LCD屏。当今大多数常见的电子设备为了便于用户操作,都会配备一块LCD液晶显示屏,用户通过屏幕可以获取到设备的相关信息方便使用。下面,我们将尝试使用树莓派来在LCD屏上展示信息。

一起玩转树莓派(11)——使用LCD屏

通过本系列博客前几篇文章的介绍,我们已经体验过了许多传感器元件,它们大多非常简单,可以直接对其进行数据读取或写入,无需复杂的指令配置。本篇博客,我们将介绍一个相对复杂的元件:LCD屏。当今大多数常见的电子设备为了便于用户操作,都会配备一块LCD液晶显示屏,用户通过屏幕可以获取到设备的相关信息方便使用。下面,我们将尝试使用树莓派来在LCD屏上展示信息。

一、LCD 1602

LCD屏是Liquid Crystal Display的简称,即液晶显示屏。LCD 1602是一种点阵式的给付型液晶显示屏,其型号为1602本身也是有意义的,表示其可以显示2行信息,每行可以显示16个字符。LCD1602最多可以显示32个字符,价格上也并不昂贵,十几元钱即可买到。LCD1602有16个引脚,如下图所示:

LCD1602的16个引脚看上去很多,但实际上使用起来并不复杂,我们首先将上图这些引脚的功能来介绍一下。

  • 引脚1:接地引脚
  • 引脚2:接5V电压
  • 引脚3:VE引脚为屏幕对比度调整引脚,接地时对比度最大,接正极电源时对比度最小。
  • 引脚4:RS引脚为功能模式引脚(也被称为寄存器选择引脚),为其加高电平时为数据模式(存取屏幕展示的数据),为其加低电平时为指令模式(读取指令)。
  • 引脚5:RW引脚为读写模式引脚,为其加高电平时为读操作,为其加低电平时为写操作。
  • 引脚6:Enable引脚,此引脚用来触发动作,负跳变时进行数据处理或指令的执行。
  • 引脚7-引脚14:这8个引脚为数据引脚,用来进行数据传输。
  • 引脚15:背光电源引脚。
  • 引脚16:背光接地引脚。

上面所介绍的引脚中,引脚1,引脚2,引脚15和引脚16比较好理解,其都是作为供电功能,无需编程操作。引脚3是一个单独调增对比度功能的引脚,作用也相对独立,无需复杂的指令操作。引脚4和引脚5是比较核心的两个引脚,这两个引脚的高低电平状态组合共有4种,分别会将LCD1602设置为读指令模式,写指令模式,读数据模式和写数据模式。引脚6可以理解为一个触发引脚,通过操作这个引脚的电平跳变来让LCD1602执行具体的功能。引脚7-引脚14用来进行数据的存取或指令的存取。

现在请你务必将上面所介绍的内容完全理解,否则后面的内容可能会更加令你迷惑。对于LCD1206的读数据模式和写数据模式你应该没有什么疑惑,只要通过引脚4和引脚5设置正确的模式后,再通过GPIO来写和读引脚7到引脚14的电平数据,即可得到一个8位的数据。我们核心需要理解的是指令模式,LCD1602的指令集如下:

上图中的RS和R/W就是引脚4和引脚5,其控制模式,与指令本身无关,我们可以先不关心。从DB7到DB0是真正的指令部分。我们下面来逐一介绍。

1. 指令一:0000 0001

清屏指令,响应时间为1.53ms。

2.指令二:0000 001- (最后一位’-‘表示0和1都可以,不被关心)

光标归位指令,执行后光标的位置会回到起点,但是数据寄存器中的数据不会清空。

3.指令三:0000 01[I/D][SH]

光标移动模式设置指令,I/D和SH两个控制为光标或屏幕移动模式。

I/D设置为0:每次读取一个字符后光标左移。

I/D设置为1:每次读取一个字符后光标右移。

SH设置为0:屏幕不移动。

SH设置为1:屏幕移动,方向与I/D的设置一致。

4.指令四:0000 1[D][C][B]

显示模式设置指令,D,C,B这三个位分别设置主显示功能,光标显示功能,光标闪烁功能。

D:设置为0则关闭屏幕,设置为1开启屏幕。

C:设置为0关闭光标,设置为1显示光标。

B:设置为0光标不闪烁,设置为1光标闪烁。

5.指令五:0001  [S/C][R/L]--

设置光标和显示屏移动方向。

S/C设置为0时,R/L设置为0则光标左移,RL设置为1时光标右移。

S/C设置为1时,R/L设置为0则显示内容左移,R/L设置为1则显示内容右移。

6.指令六:001[DL] [N][F]--

功能模式设置指令。

DL:设置为1时采用8位总线读数据,设置为0时采用4位总线读数据。

N:设置为0时是单行显示模式,设置为1时是双行显示模式。

F:设置为0时为5*8的点阵字符,设置为1时为5*11的点阵字符。

7.指令七:01[A5][A4] [A3][A2][A1][A0]

设置下一个字符要显示的位置。A5位设置要定位到的行,A0到A4位定位要显示的位置,取值为0-16之间。

8.指令八:1[A6][A5][A4] [A3][A2][A1][A0]

数据寄存器地址设置。

了解了LD1602显示屏上面的指令用法,我们就可以编程来控制显示屏显示的内容了。

二、带I2C模块的LCD 1602

前面我们说过,LCD1602有16个引脚。原则上我们已经可以使用树莓派来控制显示屏的显示了,但是16个引脚全部连接到树莓派会使接线十分的复杂,而且程序代码的编写也非常繁琐,要对太多的GPIO引脚进行操作,十分不便。本次实验,我们采用的是带I2C模块的LCD元件,I2C模块本身将一些独立的功能进行了封装,通过I2C模块,我们可以以8位数据为标准来传输任何我们想要执行的指令或让LCD显示的字符,非常方便。

如上图所示,有了IC2模块的LCD1602元件,只需要4个引脚即可实现显示功能。下面我们来分析下如何使用此I2C模块。

首先关于I2C通信的相关内容,之前博客已经有详细的介绍,这里不再赘述。我们先来介绍下为何通过4个引脚通过I2C总线传输8位的数据集合实现所有功能。

LCD引脚1与引脚2:用I2C模块的电源引脚和接地引脚代替。

LCD引脚15和引脚16:LCD的这两个引脚功能为控制背光,此逻辑被封装进了I2C模块中,I2C模块每次写入的8位数据中的第4位用来控制背光。

LCD的引脚3:LCD的此引脚用来设置显示的对比度,在I2C模块中,通过一个可调节的电阻来实现此功能,在后面的实验中如果发现屏幕显示不清,可以尝试调节此电阻器。

LCD的引脚4,引脚5和引脚6:这几个功能引脚也被封装进了I2C模块中,I2C模块每次写入的8位数据中的第1位,的2位和第3位分别用来控制这些引脚。

LCD剩下的数据引脚的数据由I2C传输的8位数据中的高4位来对应,在LCD的8位数据模式下,I2C分两次传输一次完整的数据,前传输的4位为LCD所需数据的低4位,后传输的数据为LCD所需数据的高4位。在LCD的4位数据模式下,因为LCD需要获取到完整的8位数据,因此也需要通过两次数据传输,只是此时先传输的数据为LCD所需数据的高4位,后传输的数据为LCD所需数据的低4位,这点需要特别注意。

下面总结了I2C在传输数据时每一位的意义:

第8位 第7位 第6位 第5位 第4位 第3位 第2位 第1位
数据/指令 数据/指令 数据/指令 数据/指令 背光控制位 Enable控制位 RW控制位 RS控制位

 三、编码实验

    使用I2C模块封装的LCD1602只有4个引脚,接线非常简单,如下:

LCD 树莓派
GND GND
VCC +5V
SDA 树莓派SDA功能引脚
SCL 树莓派SCL功能引脚

将LCD1602与树莓派连接完成后,在树莓派的终端执行如下指令查看I2C设备:

sudo i2cdetect -y 1

输出入下图所示:

可以看到,目前我们只连接了一个I2C设备,设备号为27。

    由于背光的控制位相对独立,我们封装单独的函数来处理,如下:

# 是否开启背光 由PCF8574T的低4位中的第4位决定
BLEN = 1 
# 补充背光控制位
def addBlenControl(data):
    global BLEN
    tmpData = data
    if BLEN:
        # 将第4位背光控制位强制设置1
        tmpData = data | 0b00001000
    else:
        # 将第4位背光控制位强制设置为0
        tmpData = data & 0b11110111
    return tmpData    

同理,可以将Enable位的控制,RS位的控制都封装成函数:

# 补充Enable控制位
def addEnableControl(data, high):
    tempData = data
    # 第3位控制Enable
    if high:
        tempData |= 0b00000100
    else:
        tempData &= 0b11111011
    return tempData

# 补充RS控制位
def addRSControl(data, high):
    tempData = data
    # 第1位控制RS
    if high:
        tempData |= 0b00000001
    else:
        tempData &= 0b11111110
    return tempData

在向I2C发送数据前,根据配置的背光设置来决定背光控制位的值:

# 通过I2C总线写入数据
def writeI2C(addr, data):
    # 添加背光控制
    temp = addBlenControl(data)
    # 写数据到I2C总线
    BUS.write_byte(addr ,temp)

准备好了这些工具函数,我们只需要根据LCD1602的指令手册来设置具体的功能,发送要展示的数据即可,完整的代码如下:

#coding:utf-8
import time
import smbus
BUS = smbus.SMBus(1)
# LCD屏幕的硬件地址
LCD_ADDR = 0x27
# 是否开启背光 由PCF8574T的低4位中的第4位决定
BLEN = 1 

# 补充背光控制位
def addBlenControl(data):
    global BLEN
    tmpData = data
    if BLEN:
        # 将第4位背光控制位强制设置1
        tmpData = data | 0b00001000
    else:
        # 将第4位背光控制位强制设置为0
        tmpData = data & 0b11110111
    return tmpData    

# 补充Enable控制位
def addEnableControl(data, high):
    tempData = data
    # 第3位控制Enable
    if high:
        tempData |= 0b00000100
    else:
        tempData &= 0b11111011
    return tempData

# 补充RS控制位
def addRSControl(data, high):
    tempData = data
    # 第1位控制RS
    if high:
        tempData |= 0b00000001
    else:
        tempData &= 0b11111110
    return tempData

# 通过I2C总线写入数据
def writeI2C(addr, data):
    # 添加背光控制
    temp = addBlenControl(data)
    # 写数据到I2C总线
    BUS.write_byte(addr ,temp)

# 发送指令到LCD1602
def sendCommand(comm):
    # comm高4位数据传输
    # 低4位先清空
    buf = comm & 0b11110000
    # 先将Enable置为高电平
    buf = addEnableControl(buf, 1)
    # 设置为指令模式
    buf = addRSControl(buf, 0)
    # 写入指令
    writeI2C(LCD_ADDR ,buf)
    time.sleep(0.002)
    # 将Enable置为低电平 使产生低电平跳变来执行指令
    buf = addEnableControl(buf, 0)          
    writeI2C(LCD_ADDR ,buf)
     
    # comm低4位数据传输
    # 高4位先清空 并将低4位的数据移动到高4位
    buf = (comm & 0b00001111) << 4
    # 当次指令的低4位用来 做enable re rew的控制
    # 先将Enable置为高电平
    buf = addEnableControl(buf, 1)
    writeI2C(LCD_ADDR ,buf)
    time.sleep(0.002)
    # 将Enable置为低电平 使产生低电平跳变来执行指令
    buf = addEnableControl(buf, 0)     
    writeI2C(LCD_ADDR ,buf)

# 发送数据到LCD 
def sendData(data):
    # data高4位数据传输
    # 低4位先清空
    buf = data & 0b11110000
    # 先将Enable置为高电平
    buf = addEnableControl(buf, 1)
    # 设置为数据模式
    buf = addRSControl(buf, 1)   
    writeI2C(LCD_ADDR ,buf)
    time.sleep(0.002)
    # 将Enable置为低电平 使产生低电平跳变来执行指令
    buf = addEnableControl(buf, 0)  
    writeI2C(LCD_ADDR ,buf)
     
    # data低4位数据传输
    buf = (data & 0b00001111) << 4
    # 先将Enable置为高电平
    buf = addEnableControl(buf, 1)
    # 设置为数据模式
    buf = addRSControl(buf, 1) 
    writeI2C(LCD_ADDR ,buf)
    time.sleep(0.002)
    # 将Enable置为低电平 使产生低电平跳变来执行指令
    buf = addEnableControl(buf, 0)  
    writeI2C(LCD_ADDR ,buf)

# 初始化方法
def initLCD():
    # 启动时,LCD1602为8位模式 I2C传输数据时先传输的为低位数据
    # 因此实际上的指令为 0b00100011
    # 为指令6 将LCD1602设置为4位总线模式
    sendCommand(0b00110010) 
    time.sleep(0.005)

    # 之后的指令都是4位总线模式
    sendCommand(0b00110010) 
    time.sleep(0.005)
    # 指令4 设置屏幕开启,无光标,无闪烁
    sendCommand(0b00001100)
    time.sleep(0.005)
    # 指令1 清屏
    sendCommand(0b00000001) 

# 设置屏幕要展示的文案 x,y确定位置
def printLCD(x, y, str):
    # 2行 16 列
    if x < 0:
        x = 0
    if x > 15:
        x = 15
    if y <0:
        y = 0
    if y > 1:
        y = 1
    # 指令7 设置数据要展示的位置
    addr = 0b10000000 + 0b00000100 * y + x
    sendCommand(addr)
    # 开始发送字符数据到LCD1602的数据寄存器
    for chr in str:
        # ord函数可以获取字符的ascil
        sendData(ord(chr))
 
# 主程序
initLCD()
printLCD(0, 0, 'Hello, world!')
time.sleep(2)
sendCommand(0b00000001)
time.sleep(0.002)
printLCD(0, 0, 'Love China!')
time.sleep(2)
sendCommand(0b00000001)
time.sleep(0.002)
printLCD(0, 0, 'Great Raspberry!')

如上代码所示,所有的指令都采用的二进制的方式,便于对比指令手册进行理解。更多时候我们会采用十六进制数字来编写指令,这样会使代码看的干净很多。上面的示例代码是一个简单的应用程序,运行后可以直接在LCD屏幕上展示3句话:

Hello World!
Love China!
Great Raspberry!

其实此程序也是一个完整的LCD1602驱动,初始化完成后,我们可以通过其提供额sendData方法来实现各种各样的显示需求。效果如下图所示:

专注技术,懂的热爱,愿意分享,做个朋友
相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
5G 网络架构
已解决:树莓派外接硬盘 usb 或者sata 导致wifi无法链接 无线网卡无法使用问题
已解决:树莓派外接硬盘 usb 或者sata 导致wifi无法链接 无线网卡无法使用问题
641 4
|
6月前
|
人工智能 自然语言处理 监控
2026年零基础部署OpenClaw(Clawdbot)教程及OpenClaw必装Skill+实战案例分享
2026年初,一款名为OpenClaw(原Clawdbot、Moltbot)的AI工具以现象级速度席卷全球科技圈,凭借72小时狂揽60000+GitHub Stars的成绩,如今星标数已突破180000+,不仅让Mac Mini全球卖断货,更带动Cloudflare股价上涨20%。这款被网友亲切称为Molty“小龙虾”的工具,并非普通的聊天机器人,而是真正“长了手的AI助理”——它能通过Telegram、飞书等10+渠道主动执行任务,从网站重建、买车砍价到深夜Bug修复,真正实现“聊天框里办大事”。
2103 4
|
程序员 编译器 C#
聊聊 C# 中的顶级语句
聊聊 C# 中的顶级语句
367 0
|
开发工具 git
|
Linux 网络安全 数据安全/隐私保护
【最新教程】树莓派安装系统及VNC远程桌面连接
【最新教程】树莓派安装系统及VNC远程桌面连接
FreeRTOS 互斥量 优先级反转(翻转)和优先级继承 详解
FreeRTOS 互斥量 优先级反转(翻转)和优先级继承 详解
|
Python
使用pip安装第三方库的方法。
使用pip安装第三方库的方法。
963 1
|
IDE 开发工具 开发者
PyCharm安装教程(图文结合,超详细,小白安装必看)
PyCharm安装教程(图文结合,超详细,小白安装必看)
|
弹性计算 缓存 测试技术
阿里云2核4G配置云服务器ECS实例规格、收费标准及最新活动价格参考
阿里云2核4G配置云服务器ECS实例规格、收费标准及最新活动价格参考,阿里云服务器2核4G配置不是指e实例和u1实例,还可以选择计算型c7、计算型c6、计算型c8i、AMD计算型c8a、性能增强计算型c8ae、高主频计算型hfc8i、AMD计算型c7a、高主频计算型hfc7等规格,
|
网络协议 Java Windows
【Minecraft开服】Windows搭建我的世界MC服务器「公网远程联机」
简单几步在windwos搭建我的世界服务器,并通过cpolar工具将本地服务暴露到公网连接
6973 0
【Minecraft开服】Windows搭建我的世界MC服务器「公网远程联机」

热门文章

最新文章