8、ESP32-S - 控制 SPI 液晶屏显示动态图片

视频链接:https://www.bilibili.com/video/BV1G34y1E7tE?p=12&spm_id_from=333.880.my_history.page.click&vd_source=b91967c499b23106586d7aa35af46413

文档连接:https://doc.itprojects.cn/0006.zhishi.esp32/02.doc/index.html#/12.240x240gif

1、制作要显示的动图(动图显示时间不要过长)。

2、将动图转换为多张静态图片,这里使用 Python 代码去做。

from PIL import Image
from PIL import ImageSequence

img = Image.open('C:\\Users\\Administrator\\Desktop\\123.gif')

i = 0
for frame in ImageSequence.Iterator(img):
    frame.save("frame%d.png" % i)
    i += 1

3、调整图片大小

from PIL import Image  # python3安装pillow库
import os.path
import glob


def convertSize(jpgfile, outdir, width=125, height=225):  # 图片的大小256*256
    img = Image.open(jpgfile)
    try:
        new_img = img.resize((width, height), Image.BILINEAR)

        if new_img.mode == 'P':
            new_img = new_img.convert("RGB")
        if new_img.mode == 'RGBA':
            new_img = new_img.convert("RGB")

        new_img.save(os.path.join(outdir, os.path.basename(jpgfile)))
    except Exception as e:
        print(e)


for jpgfile in glob.glob("*.png"):  # 修改该文件夹下的图片
    convertSize(jpgfile, "./")  # 另存为的文件夹路径

4、将图片转换为.dat文件

import struct
import numpy as np
from PIL import Image


def color565(r, g, b):
    return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3


def main():
    for i in range(1, 16):  # 16张图片循环播放
        img = Image.open("frame{}.png".format(i))
        print(i, img.format, img.size, img.mode)
        img_data = np.array(img)  # 225125列有3个 225x125x3

        with open("./frame{}.dat".format(i), "wb") as f:
            for line in img_data:
                for dot in line:
                    f.write(struct.pack("H", color565(*dot))[::-1])


if __name__ == '__main__':
    main()

5、就是要把转换好的 .dat 文件传给 ESP32,这是使用无线局域网的传输方式。首先在 ESP32 端运行接收代码(连接到 WiFi 后把自己的 ip 地址告诉给电脑),然后在电脑端运行发送代码。

接收端代码:

import time
import network
import machine
import socket


def do_connect():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect('ChinaNet-SAD8JJ', '13179734613')
        i = 1
        while not wlan.isconnected():
            print("正在链接...{}".format(i))
            i += 1
            time.sleep(1)
    print('network config:', wlan.ifconfig())


# 0. 连接wifi
do_connect()

# 1. 创建 TCP 套接字
server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 绑定本地信息
server_s.bind(("", 8080))

# 3. 设置为被动的
server_s.listen(128)

print("等待对方链接...")

# 4. 等待客户端链接
new_s, client_info = server_s.accept()

print("等待对方发送图片数据...")

# 3. 创建文件,接收数据
for i in range(1, 16):  # 15张图片循环播放
    with open("img{}.dat".format(i), "wb") as f:
        for j in range(225):
            # 3.1 接收数据
            data = new_s.recv(250)   # 125*2=250 一行有125个点, 每个点有两个字节
            # 3.2 写到文件
            f.write(data)
            # print("接收第%d行" % (i+1))

    print("img{}--接收完毕".format(i))

# 7. 关闭套接字
new_s.close()
server_s.close()

发送端代码:

import struct
import numpy as np
from PIL import Image


def color565(r, g, b):
    return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3


def main():
    for i in range(1, 16):  # 16张图片循环播放
        img = Image.open("frame{}.png".format(i))
        print(i, img.format, img.size, img.mode)
        img_data = np.array(img)  # 225125列有3个 225x125x3

        with open("./frame{}.dat".format(i), "wb") as f:
            for line in img_data:
                for dot in line:
                    f.write(struct.pack("H", color565(*dot))[::-1])


if __name__ == '__main__':
    main()

6、显示动图代码,是在上一节显示静态图片的驱动上改的。

import random
from machine import Pin, SPI
import st7789
import st7789py


# 解决第1次启动时,不亮的问题
st7789.ST7789(SPI(2, 80000000), dc=Pin(2), cs=Pin(5), rst=Pin(15))

# 创建显示屏对象
tft = st7789py.ST7789(SPI(2, 10000000), 135, 240, reset=Pin(15), dc=Pin(2), cs=Pin(5), rotation=0)

# 屏幕显示蓝色
tft.fill(st7789py.color565(0, 0, 0))#RGB

# 因为用到了15张图片,所以这里创建15个文件对象
f_list = [open("img{}.dat".format(i), "rb") for i in range(1, 16)]

def show_img():
    for f in f_list:
        f.seek(0) # 让文件指针指向0, 即从img1开始播放
        for row in range(0, 225, 25): # 从0行开始,一共有225,每次读取22行有问题(尽量取能整除的数)
            buffer = f.read(250*25)
            tft.show_img(0, row, 124, row+25, buffer) #起点坐标(0, row),终点坐标(124, row)


while True:
    show_img()

每次读取的行数阅读,播放的速度就越快,既不能每次读取的行数太多(48行没问题),否则会申请内存错误。也不能一行一行的读取,否则刷新太慢,有过于明显地刷新页面的过程,显示效果不佳。尽量每次读取是行数的整数倍 (尽量取能整除的数),避免还剩半行没读完的情况,比如这里读取 22 行就有问题。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuechanba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值