树莓派通过I2C总线连接LCD1602并部署一个小项目

开箱前

Step 1. 连接电路

啊,物理……

I2C接口需要连接树莓派的SDA与SCL功能引脚。根据树莓派实验室给出的树莓派40Pin GPIO引脚对照表可以看出,有这个功能的引脚共有两对:SDA.1与SDL.1(即3号引脚和5号引脚),SDA.0与SCL.0(27号引脚与28号引脚)

引脚对照

使用面包板将二者相连,因为我没有母对母的杜邦线了

LCD1602 GND 接 树莓派 GND(这里用6号引脚)

LCD1602 VCC 接 树莓派 5V(这里用4号引脚)

LCD1602 SCL 接 树莓派 SCL.0(这里用28号引脚)

LCD1602 SDA 接 树莓派 SDA.0(这里用27号引脚)

接线

这里我埋下了一个巨大的坑

Step 2. 部署

先把环境搭好

Python3 smbus库

1
$ sudo apt install python-smbus

I2C工具,用于检测连接

1
$ sudo apt install i2c-tools

两个都装好后,进raspi-config

1
$ sudo raspi-config

1

进入Interfacing Options

2

I2C

选‘是’就行

重启一下,再运行sudo i2cdetect -y 1。如果正常,会在第七纵列显示有27。

但我这个偏偏不正常

空的……

Fix

解决的方法很简单,我把SDA和SDL接在了第3和第5引脚。至于为什么27、28引脚不行,那就属于玄学领域的范畴了。

为了这个,我还把外壳自带的风扇拆下来了。因为风扇的线短且两个母口连在一起的,不可分开。

再见,圣光不再照耀树莓派

OwO
再次启动,它就正常了。

就这

现在,可以开始写程序了。

Step 3.驱动程序

这里就直接使用树莓派实验室所给的代码测试。(我自己改了一点)

版权归代码原作者所有,但原作者我不知道是谁,是开源的就对了,我没有说这个代码的版权归网站平台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import time
import smbus
BUS = smbus.SMBus(1)
LCD_ADDR = 0x27
BLEN = 1 #turn on/off background light

def turn_light(key):
global BLEN
BLEN = key
if key ==1 :
BUS.write_byte(LCD_ADDR ,0x08)
else:
BUS.write_byte(LCD_ADDR ,0x00)

def write_word(addr, data):
global BLEN
temp = data
if BLEN == 1:
temp |= 0x08
else:
temp &= 0xF7
BUS.write_byte(addr ,temp)

def send_command(comm):
# Send bit7-4 firstly
buf = comm & 0xF0
buf |= 0x04 # RS = 0, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)

# Send bit3-0 secondly
buf = (comm & 0x0F) << 4
buf |= 0x04 # RS = 0, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)

def send_data(data):
# Send bit7-4 firstly
buf = data & 0xF0
buf |= 0x05 # RS = 1, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)

# Send bit3-0 secondly
buf = (data & 0x0F) << 4
buf |= 0x05 # RS = 1, RW = 0, EN = 1
write_word(LCD_ADDR ,buf)
time.sleep(0.002)
buf &= 0xFB # Make EN = 0
write_word(LCD_ADDR ,buf)

def init_lcd():
try:
send_command(0x33) # Must initialize to 8-line mode at first
time.sleep(0.005)
send_command(0x32) # Then initialize to 4-line mode
time.sleep(0.005)
send_command(0x28) # 2 Lines & 5*7 dots
time.sleep(0.005)
send_command(0x0C) # Enable display without cursor
time.sleep(0.005)
send_command(0x01) # Clear Screen
BUS.write_byte(LCD_ADDR ,0x08)
except:
return False
else:
return True

def clear_lcd():
send_command(0x01) # Clear Screen

def print_lcd(x, y, str):
if x < 0:
x = 0
if x > 15:
x = 15
if y <0:
y = 0
if y > 1:
y = 1

# Move cursor
addr = 0x80 + 0x40 * y + x
send_command(addr)

for chr in str:
send_data(ord(chr))

if __name__ == '__main__':
init_lcd()
#print_lcd(0, 0, 'Hello, world!')
print_lcd(0, 0, 'It Works!HelloWorld!')

真·斜视

可以显示,但对比度过低,我就用螺丝刀拧液晶模块后面的变阻器,调整到最佳的对比度。

没显示全……

- -

EX Stage

在以上代码的基础上,我改了亿点。毕竟,买个液晶模块回来,不是拿来看HelloWorld的(手动狗头)。

都看到这里了,投个币再走吧 (QwQ)

后续

做到这里,就到了1024程序员节了。各位不管是前端后端全栈运维,还是像本人一样的个人开发者,亦或是图吧、卡吧的大佬,都请早点睡,不要肝游戏肝代码肝教案了~

肝帝.jpg

偶然想起,一年前的1024,鹅厂把QQ4Linux的坟挖了,推出了全新的QQ4Linux2009版。现在好像还在更新的样子,但早已比不过deepin-wine那个简易的容器里畅快玩耍的WineQQ。(笑)

今天搞出的这个LCD1602显示状态的项目,相信各位都可以像我一样在网上随便抄抄改改就可以简单地跑起来,所以代码我就不提供了。唯一不爽的是天气API没几个免费的,如果有知道的,希望在评论区指出,谢谢了。

o( ̄︶ ̄)o


参考链接:

树莓派通过 I2C 驱动 LCD1602 液晶屏
- 树莓派实验室

树莓派通过I2C驱动LCD1602显示屏 - CSDN博客

单片机显示原理(LCD1602) - 阿忠ZHONG - 博客园