使用 python 来驱动 SPI 小屏幕,官方提供有驱动 2.4 寸小屏幕的 demo 代码(链接 https://doc.rvspace.org/VisionFive2/Application_Notes/VisionFive2_AN_P_Using_SPI_LCD/index.html ),我手上有一个 1.8 寸的,使用昉·星光2开发板来驱动它显示图片。
Python 环境准备
先安装一下 python3 和 python3-pip
apt install python3
apt-get install python3-pip
使用 pip 默认源下载较慢,设置一下 pip 的镜像源为中科大源
pip config set global.index-url https:
安装一些支持包
apt install libxml2-dev libxslt-dev
python3 -m pip install requests wget bs4
将下面的代码保存为 install.py 然后使用 python3 install.py 执行
import requests
import wget
import sys
import os
from bs4 import BeautifulSoup
def parse_data(link_addr, class_type, key_str):
req = requests.get(url=link_addr)
req.encoding = "utf-8"
html=req.text
soup = BeautifulSoup(req.text,features="html.parser")
package_version = soup.find(class_type,class_=key_str)
dd = package_version.text.strip()
data = dd.split()
return data
def parse_link(link_addr, class_type, key_str):
req = requests.get(url=link_addr)
req.encoding = "utf-8"
html=req.text
soup = BeautifulSoup(req.text,features="html.parser")
search_data = soup.find(class_type,class_=key_str)
search_data_2 = search_data.find("a")
dl_link_get = search_data_2.get("href")
return dl_link_get
def get_dl_addr_page():
link_address = "https://pypi.org/project/VisionFive.gpio/#history"
key_str = "release__version"
class_key = "p"
data_get = parse_data(link_address, class_key, key_str)
latest_version = data_get[0]
dl_addr_page = "https://pypi.org/project/VisionFive.gpio/{}/#files".format(latest_version)
return dl_addr_page
def get_dl_addr_of_latest_version(link_addr):
key_str = "card file__card"
class_key = "div"
addr_get = parse_link(link_addr, class_key, key_str)
return addr_get
def main():
dl_addr_p = get_dl_addr_page()
whl_dl_addr = get_dl_addr_of_latest_version(dl_addr_p)
whl_name = whl_dl_addr.split("/")[-1]
whl_name_suffix = os.path.splitext(whl_name)[-1]
whl_name_prefix = os.path.splitext(whl_name)[0]
whl_name_prefix_no_platform = whl_name_prefix[0: len(whl_name_prefix) - 3]
new_platform = "linux_riscv64"
rename_whl_name = "{}{}{}".format(whl_name_prefix_no_platform, new_platform, whl_name_suffix)
wget.download(whl_dl_addr, out=rename_whl_name)
os.system("pip install " + rename_whl_name)
os.system("rm -rf " + rename_whl_name)
if __name__ == '__main__':
sys.exit(main())
安装两个软件包,这两个软件包用途为后续在屏幕上显示图片用的
pip install pillow numpy
至此,驱动 SPI 小屏幕的基本环境就搭建完成了,下面在官方的代码基础上进行修改
驱动代码编写
这里用的是 1.8 寸的,驱动芯片为 ST7735S,分辨率 128*160 的 SPI 屏幕,将官方的 LCD2inch4_lib.py 修改为如下内容,主要是修改了分辨率、初始化序列和 lcd_clear 函数的实现
import os
import sys
import time
import logging
import VisionFive.spi as spi
import VisionFive.gpio as gpio
import numpy as np
from PIL import Image,ImageDraw,ImageFont
class LCD_dev():
width = 128
height = 160
def __init__(self, rst_pin, dc_pin, dev):
self.rstpin = rst_pin
self.dcpin = dc_pin
self.spidev = dev
spi.getdev(self.spidev)
spi.setmode(40000000, 0, 8)
gpio.setup(self.rstpin, gpio.OUT)
gpio.setup(self.dcpin, gpio.OUT)
def __del__(self):
spi.freedev()
def lcd_reset(self):
gpio.output(self.rstpin, gpio.HIGH)
time.sleep(0.01)
gpio.output(self.rstpin, gpio.LOW)
time.sleep(0.01)
gpio.output(self.rstpin, gpio.HIGH)
time.sleep(0.01)
def lcd_spisend(self, data):
spi.transfer(data)
def lcd_sendcmd(self, cmd):
gpio.output(self.dcpin, gpio.LOW)
spi.transfer(cmd)
def lcd_senddata(self,data):
gpio.output(self.dcpin, gpio.HIGH)
spi.transfer(data)
def lcd_sendnbytes(self, data):
gpio.output(self.dcpin, gpio.HIGH)
spi.write(data)
def lcd_init(self):
self.lcd_reset()
self.lcd_sendcmd(0x11)
self.lcd_sendcmd(0x09)
self.lcd_senddata(0x00)
self.lcd_senddata(0x00)
self.lcd_sendcmd(0xB1)
self.lcd_senddata(0x05)
self.lcd_senddata(0x3C)
self.lcd_senddata(0x3C)
self.lcd_sendcmd(0xB2)
self.lcd_senddata(0x05)
self.lcd_senddata(0x3C)
self.lcd_senddata(0x3C)
self.lcd_sendcmd(0xB3)
self.lcd_senddata(0x05)
self.lcd_senddata(0x3C)
self.lcd_senddata(0x3C)
self.lcd_senddata(0x05)
self.lcd_senddata(0x3C)
self.lcd_senddata(0x3C)
self.lcd_sendcmd(0xB4)
self.lcd_senddata(0x03)
self.lcd_sendcmd(0xC0)
self.lcd_senddata(0x28)
self.lcd_senddata(0x08)
self.lcd_senddata(0x04)
self.lcd_sendcmd(0xC1)
self.lcd_senddata(0XC0)
self.lcd_sendcmd(0xC2)
self.lcd_senddata(0x0D)
self.lcd_senddata(0x00)
self.lcd_sendcmd(0xC3)
self.lcd_senddata(0x8D)
self.lcd_senddata(0x2A)
self.lcd_sendcmd(0xC4)
self.lcd_senddata(0x8D)
self.lcd_senddata(0xEE)
self.lcd_sendcmd(0xC5)
self.lcd_senddata(0x1A)
self.lcd_sendcmd(0x36)
self.lcd_senddata(0x00)
self.lcd_sendcmd(0xE0)
self.lcd_senddata(0x04)
self.lcd_senddata(0x22)
self.lcd_senddata(0x07)
self.lcd_senddata(0x0A)
self.lcd_senddata(0x2E)
self.lcd_senddata(0x30)
self.lcd_senddata(0x25)
self.lcd_senddata(0x2A)
self.lcd_senddata(0x28)
self.lcd_senddata(0x26)
self.lcd_senddata(0x2E)
self.lcd_senddata(0x3A)
self.lcd_senddata(0x00)
self.lcd_senddata(0x01)
self.lcd_senddata(0x03)
self.lcd_senddata(0x13)
self.lcd_sendcmd(0xE1)
self.lcd_senddata(0x04)
self.lcd_senddata(0x16)
self.lcd_senddata(0x06)
self.lcd_senddata(0x0D)
self.lcd_senddata(0x2D)
self.lcd_senddata(0x26)
self.lcd_senddata(0x23)
self.lcd_senddata(0x27)
self.lcd_senddata(0x27)
self.lcd_senddata(0x25)
self.lcd_senddata(0x2D)
self.lcd_senddata(0x3B)
self.lcd_senddata(0x00)
self.lcd_senddata(0x01)
self.lcd_senddata(0x04)
self.lcd_senddata(0x13)
self.lcd_sendcmd(0x3A)
self.lcd_senddata(0x05)
self.lcd_sendcmd(0x29)
def lcd_setPos(self, Xstart, Ystart, Xend, Yend):
self.lcd_sendcmd(0x2a)
self.lcd_senddata((Xstart + 2) >>8)
self.lcd_senddata((Xstart + 2) & 0xff)
self.lcd_senddata((Xend + 1) >> 8)
self.lcd_senddata((Xend + 1) & 0xff)
self.lcd_sendcmd(0x2b)
self.lcd_senddata((Ystart + 1) >>8)
self.lcd_senddata((Ystart + 1) & 0xff)
self.lcd_senddata((Yend + 2) >> 8)
self.lcd_senddata((Yend + 2) & 0xff)
self.lcd_sendcmd(0x2C)
def lcd_clear(self, color):
pix = np.zeros((self.height, self.width, 2), dtype = np.uint8)
pix[...,[0]] = color >> 8
pix[...,[1]] = color
pix = pix.flatten().tolist()
self.lcd_setPos(0, 0, self.width, self.height)
gpio.output(self.dcpin, gpio.HIGH)
self.lcd_sendnbytes(pix)
def lcd_ShowImage(self, Image, Xstart, Ystart):
imwidth, imheight = Image.size
img = np.asarray(Image)
pix = np.zeros((imheight, imwidth, 2), dtype = np.uint8)
pix[...,[0]] = np.add(np.bitwise_and(img[...,[0]],0xF8),np.right_shift(img[...,[1]],5))
pix[...,[1]] = np.add(np.bitwise_and(np.left_shift(img[...,[1]],3),0xE0), np.right_shift(img[...,[2]],3))
pix = pix.flatten().tolist()
self.lcd_setPos(0, 0, self.width, self.height)
gpio.output(self.dcpin, gpio.HIGH)
self.lcd_sendnbytes(pix)
编写应用代码来调用前文的驱动相关的代码,实现
'''
Please make sure the 2.4inch LCD Moudle is connected to the correct pins.
The following table describes how to connect the 2.4inch LCD Module to the 40-pin header.
-------------------------------------------------
__2.4inch LCD Module___Pin Number_____Pin Name
VCC 17 3.3 V Power
GND 39 GND
DIN 19 SPI MOSI
CLK 23 SPI SCLK
CS 24 SPI CE0
DC 40 GPIO44
RST 11 GPIO42
BL 18 GPIO51
-------------------------------------------------
'''
import os
import sys
import time
import logging
from PIL import Image
sys.path.append("..")
import VisionFive.boardtype as board_t
import LCD_dev
'''
Demo modification ans new function description
------------------------------------------------------------
I. add the clear() function to fill LCD screen with white
II. give a hexadecimal value of white
III. cycle through multiple pictures
---------------------------------------------------------------
'''
RED = 0xf800
BLUE = 0x001f
GREEN = 0x07e0
BLACK = 0x0000
def main():
print('-----------lcd demo-------------')
vf_t = board_t.boardtype()
SPI_DEVICE = "/dev/spidev1.0"
disp = LCD_dev.LCD_dev(11, 40, SPI_DEVICE)
disp.lcd_init()
disp.lcd_clear(BLACK)
image = Image.open('./rvspace.jpg')
disp.lcd_ShowImage(image, 50, 0)
time.sleep(1)
while True:
time.sleep(1)
disp.lcd_clear(RED)
time.sleep(1)
disp.lcd_clear(BLUE)
time.sleep(1)
disp.lcd_clear(GREEN)
if __name__=="__main__":
main()