当前位置: 首页 > news >正文

4英寸电子墨水屏驱动全解析:从树莓派到STM32的低功耗显示方案

1. 从一块“会变”的屏幕说起:4英寸电子墨水屏的独特魅力

如果你玩过树莓派、Arduino或者STM32,肯定对点亮一块LCD或者OLED屏幕不陌生。那种色彩鲜艳、响应迅速的显示效果,确实很酷。但今天我想聊点不一样的——一块4英寸的电子墨水屏,也就是大家常说的e-Paper。你可能在Kindle上见过它,那种像印刷纸张一样的质感,不发光,在阳光下反而更清晰,而且最关键的是,它只在刷新内容时才耗电,显示静态画面时,功耗几乎为零。

这就是4inch e-Paper HAT+ (E) 这块板子的核心价值。它不是一个独立的设备,而是一个“帽子”(HAT),专为树莓派、Jetson Nano这类单板计算机,以及Arduino、STM32这类微控制器设计的扩展模块。它的目标场景非常明确:当你需要构建一个低功耗、长时间显示、且对视觉舒适度有要求的设备时,它就是绝佳的选择。想象一下,一个室外的天气站、一个智能家居的中央状态显示屏、一个仓库的电子标签、或者一个无需频繁充电的便携信息终端。在这些场景里,LCD屏幕的持续背光耗电和刺眼问题,都会成为短板,而电子墨水屏的优势就凸显出来了。

我最初接触它,是想做一个放在书桌上的日程提醒板,希望它像便签纸一样,插上电更新完内容就可以一直显示,不用整天亮着。市面上很多e-Paper模块驱动起来比较麻烦,而这块4inch HAT+ (E) 最大的好处就是“开箱即用”的友好度。它把复杂的驱动电路、电压转换、乃至温度传感器都集成在了一块板子上,你只需要用排线连接屏幕,再把HAT插到树莓派的GPIO针脚上,基本上就完成了硬件连接。软件层面,厂商也提供了完善的C、Python和Arduino库,大大降低了入门门槛。

所以,无论你是想给树莓派项目加一个酷炫又实用的显示终端,还是想用STM32做一个超低功耗的显示设备,这块屏幕都是一个值得深入把玩的组件。接下来,我就结合自己的使用经验,带你从硬件拆解到软件驱动,完整地走一遍它的使用流程,并分享几个实际项目中容易踩到的坑和解决技巧。

2. 硬件深度解析:不只是屏幕,更是一个完整的显示子系统

拿到4inch e-Paper HAT+ (E),第一感觉是比想象中要“复杂”一点。它不仅仅是一块屏幕加一个FPC(柔性电路板)接口,而是一个高度集成的子系统。理解它的硬件构成,对于后续的驱动和问题排查至关重要。

2.1 核心部件与接口布局

板子的核心是一块4.01英寸(对角线)的电子墨水屏,分辨率为640x400像素。这个分辨率在4英寸的尺寸上,显示文字和简单图形已经非常清晰了。屏幕本身是黑白的,但通过特殊的涂层,可以实现黑、白、红(或黄)的三色显示,我们这款(E)型号通常支持黑、白、红三色。

驱动屏幕的,是板载的一颗专用驱动芯片(通常是SSD1677或类似型号)。这颗芯片负责接收来自主控制器(如树莓派)的图像数据,并生成复杂的时序波形来精确控制每一个“微胶囊”里的黑白粒子移动,从而形成图像。这个过程远比LCD复杂,所以驱动芯片是必不可少的。

除了驱动芯片,板上还有一个非常关键的电路:升压电路。电子墨水屏需要较高的电压(通常15V-20V)来进行全局刷新。而树莓派或STM32的GPIO只能提供3.3V或5V。因此,板载的升压电路(Boost Converter)负责将输入电压提升到屏幕所需的高压。这意味着你只需要给HAT提供5V电源,它自己会处理好屏幕的供电。

接口方面,主要分为两类:

  1. 屏幕接口:一个标准的FPC连接器,通过一根排线与屏幕本体相连。这个连接非常脆弱,插拔时一定要对准缺口,均匀用力,切忌生拉硬拽。我见过不止一个朋友因为排线没插好或者插歪了,导致屏幕出现局部乱码或完全无显示。
  2. 主控接口:两排40Pin的GPIO排针,与树莓派40Pin GPIO布局完全兼容,可以直接插在树莓派Zero/2/3/4/5上。对于非树莓派平台(如STM32),则需要通过杜邦线连接关键的几个引脚。

注意:板子上通常还会有一个小的拨码开关,用于选择通信接口是SPI还是I2C。对于4英寸这种分辨率的屏幕,为了传输速度,必须选择SPI模式。I2C速度太慢,刷新一张图要几十秒,基本不可用。所以拿到板子第一件事,确认拨码开关拨到了SPI一侧(通常标有“SPI”或“BS0=0, BS1=0”的标识)。

2.2 电源设计与功耗实测

功耗是电子墨水屏项目的核心考量。板子的供电输入是5V,可以从树莓派的5V引脚取电,也可以从外部Micro USB口供电。我强烈建议,在驱动屏幕进行全局刷新(尤其是清屏)时,使用外部独立电源供电。因为全局刷新瞬间电流可能达到100mA以上(峰值甚至更高),如果仅靠树莓派供电,可能会引起树莓派电压波动,导致其重启或运行不稳定。

为了量化它的功耗,我用电流表做了一个简单测试:

  • 静态显示期:当屏幕完成刷新,显示静态图像时,电流几乎为0mA(uA级别),功耗可以忽略不计。这是e-Paper最大的优势。
  • 局部刷新期:如果只是更新部分区域(比如仅刷新一个数字),电流在10-30mA之间,持续时间很短。
  • 全局刷新期:执行一次完整的全屏刷新(如display.clear()),电流峰值可达120-150mA,持续约1-2秒。

所以,在电池供电的场景下,你的功耗优化策略应该是:最大化静态显示时间,最小化全局刷新次数。例如,更新数据时,尽量使用局部刷新API;定期(比如每刷新24小时)执行一次全局刷新以防止残影。

2.3 温度传感器与它的妙用

一个容易被忽略但非常实用的部件是板载的温度传感器(通常是NTC热敏电阻)。电子墨水屏的刷新波形(LUT,查找表)对温度非常敏感。低温下,粒子移动慢,需要更长的驱动时间;高温下则相反。使用错误的波形可能导致刷新不彻底、残影严重甚至损坏屏幕。

因此,优秀的驱动库(如Waveshare提供的库)会利用这个温度传感器,根据当前环境温度自动选择或微调刷新波形。在初始化屏幕时,库函数通常会先读取温度传感器的值,然后加载对应的LUT。这就是为什么你必须确保温度传感器相关的引脚连接正确,并且驱动代码中使能了温度读取功能。如果温度读取失败,库可能会使用一个默认的室温波形,在极端温度下显示效果会大打折扣。

3. 软件驱动全攻略:从树莓派到STM32

硬件准备就绪后,下一步就是让屏幕动起来。根据你的主控平台,驱动方式有所不同,但核心逻辑相通:通过SPI发送图像数据和命令。

3.1 树莓派平台:最便捷的体验

在树莓派上使用,无疑是最简单的。因为厂商的库已经为你处理好了一切底层细节。

第一步:启用SPI接口树莓派的SPI默认是关闭的。通过sudo raspi-config命令,进入Interface Options->SPI,选择Yes启用它。重启后,你可以用ls /dev/spi*命令检查,应该能看到/dev/spidev0.0/dev/spidev0.1设备。

第二步:安装驱动库Waveshare提供了Python库,可以通过pip安装,或者直接从GitHub克隆。

sudo apt update sudo apt install python3-pip python3-pil -y git clone https://github.com/waveshare/e-Paper.git cd e-Paper/RaspberryPi_JetsonNano/python sudo pip3 install .

安装后,在examples目录下就能找到针对4inch e-Paper HAT (E)的示例程序。

第三步:理解示例代码与关键API我们以epd_4in01f_test.py为例,拆解关键步骤:

from waveshare_epd import epd4in01f import time from PIL import Image, ImageDraw, ImageFont # 初始化屏幕对象 epd = epd4in01f.EPD() epd.init() # 这里会进行硬件复位、读取温度、加载LUT等操作 epd.Clear() # 全屏清空为白色 # 创建一幅图像,模式为'1'(1位黑白)或'L'(8位灰度,库内部会处理) # 注意:对于三色屏,我们通常使用'1'模式,用0/1表示黑白,另一个颜色(如红色)需要特殊处理 height = epd.height # 400 width = epd.width # 640 image = Image.new('1', (width, height), 255) # 255为白色 draw = ImageDraw.Draw(image) # 绘制内容 font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 24) draw.text((10, 10), 'Hello, e-Paper!', font=font, fill=0) # fill=0 为黑色 # 绘制一个红色矩形(需要调用特定的方法,因为普通绘制只认0/1) # 通常库会提供 `draw_red_rectangle` 或类似函数,或者通过创建另一张“红色层”图像来实现 # 显示图像 # 对于黑白内容: epd.display(epd.getbuffer(image)) # 对于包含红黑白的内容,可能需要调用 epd.display(black_buffer, red_buffer) time.sleep(2) # 进入睡眠模式以省电 epd.sleep()

关键点解析

  1. init():这个函数至关重要。它完成了硬件初始化、温度读取和波形加载。如果屏幕初始化后显示异常,首先检查init()是否成功执行,温度值是否被正确读取(可以打印出来看看)。
  2. Clear():全屏刷新为白色。这是一个“全局刷新”,耗电且耗时,但能彻底清除残影。不宜频繁调用。
  3. 图像模式:使用Image.new('1', ...)创建1位深度的图像,这是最高效的方式。库函数epd.getbuffer()会将PIL图像对象转换成屏幕驱动所需的字节流格式。
  4. sleep():显示完成后,务必调用sleep()。这将让驱动芯片进入低功耗模式,此时除了SPI的CS引脚,其他IO口会进入高阻态,进一步降低功耗。在下次刷新前,需要重新调用init()

3.2 Arduino平台:深入底层控制

在Arduino上驱动,能让你更贴近硬件底层。通常需要连接如下引脚:

  • SPI:SCK, MOSI, MISO, CS(片选)
  • 控制引脚:RST(复位), DC(数据/命令选择), BUSY(忙状态指示)

接线示例(以Arduino Uno为例)

e-Paper HAT -> Arduino Uno VCC -> 5V GND -> GND DIN (MOSI) -> Pin 11 CLK (SCK) -> Pin 13 CS -> Pin 10 DC -> Pin 9 RST -> Pin 8 BUSY -> Pin 7

驱动逻辑核心: Arduino库的核心函数通常是EPD_4IN01F_Init()EPD_4IN01F_Clear()EPD_4IN01F_Display()。与Python库类似,初始化过程中会读取温度(通过ADC读取NTC的电压值并换算)。你需要将屏幕的BUSY引脚连接到Arduino的一个IO口,并在代码中不断轮询其状态,直到屏幕准备好接收下一条命令。这是与树莓派库(可能使用延时等待)的一个细微差别。

// 伪代码逻辑 void EPD_4IN01F_Init(void) { // 1. 硬件复位 (拉低RST,延时,拉高) // 2. 发送一系列初始化命令序列 // 3. 读取温度传感器ADC值 float temperature = Read_Temperature(); // 4. 根据温度选择并发送对应的LUT数据 Set_LUT_By_Temperature(temperature); } void EPD_4IN01F_Display(const uint8_t *image_buffer) { // 1. 发送“开始写RAM”命令 // 2. 通过SPI逐行发送image_buffer数据 // 3. 发送“刷新显示”命令 // 4. 等待BUSY引脚变低(屏幕刷新完成) while(digitalRead(BUSY_PIN) == HIGH) { delay(10); } }

在Arduino上,你需要自己管理图像缓冲区(一个大小为(640/8) * 400 = 32000字节的数组),并通过位操作来设置每个像素的黑白。这对于动态生成简单图形是可行的,但对于复杂图片,最好还是在PC上生成好字节流数组,然后硬编码到Arduino程序中。

3.3 STM32平台:平衡性能与功耗

在STM32上驱动,是嵌入式开发的典型场景。你可以使用HAL库或标准外设库来操作SPI和GPIO。

工程配置要点

  1. SPI配置:配置为全双工主模式,数据大小8位,时钟极性(CPOL)和相位(CPHA)通常设置为0和0(模式0)。速度不宜过高,初期可设为5-10MHz。务必开启DMA传输,这将大大减轻CPU负担,尤其是在刷新全屏图像(32KB数据)时。
  2. GPIO配置:将RST、DC、CS、BUSY引脚配置为推挽输出(CS、DC、RST)和输入上拉(BUSY)。
  3. 定时器:用于提供精确的延时,替代HAL_Delay()
  4. ADC:用于读取板载温度传感器的电压值。

驱动流程优化

// 使用DMA传输显示数据的示例流程 void EPD_Refresh_Full(uint8_t *image_data) { EPD_SendCommand(0x24); // 写入黑/白RAM EPD_SetDC(1); // DC置高,后续为数据 HAL_SPI_Transmit_DMA(&hspi1, image_data, IMAGE_SIZE); // 等待DMA传输完成 while (__HAL_SPI_GET_FLAG(&hspi1, HAL_SPI_FLAG_BSY)); EPD_UpdateDisplay(); // 发送刷新命令 EPD_WaitBusy(); // 等待刷新完成 }

在STM32上,你可以实现更精细的功耗控制。例如,在屏幕进入sleep模式后,可以将连接屏幕的GPIO(除CS外)设置为模拟输入以降低功耗,甚至关闭SPI外设的时钟。同时,利用STM32的低功耗模式(Stop模式),结合RTC定时唤醒刷新屏幕,可以构建出续航数周甚至数月的超低功耗显示设备。

4. 图像处理与显示优化:让内容更出彩

直接显示黑白二值图像往往不够美观。如何生成适合电子墨水屏显示的图像内容,是一门小学问。

4.1 图像二值化与抖动算法

电子墨水屏本质是单色(或三色)设备,显示彩色或灰度图片需要先进行二值化处理。最简单的二值化是设定一个阈值,高于阈值的像素为白,低于为黑。但这样会丢失大量细节。

Floyd-Steinberg误差扩散抖动算法是电子墨水屏显示图片的常用技巧。它的原理是将一个像素的二值化误差(比如,一个灰度值为120的像素被强行设为255白色,产生了-135的误差),按一定比例扩散到它右、右下、下、左下的邻居像素上。这样,从整体上看,图像的明暗关系得以保留,视觉效果远好于简单二值化。

在Python中,使用PIL库可以轻松实现:

from PIL import Image image_gray = Image.open('input.jpg').convert('L') # 转换为灰度图 # 方法1:简单阈值二值化 image_bw_simple = image_gray.point(lambda x: 0 if x < 128 else 255, '1') # 方法2:误差扩散抖动 image_bw_dithered = image_gray.convert('1', dither=Image.FLOYDSTEINBERG) # 对比保存,可以看到dithered后的图片层次感好很多 image_bw_dithered.save('output_dithered.bmp')

对于STM32/Arduino,如果需要在资源受限的MCU上实现抖动,可以考虑预先在PC上处理图片,然后将处理后的二值化位图数据以数组形式存储在MCU的Flash中。

4.2 局部刷新与全局刷新的艺术

为了平衡显示质量和功耗,必须善用两种刷新模式。

  • 全局刷新(Full Update):驱动屏幕的所有像素点进行一次完整的“清零-写入”周期。效果最好,无残影,但耗时(约2-4秒)耗电。适用于首次显示、更换完全不同的画面、或定期(如每24小时一次)清除残影。
  • 局部刷新(Partial Update):只刷新屏幕上发生变化的部分区域。速度极快(可能只需几百毫秒),功耗低。但连续多次局部刷新后,屏幕可能会出现轻微的“残影”或“鬼影”,因为电子粒子没有经过完整的复位过程。

最佳实践策略

  1. 项目启动时,执行一次全局刷新,确保干净的初始状态。
  2. 在后续的日常数据更新中(如更新温度、时间),使用局部刷新。
  3. 设定一个计数器,每进行N次(例如50次)局部刷新后,强制进行一次全局刷新,以消除累积的残影。
  4. 如果显示的内容对比度强烈、变化区域大(比如从黑底白字切换到白底黑字),建议直接使用全局刷新,因为局部刷新在这种场景下效果可能不佳。

在Waveshare的库中,通常会有类似epd.displayPartBaseImage()epd.displayPart()这样的函数来支持局部刷新。使用时需要注意,局部刷新前,有时需要先指定一个“基准图像”(Base Image),后续的局部更新都是基于这个基准图像进行的。

4.3 字体与UI设计考量

在640x400的分辨率下,显示文字有很好的效果。但要注意:

  • 字体选择:优先选择笔画清晰、无衬线的等宽字体,如文泉驿微米黑、DejaVu Sans Mono。避免使用笔画过细的字体,在二值化后可能断裂。
  • 字号大小:对于中文,24点阵或以上大小才能保证较好的可读性。英文可以稍小,如16或18点阵。
  • 反色与闪烁:避免频繁地全屏反色(黑变白,白变黑),这相当于一次全局刷新,且视觉效果突兀。更新UI时,尽量采用“增量更新”的方式,只重绘变化的区域。
  • 帧率管理:电子墨水屏不是为动画设计的。任何变化都应有明确的用户触发或定时触发,避免尝试制作连续动画,那会导致屏幕疯狂刷新,体验很差且伤屏。

5. 实战避坑与进阶技巧

在实际项目中,总会遇到一些预料之外的问题。这里分享几个我踩过的坑和总结的技巧。

5.1 常见问题排查清单

问题一:屏幕初始化失败,全白或全黑,无任何反应。

  • 检查电源:首先用万用表测量HAT板的5V输入电压是否稳定。尝试使用外部USB电源单独为HAT供电。
  • 检查排线:这是最高发的问题。关闭电源,重新拔插屏幕排线,确保金手指完全插入且锁扣扣紧。
  • 检查拨码开关:确认已拨到SPI模式。
  • 检查GPIO连接:如果使用杜邦线连接非树莓派主板,务必检查每一根线是否连接牢固,特别是RST、DC、BUSY这几个控制引脚。
  • 检查代码初始化顺序:确保代码中严格按照硬件复位->发送初始化命令->等待BUSY的顺序执行。在init()函数前增加几秒延时有时能解决上电时序问题。

问题二:显示内容有重影或残影严重。

  • 温度影响:确认温度传感器工作正常。在过冷(<5°C)或过热(>35°C)环境下,显示质量会下降。可以尝试在代码中手动指定一个固定的、适合当前环境的LUT进行测试。
  • 刷新模式误用:确认你是否在应该用全局刷新的地方用了局部刷新。尝试执行一次epd.Clear()看看能否消除。
  • 供电不足:全局刷新时电压跌落可能导致刷新波形能量不足,粒子移动不到位。强化电源(如使用带稳压的5V2A适配器)。

问题三:刷新速度异常缓慢。

  • SPI时钟速度:检查主控的SPI时钟频率设置。对于树莓派,可以尝试在初始化SPI时提高速度(如增加到20MHz)。对于STM32,检查SPI分频系数。
  • 软件延时:检查代码中是否有多余的delay()。驱动库中必要的延时不能省,但业务逻辑中的延时应优化。
  • 图像处理耗时:在树莓派上,用PIL处理大图可能较慢。可以考虑预先生成好图片,或者使用更高效的库(如OpenCV)。

5.2 低功耗设计实战

要打造一个电池供电的天气站或信息牌,低功耗设计是核心。

  1. 主控睡眠:让树莓派或STM32在屏幕刷新完成后进入深度睡眠。对于树莓派,可以安装rtc-wake或使用硬件看门狗定时唤醒。对于STM32,可以使用Stop或Standby模式,配合RTC闹钟或外部中断唤醒。
  2. 屏幕彻底断电:在长期间歇性显示的场景,可以考虑在屏幕sleep()后,通过一个MOSFET开关电路,彻底切断屏幕模块的5V供电。下次需要显示时,先上电,再初始化。这需要额外的电路,但能将静态功耗降到真正的零。
  3. 刷新策略优化:这是软件层面的关键。设计一个“脏矩形”机制,只记录屏幕上需要更新的最小区域,然后仅刷新这个区域。将多次小的数据更新(如每秒更新的秒数)缓冲起来,合并成一次较大的局部刷新,比如每分钟刷新一次。

5.3 扩展思考:多屏幕同步与级联

一个有趣的想法是,能否用一块主控驱动多块电子墨水屏?理论上,只要SPI总线负载允许,可以通过不同的CS片选引脚来控制多个屏幕。但需要注意:

  • GPIO资源:每增加一块屏幕,就需要额外占用一个CS引脚、一个BUSY引脚(如果不想轮询,可以接中断)、一个RST和DC引脚。IO可能很快就不够用了。
  • 电源负载:多块屏幕同时刷新时,峰值电流会叠加,对电源是巨大考验。必须错开它们的刷新时间。
  • 软件架构:需要抽象出一个屏幕管理器,维护每块屏幕的帧缓冲区和状态(是否忙)。刷新时,依次选中各屏幕进行数据传输。

我曾尝试用一块树莓派驱动两块4英寸屏,错开1秒刷新,用来显示不同的信息板块,基本可行。但更复杂的应用,可能需要使用带更多硬件SPI或GPIO的主控,或者使用IO扩展芯片。

玩转这块4英寸电子墨水屏的过程,更像是在和一种特殊的物理现象打交道。你需要理解它的“脾气”——怕冷怕热、刷新慢、静态省电。当你根据它的特性去设计应用时,就能做出那些LCD屏幕难以胜任的、独特而优雅的产品。从简单的文字显示器到复杂的低功耗仪表盘,它的可能性远比第一眼看上去要多。最后一个小建议,多看看厂商提供的例程和文档,但更要敢于跳出例程,去尝试自己的刷新策略和图像处理算法,那才是真正乐趣的开始。

http://www.jsqmd.com/news/1309546/

相关文章:

  • Kafka-King深度解析:3大核心功能解锁可视化Kafka管理完整攻略
  • LibreOffice Online完整指南:5步搭建私有在线办公平台
  • Android-EDLA 谷歌安全补丁、GMS包以及mainline包更新
  • 1.69英寸LCD模块选型、驱动与优化全攻略
  • 椰林海鲜码头联系地址? - 晴光转树
  • 2026 年至今,月湖优秀的不锈钢桥架源头厂家怎么联系,户外工程用这玩意儿,竟能扛住10年沿海盐雾腐蚀不生锈? - 行业严选官
  • 【单片机毕业设计】基于 STC89C52 的室内烟雾温湿度安防调控系统设计 基于 51 单片机的阈值可调环境智能报警装置设计(017901)
  • IDE+笔记+Agent如何分工?LobsterAI在2026工具栈的3条执行边界
  • 杰理开发入门分享:工具链选型与调试实践
  • 2026 年新发布:周口热门的894无缝钢管供货商有哪些,揭秘89脑4鏃犵紳閽㈢:你必须知道的底层逻辑 - 企业官方推荐【认证】
  • DeepFace人脸对齐性能优化实战指南:5个技巧解决卡顿问题
  • Zenodo数据下载终极指南:3个简单步骤告别科研数据获取烦恼
  • .NET Core终极安装指南:3分钟完成跨平台部署
  • 2026柳州黄金回收白银回收铂金回收市民首选无隐形扣费正规备案回收门店联系方式推荐
  • 终极免费Windows屏幕标注工具:ppInk完全使用指南
  • 钛基熔覆粉末10问—氧化怎么防?流动性差怎么办?回收粉能用吗
  • 广州市海鲜餐厅哪家好:【椰林海鲜码头】回味悠长 - 秋山寄远
  • vue3 为什么需要toRef和toRefs
  • 【单片机毕业设计】基于 MPU6050 的人体姿态安全监测终端开发 基于 STM32 的环境光照自适应照明控制系统(018001)
  • 孤能子视角:EIS安全论看国家总体安全观、统筹发展与安全
  • 10分钟学会用SIMD-Visualiser调试SIMD代码:新手必备的可视化排错技巧
  • 2026年节能极窄门窗厂家选型推荐:大宅极简门窗定制厂家盘点 - 海棠依旧大
  • 终极Windows屏幕捕获指南:如何用Python实现240FPS高性能截图
  • 34-数据科学-数据分析与可视化
  • 欧卡2自动驾驶革命:ETS2LA如何让长途驾驶变得轻松有趣
  • 5分钟掌握Reloaded-II:跨平台游戏模组加载神器
  • C++编译错误no matching function for call to的深度解析与实战排查指南
  • 100% 成本清零!行业通用表述不侵权,跨境版权 TRO 应诉复盘!
  • 惠州黄金回收正规商家评测:惠奢汇(惠城旗舰店)凭双资质领跑,附避坑指南 - 生活测评小能手
  • 快速生成奶茶创意海报:低成本做出治愈系广告素材