树莓派GPIO驱动ST7735S主控TFT液晶屏显示图片和文字
程序员文章站
2022-05-30 19:35:54
...
本文使用1.8‘’128*160RGB_TFT ST7735S主控的液晶屏来操作
参考blog:http://blog.mangolovecarrot.net/2017/03/05/raspi-study1102
文中使用同类型液晶屏显示了纯色和制作点阵来显示文字,但是这实在是太麻烦了。
本文主要介绍如何使用PIL库来辅助显示,想要了解更多细节建议先看原文。
PIL库的安装
sudo apt-get install python-pil python3-pil
代码
在原作者的代码上增加了两个函数,用于图片的转换(侵删),关于RGB565请看原文
import RPi.GPIO as GPIO
import time
import math
from PIL import Image
cs = 23 # 片选
rs = 17 # 数据 / 命令 切换
sda = 13 # 数据
scl = 19 # 时钟
reset = 27 # 复位
# 传输byte
def setByteData(data):
# print ""
# print "S-----------setByte---------------:", hex(data)
for bit in range(0, 8):
# 传入的数字从高位到低位依次判断是否为1,若为1则设置高电平,否则设置低电平
# 判断的方法是先向左移位,把要判断的位移动到最高位然后跟0x80(1000 0000)相与,
# 如果结果仍然是0x80(1000 0000)就表示最高位是1,否则最高位就是0
if ((data << bit) & 0x80 == 0x80):
setBitData(True)
# print "1",
else:
setBitData(False)
# print "0",
# print ""
# print "E-----------setByte---------------"
def setBitData(data):
GPIO.output(scl, False)
GPIO.output(sda, data)
GPIO.output(scl, True)
def write_command(cmd):
GPIO.output(cs, False)
GPIO.output(rs, False)
setByteData(cmd)
GPIO.output(cs, True)
def write_data(data):
GPIO.output(cs, False)
GPIO.output(rs, True)
setByteData(data)
GPIO.output(cs, True)
def write_data_16bit(dataH, dataL):
write_data(dataH)
write_data(dataL)
def lcd_reset():
GPIO.output(reset, False)
time.sleep(0.1)
GPIO.output(reset, True)
time.sleep(0.1)
def lcd_init(width, heigh):
lcd_reset()
write_command(0x11) # Exit Sleep
time.sleep(0.02)
write_command(0x26) # Set Default Gamma
write_data(0x04)
write_command(0xB1) # Set Frame Rate
write_data(0x0e)
write_data(0x10)
write_command(0xC0) # Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
write_data(0x08)
write_data(0x00)
write_command(0xC1) # Set BT[2:0] for AVDD & VCL & VGH & VGL
write_data(0x05)
write_command(0xC5) # Set VMH[6:0] & VML[6:0] for VOMH & VCOML
write_data(0x38)
write_data(0x40)
write_command(0x3a) # Set Color Format
write_data(0x05)
write_command(0x36) # RGB
write_data(0xc8)
write_command(0x2A) # Set Column Address
write_data(0x00)
write_data(0x00)
write_data(0x00)
write_data(width - 1)
write_command(0x2B) # Set Page Address
write_data(0x00)
write_data(0x00)
write_data(0x00)
write_data(heigh - 1)
write_command(0xB4)
write_data(0x00)
write_command(0xf2) # Enable Gamma bit
write_data(0x01)
write_command(0xE0)
write_data(0x3f) # p1
write_data(0x22) # p2
write_data(0x20) # p3
write_data(0x30) # p4
write_data(0x29) # p5
write_data(0x0c) # p6
write_data(0x4e) # p7
write_data(0xb7) # p8
write_data(0x3c) # p9
write_data(0x19) # p10
write_data(0x22) # p11
write_data(0x1e) # p12
write_data(0x02) # p13
write_data(0x01) # p14
write_data(0x00) # p15
write_command(0xE1)
write_data(0x00) # p1
write_data(0x1b) # p2
write_data(0x1f) # p3
write_data(0x0f) # p4
write_data(0x16) # p5
write_data(0x13) # p6
write_data(0x31) # p7
write_data(0x84) # p8
write_data(0x43) # p9
write_data(0x06) # p10
write_data(0x1d) # p11
write_data(0x21) # p12
write_data(0x3d) # p13
write_data(0x3e) # p14
write_data(0x3f) # p15
write_command(0x29) # Display On
write_command(0x2C)
def show_single_color(DH, DL, width, heigh):
for i in range(0, heigh):
for j in range(0, width):
write_data_16bit(DH, DL)
def rgb2rgb565(image):
'''
将RGB(255,255,255)转换为(31,63,31)
'''
rgb565 = []
w, h = image.size
for y in range(h):
for x in range(w):
r, g, b = image.getpixel((x, y))[:3]
r = math.ceil(r / 0xFF * 0x1F)
g = math.ceil(g / 0xFF * 0x3f)
b = math.ceil(b / 0xFF * 0x1F)
rgb565.append((r, g, b))
return rgb565
def show4rgb565(rgb565):
'''
将rgb合并后取高低8位用于传输显示
原文中的RGB565 从高位到低位依次是红、绿、蓝
但是我所用的屏幕需要蓝、绿、红才能正常显示
'''
DH = 0
DL = 0
for r, g, b in rgb565:
h16 = ((b << 6) + g << 5) + r # 蓝、绿、红
# h16 = ((r << 6) + g << 5) + b # 红、绿、蓝
DH = (h16 & 0xFF00) >> 8
DL = h16 & 0x00FF
write_data_16bit(DH, DL)
# print(hex(h16),hex(DH), hex(DL))
if __name__ == '__main__':
try:
GPIO.setmode(GPIO.BCM)
GPIO.setup(cs, GPIO.OUT)
GPIO.setup(rs, GPIO.OUT)
GPIO.setup(sda, GPIO.OUT)
GPIO.setup(scl, GPIO.OUT)
GPIO.setup(reset, GPIO.OUT)
lcd_init(128, 160) # 屏幕宽、高
write_command(0x2C)
image = Image.open('图片路径')
image = image.resize((128, 160), Image.ANTIALIAS) #修改图片大小 屏幕宽、高
rgb565 = rgb2rgb565(image)
show4rgb565(rgb565)
while True:
pass
except KeyboardInterrupt:
pass
# 清理GPIO口
GPIO.cleanup()
连接方式
液晶屏 | 树莓派 |
---|---|
LCD | 3.3V(不可以是5V!!) |
SCK | GPIO19 |
SDA | GPIO13 |
AO | GPIO17 |
RESET | GPIO27 |
CS | GPIO23 |
GND | GND |
VCC | 3.3V(不可以是5V!!) |
运行
将代码复制并修改一个正确的图片路径,并保存到一个文件中,这里文件名为show.py
sudo python show.py
显示文字
使用PIL的Image、ImageDraw模块能够很快生成带有文字的图片
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
W = 128
H = 160
image = Image.new('RGB', (W, H))
font = ImageFont.load_default() # 加载默认字体
# ImageFont.truetype(font, font_size) 也可以加载本地ttf格式字体 font:文件名 font_size:字体大小
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, W, H), outline=0, fill=0)
line = 'hello PIL'
draw.text((0, 0), line, font=font, fill=255)
这段代码生成了一个带有hello PIL
文字的image对象,像显示图片的方式使用该image就可以了
默认字体
自定义字体
自动换行
通过计算文字大小和屏幕大小,进行自动换行,需要注意的是font_obj是一个字体对象,例如
ImageFont.truetype(font, font_size)
返回的对象
def auto_text(text, W, H, font_obj=None):
if not font_obj:
font_obj = ImageFont.load_default()
image = Image.new('RGB', (W, H))
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, W, H), outline=0, fill=0)
line = ''
top = 0
max_h = max([font_obj.getsize(c)[1] for c in text])
for i in range(len(text)):
t = line + text[i]
if font_obj.getsize(t)[0] > W:
draw.text((0, top), line, font=font_obj, fill=255)
line = text[i]
top += max_h
if top >= H:
break
else:
line = t
else:
draw.text((0, top), line, font=font_obj, fill=255)
return image
上一篇: 2020人工智能领域高成长企业TOP100发布,维择科技强势入选
下一篇: 3D_HW6