视频学习链接: https://www.bilibili.com/video/BV1G34y1E7tE?p=11&vd_source=b91967c499b23106586d7aa35af46413

讲义链接:https://doc.itprojects.cn/0006.zhishi.esp32/02.doc/index.html#/11.240x240image


链接: https://doc.itprojects.cn/0006.zhishi.esp32/01.download/st7789_itprojects.py

代码也粘贴在这:

import ustruct
import utime_NOP = const(0x00)
_SWRESET = const(0x01)
_RDDID = const(0x04)
_RDDST = const(0x09)_SLPIN = const(0x10)
_SLPOUT = const(0x11)
_PTLON = const(0x12)
_NORON = const(0x13)_INVOFF = const(0x20)
_INVON = const(0x21)
_DISPOFF = const(0x28)
_DISPON = const(0x29)
_CASET = const(0x2A)
_RASET = const(0x2B)
_RAMWR = const(0x2C)
_RAMRD = const(0x2E)_PTLAR = const(0x30)
_COLMOD = const(0x3A)
_MADCTL = const(0x36)_FRMCTR1 = const(0xB1)
_FRMCTR2 = const(0xB2)
_FRMCTR3 = const(0xB3)
_INVCTR = const(0xB4)
_DISSET5 = const(0xB6)_PWCTR1 = const(0xC0)
_PWCTR2 = const(0xC1)
_PWCTR3 = const(0xC2)
_PWCTR4 = const(0xC3)
_PWCTR5 = const(0xC4)
_VMCTR1 = const(0xC5)_RDID1 = const(0xDA)
_RDID2 = const(0xDB)
_RDID3 = const(0xDC)
_RDID4 = const(0xDD)_PWCTR6 = const(0xFC)_GMCTRP1 = const(0xE0)
_GMCTRN1 = const(0xE1)def color565(r, g, b):return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3class DummyPin:"""A fake gpio pin for when you want to skip pins."""OUT = 0IN = 0PULL_UP = 0PULL_DOWN = 0OPEN_DRAIN = 0ALT = 0ALT_OPEN_DRAIN = 0LOW_POWER = 0MED_POWER = 0HIGH_PWER = 0IRQ_FALLING = 0IRQ_RISING = 0IRQ_LOW_LEVEL = 0IRQ_HIGH_LEVEL = 0def __call__(self, *args, **kwargs):return Falseinit = __call__value = __call__out_value = __call__toggle = __call__high = __call__low = __call__on = __call__off = __call__mode = __call__pull = __call__drive = __call__irq = __call__class Display:_PAGE_SET = None_COLUMN_SET = None_RAM_WRITE = None_RAM_READ = None_INIT = ()_ENCODE_PIXEL = ">H"_ENCODE_POS = ">HH"_DECODE_PIXEL = ">BBB"def __init__(self, width, height):self.width = widthself.height = heightself.init()def init(self):"""Run the initialization commands."""for command, data in self._INIT:self._write(command, data)def _block(self, x0, y0, x1, y1, data=None):"""Read or write a block of data."""self._write(self._COLUMN_SET, self._encode_pos(x0, x1))self._write(self._PAGE_SET, self._encode_pos(y0+80, y1+80))if data is None:size = ustruct.calcsize(self._DECODE_PIXEL)return self._read(self._RAM_READ, (x1 - x0 + 1) * (y1 - y0 + 1) * size)self._write(self._RAM_WRITE, data)def _encode_pos(self, a, b):"""Encode a postion into bytes."""return ustruct.pack(self._ENCODE_POS, a, b)def _encode_pixel(self, color):"""Encode a pixel color into bytes."""return ustruct.pack(self._ENCODE_PIXEL, color)def _decode_pixel(self, data):"""Decode bytes into a pixel color."""return color565(*ustruct.unpack(self._DECODE_PIXEL, data))def pixel(self, x, y, color=None):"""Read or write a pixel."""if color is None:return self._decode_pixel(self._block(x, y, x, y))if not 0 <= x < self.width or not 0 <= y < self.height:returnself._block(x, y, x, y, self._encode_pixel(color))def fill_rectangle(self, x, y, width, height, color):"""Draw a filled rectangle."""x = min(self.width - 1, max(0, x))y = min(self.height - 1, max(0, y))w = min(self.width - x, max(1, width))h = min(self.height - y, max(1, height))self._block(x, y, x + w - 1, y + h - 1, b'')chunks, rest = divmod(w * h, 512)print("color:", color)pixel = self._encode_pixel(color)print("decode:", pixel)if chunks:data = pixel * 512for count in range(chunks):self._write(None, data)if rest:self._write(None, pixel * rest)def fill(self, color=0):"""Fill whole screen."""self.fill_rectangle(0, 0, self.width, self.height, color)def hline(self, x, y, width, color):"""Draw a horizontal line."""self.fill_rectangle(x, y, width, 1, color)def vline(self, x, y, height, color):"""Draw a vertical line."""self.fill_rectangle(x, y, 1, height, color)def blit_buffer(self, buffer, x, y, width, height):"""Copy pixels from a buffer."""if (not 0 <= x < self.width ornot 0 <= y < self.height ornot 0 < x + width <= self.width ornot 0 < y + height <= self.height):raise ValueError("out of bounds")self._block(x, y, x + width - 1, y + height - 1, buffer)class DisplaySPI(Display):def __init__(self, spi, dc, cs=None, rst=None, width=1, height=1):self.spi = spiself.cs = csself.dc = dcself.rst = rstif self.rst is None:self.rst = DummyPin()if self.cs is None:self.cs = DummyPin()self.cs.init(self.cs.OUT, value=1)self.dc.init(self.dc.OUT, value=0)self.rst.init(self.rst.OUT, value=1)self.reset()super().__init__(width, height)def reset(self):self.rst(0)utime.sleep_ms(50)self.rst(1)utime.sleep_ms(50)def _write(self, command=None, data=None):if command is not None:self.dc(0)self.cs(0)self.spi.write(bytearray([command]))self.cs(1)if data:self.dc(1)self.cs(0)self.spi.write(data)self.cs(1)def _read(self, command=None, count=0):self.dc(0)self.cs(0)if command is not None:self.spi.write(bytearray([command]))if count:data = self.spi.read(count)self.cs(1)return dataclass ST7789(DisplaySPI):"""A simple driver for the ST7789-based displays.>>> from machine import Pin, SPI>>> import st7789>>> display = st7789.ST7789(SPI(1), dc=Pin(12), cs=Pin(15), rst=Pin(16))>>> display = st7789.ST7789R(SPI(1, baudrate=40000000), dc=Pin(12), cs=Pin(15), rst=Pin(16))>>> display.fill(0x7521)>>> display.pixel(64, 64, 0)"""_COLUMN_SET = _CASET_PAGE_SET = _RASET_RAM_WRITE = _RAMWR_RAM_READ = _RAMRD_INIT = ((_SWRESET, None),(_SLPOUT, None),(_COLMOD, b"\x55"),  # 16bit color(_MADCTL, b"\x08"),)def __init__(self, spi, dc, cs, rst=None, width=240, height=240):super().__init__(spi, dc, cs, rst, width, height)def init(self):super().init()cols = ustruct.pack(">HH", 0, self.width)rows = ustruct.pack(">HH", 0, self.height)for command, data in ((_CASET, cols),(_RASET, rows),(_INVON, None),(_NORON, None),(_DISPON, None),(_MADCTL, b"\xc0"),  # Set rotation to 0 and use RGB):self._write(command, data)class ST7789_Image(ST7789):def _set_columns(self, start, end):if start <= end:self._write(_CASET, self._encode_pos(start, end))def _set_rows(self, start, end):if start <= end:self._write(_RASET, self._encode_pos(start, end))def _set_window(self, x0, y0, x1, y1):"""x0:  x起始位置y0:  y起始位置x1:  x结束位置y1:  y结束位置"""self._set_columns(x0, x1)self._set_rows(y0, y1)self._write(_RAMWR)def show_img(self, x0, y0, x1, y1, img_data):self._set_window(x0, y0 + 80, x1, y1 + 80)self._write(None, img_data)

(个人认为,这两个库结合的并不彻底,在显示一些更复杂的功能时,还是使用两个库(上节课的方法)来进行驱动。因为这个库只是在st7789.py的基础上增加了显示图片的功能(比如用来演示上节课旋转的功能时就不行),另外说下,我的液晶屏用这种不能行。)

下面,还是使用两种相结合的方式(经过实验,确实第一个驱动不能去掉,否则屏幕不刷新显示)来显示图片。

我是这样做的,首先保留 st7789.py 这个文件,其次,修改 st7789py.py 这个文件,修改的方法也很简单,也是参考视频中的程序内容做的。就是在后面重新定义了一个显示图片的函数。

 def show_img(self, x0, y0, x1, y1, img_data):self._set_window(x0, y0, x1, y1)self._write(None, img_data)

解决了驱动的问题后,就是解决图片的问题。


我所使用的液晶屏的大小为 135 (宽、列、垂直) x 240(长、行、水平)。

截图后,使用画图软件调整大小,这里调整为(125 x 225)

在电脑端运行 python 程序,将该图片转换为一个二进制数据的文件。该视频中也提供了代码。

import struct
import numpy as np
from PIL import Image  def color565(r, g, b):return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3def main():img = Image.open("test1.png")print(img.format, img.size, img.mode)img_data = np.array(img)  # 225行125列有3个 225x125x3with open("text_img.dat", "wb") as f:for line in img_data:for dot in line:f.write(struct.pack("H", color565(*dot))[::-1])if __name__ == '__main__':main()

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

接收端代码:

import time
import network
import machine
import socketdef do_connect():wlan = network.WLAN(network.STA_IF)wlan.active(True)if not wlan.isconnected():print('connecting to network...')wlan.connect('ChinaNet-SAD8JJ', '13xxxxxx13')i = 1while not wlan.isconnected():print("正在链接...{}".format(i))i += 1time.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. 创建文件,接收数据
with open("text_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行" % (j+1))print("接收完毕".)# 7. 关闭套接字
new_s.close()
server_s.close()

发送端代码:

from socket import *# 1. 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)# 2. 链接服务器
tcp_client_socket.connect(("192.168.2.88", 8080))# 2. 打开文件,发送数据
with open("text_img.dat", "rb") as f:for j in range(225):# 3.1 写到文件data = f.read(250)# 3.2 接收数据tcp_client_socket.send(data)  # 125*2=250 一行有125个点, 每个点有两个字节# print("发送第%d行" % (j + 1))# time.sleep(0.5)print("发送完毕.")# 7. 关闭套接字
tcp_client_socket.close()

最后,显示图片,代码如下:

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))#RGBdef show_img():with open("text_img.dat", "rb") as f:for row in range(225):buffer = f.read(250)tft.show_img(0, row, 124, row, buffer) #起点坐标(0, row),终点坐标(124, row)show_img()

7、ESP32-S - 控制 SPI 液晶屏显示图片相关推荐

  1. Wemos D1 R32 ESP32开发板OLED液晶屏显示

    目录 一.实验准备 二.实验代码 1.OLED液晶屏显示"Hello World" 2. OLED液晶满屏显示字符 3.OLED屏显示时钟 4.OLED屏显示矢量图片 5 OLED ...

  2. 树莓派GPIO驱动ST7735S主控TFT液晶屏显示图片和文字

    本文使用1.8''128*160RGB_TFT ST7735S主控的液晶屏来操作 参考blog:http://blog.mangolovecarrot.net/2017/03/05/raspi-stu ...

  3. 单片机采用RLE算法实现液晶屏显示图片

    由于需要用到液晶屏(320*240)显示图片,而且图片的数量比较多(好几百张),并且图片要求保存到16M的SPI FLASH里面,显然如果不处理 16M的FLASH明显是放不下去.后来同事说可以用压缩 ...

  4. 使用Python控制1602液晶屏实时显示时间(附PyCharm远程调试)

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文介绍一下UP板的GPIO资源使用,以及一个使用Python演示一个简单的demo. 本文使用Markdown写成,为获得更好的 ...

  5. 树莓派开发系列教程10——树莓派spi液晶屏支持(fbtft)

        树莓派官方支持av及HDMI输出,板子上预留了一个csi接口的液晶显示屏,但是一直没有相应的模组出现.在很多应用场合我们需要一些小型的液晶屏显示一些基本的信息,所以小屏驱动很是必要. 在git ...

  6. 57步进电机驱动板,可以通过编码器调速,支持SPI通讯屏显示,485通讯

    57步进电机驱动板,可以通过编码器调速,支持SPI通讯屏显示,485通讯. 板子上面有电位器可电流设定或者485改电流设定. 最大电流支持4.5A,如果需要更大电流需要改元器件参数. 有启停和方向按键 ...

  7. Linux高级应用(二)文件IO函数与液晶屏显示

    一.结构体占用的内存 struct test { char a; int b; short c; long d; char *p; }; 求该结构体占用的内存?sizeof(struct test) ...

  8. 超声波传感器与液晶屏显示实验

    实验二  超声波传感器与液晶屏显示实验 一.实验目的 了解液晶屏显示的基本原理以及电路连接. 二.实验内容  了解液晶屏的工作原理和工作情况. 三.实验仪器 导线若干,1602液晶显示屏,LY-F2 ...

  9. c语言52单片机液晶屏显示,[手把手教你学51单片机C语言教程]22 LCD12864液晶屏显示.pdf...

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspC/C++资料 [手把手教你学51单片机C语言教程]22 LCD ...

  10. nokia5110液晶屏显示汉字,图形,…

    nokia5110液晶屏显示汉字,图形,字符,字符串 从网上看到的文章,感觉很好,顾转载收藏啦 #include #include #define uchar unsigned char #defin ...

最新文章

  1. 【(Python解释器、Pycharm)安装教程】【使用PyCharm编写第一个Python程序】
  2. .NET Core全Linux开发体验分享
  3. [vue-element] 有用过哪些vue的ui?说说它们的优缺点?
  4. webRTC实战总结
  5. 4010-基于邻接矩阵的边的删除(C++,附思路)
  6. linux发布tomcat项目项目流程,linux下tomcat的配置及项目的部署流程
  7. linux 挂载windows共享目录 is not a valid block device
  8. 【渝粤教育】国家开放大学2019年春季 3818-22T燃气工程施工 参考试题
  9. win10/win7安装Rational Rose 2007(解决虚拟光驱加载不了bin文件问题)
  10. Google 安装印象笔记剪藏插件
  11. 人的精力是什么?如何强化精力
  12. 关于C语言二级机考软件环境的一些问题
  13. WebBrowser查看版本
  14. GShutDown:自动化关机鄙吝材
  15. 如何正确计算LINUX内存使用率
  16. 使用ipmi调节r410的风扇转速
  17. sublime text3--js智能提示插件以及其他常用插件
  18. GStreamer插件实列rockchipmpp
  19. VMware+Ubuntu16.04部署k8s多节点网络(二)——配置各节点网络
  20. 无线网卡在服务器上不能启用,解决无线网卡突然不能启用的问题(事件ID4294)...

热门文章

  1. 关于php多维数组,PHP多维数组
  2. matlab:正态分布的概率密度图形
  3. 同时使用动态库和静态库时怎么写makefile
  4. Spark独到见解--1、什么是Spark?及和MR的区别
  5. ln多少等于2用计算机,ln2(log计算器在线)
  6. 如何正确、高效地进行论文阅读和批判性思考
  7. win10开启无线网卡服务器,win10系统设置开启或者禁用无线网卡的恢复步骤
  8. 树莓派怎么切换输入法_树莓派 Raspberry Pi 设置显示中文方法安装输入法
  9. wps计算机里wps云盘图标,我的电脑中的wps网盘图标怎么设置删除
  10. 简单理解时间同步和时钟同步