RISC-V技术论坛
直播中

知之为知之zhl

4年用户 99经验值
擅长:可编程逻辑 电源/新能源
私信 关注
[经验]

【昉·星光 2 高性能RISC-V单板计算机体验】使用 SPI 驱动小屏幕

使用 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://pypi.mirrors.ustc.edu.cn/simple/

安装一些支持包

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 函数的实现

  • LCD_dev.py
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)

        #Reset the maximum clock frequency of communication.
        #The display speed of the picture is positively correlated with the clock frequency.
        spi.setmode(40000000, 0, 8)
        gpio.setup(self.rstpin, gpio.OUT)
        gpio.setup(self.dcpin, gpio.OUT)

    def __del__(self):
        spi.freedev()

    #Add a short delay for each change of electrical level.
    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)


    #Write multiple bytes.
    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) #Sleep out.
        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) #Display On.

    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)

        #Multi-byte-write.
        self.lcd_sendnbytes(pix)

    def lcd_ShowImage(self, Image, Xstart, Ystart):
        #Set buffer to the value of the Python Imaging Library image.
        #Write display buffer to the physical display.
        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)
        #Multi-byte-write.
        self.lcd_sendnbytes(pix)

编写应用代码来调用前文的驱动相关的代码,实现

  • LCD_demo.py
#!/usr/bin/python
'''
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-------------')

    #Determining cpu Type: 1 means visionfive1; 2 means visionfive 2
    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()

VID_20230801_233309

更多回帖

发帖
×
20
完善资料,
赚取积分