跳转至

epd 墨水屏操作库

作者:江访 | 最后修改:2026-08-19

一、概述

epd 是 LuatOS 的电子墨水屏操作库,基于 tiny_epd 组件实现,支持微雪电子多款 1.54 英寸墨水屏,覆盖黑白(BW)、黑白红(BWR)、黑白红黄(BWRY)三类颜色面板。

与 eink 库不同,epd 库采用面向对象的调用方式:先调用 epd.open() 打开屏幕得到 panel 对象,再通过 panel 对象的方法完成初始化、绘图、刷新、休眠等操作。屏幕刷新采用异步机制,不会阻塞业务代码。

epd 库提供如下几大类功能:

  1. 屏幕打开与初始化:支持 7 种内置型号和自定义屏幕(custom 模式)

  2. 基本图形绘制:直线、矩形、圆形、像素点等基本图形的绘制

  3. 文本显示:支持 UTF-8 中英文字体显示(需固件启用 HZFont 功能)

  4. 位图显示:支持 XBM 格式位图显示

  5. 二维码生成:支持二维码生成和显示

  6. 多种刷新模式:全刷(FULL)、快刷(FAST)、局部刷新(PARTIAL)、局部区域刷新(PARTIAL_RECT)、自动刷新(AUTO)

主要特性:

  1. 支持 7 种逻辑颜色(黑/白/红/黄/橙/蓝/绿),自动映射到当前面板支持的物理颜色

  2. 支持画布旋转(0/90/180/270 度),旋转后坐标自动适配

  3. 刷新异步执行,可通过返回值查询刷新结果

  4. 支持自定义屏幕(custom 模式),通过命令序列描述任意墨水屏控制器,无需编写 C 驱动

注意事项:

  1. 墨水屏刷新速度较慢,不适合频繁更新的场景

  2. 使用前必须先初始化 SPI,再调用 epd.open()

  3. 一次刷新进行期间(刷新未完成),再次调用其他接口会返回 false, "busy"

  4. 中文文本绘制(panel:drawHzfont())需要固件启用 HZFont 功能,是否支持以具体产品固件为准

  5. 不同型号支持的刷新模式、颜色不同,可通过 panel:supportsColor()panel:info() 查询

二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo。

关于错误处理写法说明:示例中使用 if not ... then log.error(...) return end 的判断方式处理错误,这是实际业务开发推荐的写法。epd 库的大部分接口在失败时返回 false 和错误信息字符串,业务代码应根据返回值做相应处理;直接使用 assert() 断言会导致失败时程序异常终止,仅适合开发调试阶段。

2.1 核心代码

-- 本核心示例演示 epd 库的基本使用流程:
-- 1、初始化 SPI 设备
-- 2、打开并初始化墨水屏
-- 3、绘制文本和图形
-- 4、刷新显示到屏幕

-- 按实际接线配置 SPI 编号和 GPIO 引脚号
local spi_id = 0
local pin_cs   = 8    -- 片选引脚
local pin_dc   = 10   -- 数据/命令引脚
local pin_rst  = 1    -- 复位引脚
local pin_busy = 22   -- 忙检测引脚

-- 主函数
local function main()
    -- 注意:epd.open() 之前必须先初始化 SPI,使用 spi.deviceSetup() 方式初始化
    -- 注意:spi_epd 不加 local,后续示例会继续复用该 SPI 设备对象
    spi_epd = spi.deviceSetup(spi_id, pin_cs, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)

    -- 打开 1.54 英寸黑白墨水屏,port="device" 表示使用上面创建的 SPI 对象
    local panel, err = epd.open(epd.MODEL_1IN54,
        { port = "device", pin_dc = pin_dc, pin_rst = pin_rst, pin_busy = pin_busy },
        spi_epd)
    if not panel then
        log.error("epd", "打开屏幕失败", err)
        return
    end

    -- 初始化屏幕
    if not panel:init() then
        log.error("epd", "初始化失败")
        return
    end

    -- 清屏为白色
    panel:clear(epd.WHITE)

    -- 设置当前前景色为黑色、背景色为白色
    panel:setColor(epd.BLACK, epd.WHITE)

    -- 绘制外边框(矩形,空心)
    panel:rect(0, 0, 199, 199, epd.BLACK, 0)

    -- 绘制分割线(直线)
    panel:line(0, 30, 199, 30, epd.BLACK)

    -- 绘制实心圆形
    panel:circle(50, 110, 30, epd.BLACK, 1)

    -- 绘制空心矩形
    panel:rect(100, 80, 180, 140, epd.BLACK, 0)

    -- 绘制二维码
    panel:qrcode(20, 150, "https://docs.openluat.com", 60, epd.BLACK)

    -- 异步刷新整屏,.wait() 等待刷新完成,返回 true 或 false + 错误信息
    local ok, rerr = panel:refresh(epd.FULL).wait()
    if not ok then
        log.error("epd", "刷新失败", rerr)
        return
    end

    -- 使用完毕后进入休眠,降低功耗
    panel:sleep(epd.SLEEP_DEEP)
end

-- 运行主函数
sys.taskInit(main)

2.2 局部刷新示例

-- 本示例演示局部区域刷新,适合只更新屏幕局部内容的场景
-- 局部刷新可以显著缩短单次刷新耗时,但最终效果以屏幕硬件支持为准

local function main()
    -- 注意:spi_epd 不加 local,与其他示例保持一致的全局变量写法
    spi_epd = spi.deviceSetup(0, 8, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)
    local panel, err = epd.open(epd.MODEL_1IN54,
        { port = "device", pin_dc = 10, pin_rst = 1, pin_busy = 22 }, spi_epd)
    if not panel then
        log.error("epd", "打开屏幕失败", err)
        return
    end
    panel:init()
    panel:clear(epd.WHITE)

    -- 在指定区域绘制一个像素点
    panel:pixel(12, 18, epd.BLACK)

    -- 只刷新该像素点所在的局部区域(x, y, w, h)
    -- 注意:仅 PARTIAL_RECT 模式支持指定区域,且需要屏幕硬件支持局部刷新
    local ok, rerr = panel:refresh(epd.PARTIAL_RECT, 10, 16, 5, 5).wait()
    if not ok then
        log.error("epd", "局部刷新失败", rerr)
        return
    end

    panel:sleep(epd.SLEEP_DEEP)
end

sys.taskInit(main)

三、常量详解

核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;

如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;

3.1 屏幕型号常量

屏幕型号常量用于 epd.open() 的第一个参数,指定墨水屏的具体型号。

epd.MODEL_1IN54

常量含义:微雪 1.54 英寸黑白墨水屏,分辨率 200x200
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54_V2

常量含义:微雪 1.54 英寸黑白墨水屏 V2 版本,分辨率 200x200
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54_V2, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54_V3

常量含义:微雪 1.54 英寸黑白墨水屏 V3 版本,分辨率 200x200
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54_V3, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54_SSD1607

常量含义:SSD1607 控制器 1.54 英寸黑白墨水屏,分辨率 200x200
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54_SSD1607, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54R

常量含义:微雪 1.54 英寸黑白红墨水屏,分辨率 152x152
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54R, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54B_V2

常量含义:微雪 1.54 英寸黑白红墨水屏 V2 版本,分辨率 200x200
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54B_V2, opts, spi_epd)
适用产品型号:以固件支持列表为准;

epd.MODEL_1IN54G_V2

常量含义:微雪 1.54 英寸四色墨水屏(黑白红黄),分辨率 200x200,支持快刷;
数据类型:number
参数示例:epd.open(epd.MODEL_1IN54G_V2, opts, spi_epd)
适用产品型号:以固件支持列表为准;

custom 模式(字符串 "custom")

常量含义:自定义墨水屏模式,通过命令序列描述屏幕初始化、刷新、休眠时序;
注意事项:该模式没有对应的数字常量,直接在 epd.open() 的第一个参数传入字符串 "custom"
         使用该模式时,opts 配置表中必须额外提供 widthheightinitrefresh 等自定义配置,详见 4.1.1 函数详解;
参数示例:epd.open("custom", custom_opts, spi_epd)
适用产品型号:以固件支持列表为准;

3.2 颜色常量

颜色常量用于绘图接口的 color 参数,如 panel:pixel()panel:line()panel:rect()panel:circle() 等。epd 库会自动把逻辑颜色映射到当前面板支持的物理颜色。

epd.BLACK    -- 黑色
epd.WHITE    -- 白色
epd.RED      -- 红色
epd.YELLOW   -- 黄色
epd.ORANGE   -- 橙色
epd.BLUE     -- 蓝色
epd.GREEN    -- 绿色

注意事项:

  1. 并非所有面板都支持所有颜色,黑白屏只支持 epd.BLACKepd.WHITE

  2. 调用 panel:setColor(fg, bg) 设置不支持的组合颜色时,会返回 false 和错误信息

  3. 可通过 panel:supportsColor(color) 查询某个颜色是否受当前面板支持

3.3 刷新模式常量

刷新模式常量用于 panel:refresh() 的参数,指定屏幕刷新的方式。

常量 说明 适用场景
epd.FULL 全屏刷新,画面整体刷新一次 首次显示、整屏内容变化时
epd.FAST 快速刷新,刷新耗时短,但残留较重 支持快刷的屏幕(如 MODEL_1IN54G_V2),需要频繁更新的场景
epd.PARTIAL 局部刷新(部分 LUT + 完整帧缓冲传输),刷新全帧但显示效果残留较小 屏幕支持局部刷新时
epd.PARTIAL_RECT 局部区域刷新(部分 LUT + 指定矩形区域),只刷新指定区域 屏幕支持局部区域刷新,且只想更新局部内容时
epd.AUTO 自动刷新,屏幕支持局部刷新时自动选择局部刷新,否则全屏刷新 不确定选哪个时,建议使用默认值

注意事项:

  1. panel:refresh() 不带参数时默认使用全屏刷新(FULL)

  2. 并非所有型号都支持局部刷新,可通过 panel:info().caps 查询能力位

3.4 休眠模式常量

休眠模式常量用于 panel:sleep() 的参数,指定屏幕进入的休眠状态。

常量 说明 适用场景
epd.SLEEP_AUTO 自动休眠,由驱动按屏幕能力选择最深的休眠模式 不确定选哪个时,使用默认值即可
epd.SLEEP_STANDBY 待机休眠 屏幕支持待机模式时
epd.SLEEP_DEEP 深度休眠,功耗最低 长时间不再刷新屏幕时

注意事项:

  1. panel:sleep() 不带参数时默认使用 SLEEP_AUTO

  2. 深度休眠后,再次刷新屏幕前需要重新调用 panel:init() 初始化

3.5 帧缓冲格式常量

帧缓冲格式常量用于自定义屏幕(custom 模式)和 panel:info() 返回的 format 字段。

epd.FORMAT_INDEX1     -- 1 位索引格式,黑白
epd.FORMAT_INDEX2     -- 2 位索引格式,4 色
epd.FORMAT_INDEX4     -- 4 位索引格式
epd.FORMAT_INDEX8     -- 8 位索引格式
epd.FORMAT_PLANAR1    -- 1 位平面格式

3.6 能力位常量

能力位常量用于 panel:info().caps 字段,按位组合标识面板支持的能力。

epd.CAP_REFRESH_FULL        -- 支持全屏刷新
epd.CAP_REFRESH_FAST        -- 支持快速刷新
epd.CAP_REFRESH_PARTIAL     -- 支持局部刷新
epd.CAP_REFRESH_PARTIAL_RECT-- 支持局部区域刷新
epd.CAP_SLEEP_STANDBY       -- 支持待机休眠
epd.CAP_SLEEP_DEEP          -- 支持深度休眠
epd.CAP_COLOR_BW            -- 支持黑白
epd.CAP_COLOR_BWR           -- 支持黑白红
epd.CAP_COLOR_BWY           -- 支持黑白黄
epd.CAP_COLOR_4             -- 支持 4 色
epd.CAP_COLOR_7             -- 支持 7 色
epd.CAP_GRAY                -- 支持灰度

3.7 抖动方式说明(需固件启用 HZFont)

panel:drawHzfont() 内部按阈值抖动方式将灰度文本二值化绘制,阈值固定为 128。

-- 当前版本 drawHzfont 不提供抖动方式常量
-- 如需调整文字灰度表现,可通过字号 size 参数间接控制

注意事项:

  1. 以上说明仅在固件启用 HZFont 功能时适用

  2. 当前版本未暴露 epd.DITHER_THRESHOLD / epd.DITHER_BAYER4 常量,请勿在代码中直接使用这两个名字,否则会报 attempt to index a nil value

四、函数详解

4.1 屏幕打开与初始化

4.1.1 epd.open(model, opts[, spi_device])

功能

打开墨水屏并创建 panel 对象。返回的 panel 对象用于调用后续所有屏幕操作接口。

参数

model

参数含义:墨水屏型号,使用 3.1 章节的屏幕型号常量,或直接传入型号名称字符串
数据类型:number/string
取值范围:epd.MODEL_1IN54、epd.MODEL_1IN54_V2、epd.MODEL_1IN54_V3、epd.MODEL_1IN54_SSD1607、
          epd.MODEL_1IN54R、epd.MODEL_1IN54B_V2、epd.MODEL_1IN54G_V2
          (也可传入型号名称字符串,如 "1in54"、"1in54_v2"、"custom")
是否必选:是
注意事项:custom 模式需要额外配置自定义屏幕参数,详见本函数示例
参数示例:epd.MODEL_1IN54

opts

参数含义:屏幕配置表,包含 SPI 端口和 GPIO 引脚配置
数据类型:table
取值范围:包含以下参数:

{
    参数含义:SPI 端口,可以是 SPI 编号或字符串 "device"
    数据类型:number/string
    取值范围:SPI 编号(如 0、1);或 "device" 表示使用第三个参数传入的 SPI 设备对象
    是否必选:是
    注意事项:使用 "device" 方式时必须同时传入第三个参数 spi_device
    参数示例:0 或 "device"
    opts.port ,

    参数含义:数据/命令引脚(DC)
    数据类型:number
    取值范围:有效 GPIO 编号
    是否必选:是
    参数示例:10
    opts.pin_dc ,

    参数含义:复位引脚(RST)
    数据类型:number
    取值范围:有效 GPIO 编号
    是否必选:是
    参数示例:1
    opts.pin_rst ,

    参数含义:忙检测引脚(BUSY)
    数据类型:number
    取值范围:有效 GPIO 编号
    是否必选:是
    参数示例:22
    opts.pin_busy ,

    参数含义:BUSY 引脚的上下拉配置
    数据类型:number
    取值范围:0 表示使用默认配置,其他值由固件平台决定(如 gpio.PULLUP / gpio.PULLDOWN)
    是否必选:否
    注意事项:默认 0,使用默认配置即可
    参数示例:0
    opts.busy_pull ,

    参数含义:BUSY 引脚轮询间隔,单位毫秒
    数据类型:number
    取值范围:大于等于 0
    是否必选:否
    注意事项:默认 0,此时使用库内部默认轮询间隔 10ms。一般无需修改
    参数示例:0
    opts.busy_poll_ms ,

    参数含义:画布旋转角度
    数据类型:number
    取值范围:0/90/180/270,或索引 0/1/2/3
    是否必选:否
    注意事项:不填默认 0 度。也可使用面板方法 panel:setRotation() 动态设置
    参数示例:0
    opts.rotation ,

    参数含义:画布方向(rotation 的别名)
    数据类型:number
    取值范围:同 rotation,0/90/180/270 或索引 0/1/2/3
    是否必选:否
    注意事项:当同时传入 rotation 和 direction 时,以 rotation 为准
    参数示例:0
    opts.direction ,
}

custom 模式附加配置(当 model 传入字符串 "custom" 时必须提供):

参数含义:自定义屏幕配置表,追加在 opts 中
数据类型:table
取值范围:包含以下参数:

{
    参数含义:屏幕像素宽度
    数据类型:number
    取值范围:1~65535
    是否必选:是
    opts.width ,

    参数含义:屏幕像素高度
    数据类型:number
    取值范围:1~65535
    是否必选:是
    opts.height ,

    参数含义:帧缓冲格式
    数据类型:number
    取值范围:epd.FORMAT_INDEX1(当前 custom 模式仅支持 1 位索引格式,即黑白屏)
    是否必选:否
    注意事项:如需自定义彩色屏,请使用内置型号或等待后续版本支持
    opts.format ,

    参数含义:BUSY 引脚空闲电平
    数据类型:number
    取值范围:0 或 1
    是否必选:否
    注意事项:默认 0
    opts.busy_level ,

    参数含义:BUSY 等待超时时间,单位毫秒
    数据类型:number
    取值范围:大于等于 0
    是否必选:否
    opts.busy_timeout ,

    参数含义:初始化命令序列
    数据类型:table
    取值范围:命令步骤列表,每一步支持以下格式之一:
             {cmd=命令字, data={数据...}} 发送命令及可选数据
             {reset={high=高电平毫秒, low=低电平毫秒, high2=再高电平毫秒}} 复位时序
             {delay=毫秒} 延时
             {busy=空闲电平[, timeout=毫秒]} 等待屏幕空闲
             {write_ram=命令字} 写入整帧 RAM
             {write_ram2=命令字} 写入第二平面 RAM
    是否必选:是
    参数示例:{ {reset={high=20, low=2, high2=20}}, {cmd=0x01, data={0x03}} }
    opts.init ,

    参数含义:快速刷新初始化命令序列(可选)
    数据类型:table
    取值范围:同 init
    是否必选:否
    opts.fast_init ,

    参数含义:刷新命令序列
    数据类型:table
    取值范围:包含 full / fast / partial 三个可选子序列,子序列格式同 init;
              其中 full 为必填
    是否必选:是(full 必填)
    参数示例:{ full = { {cmd=0x22, data={0xF7}} } }
    opts.refresh ,

    参数含义:休眠命令序列
    数据类型:table
    取值范围:包含 deep 子序列,格式同 init
    是否必选:否
    opts.sleep ,
}

spi_device

参数含义:SPI 设备对象
数据类型:userdata
取值范围:spi.deviceSetup() 的返回值
是否必选:仅当 opts.port = "device" 时必须传入
注意事项:使用该方式时,SPI 对象由 epd 库持有,panel 关闭时自动释放
参数示例:spi.deviceSetup(0, 8, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)

返回值

panel

含义说明:成功时返回墨水屏 panel 对象
数据类型:userdata
返回示例:epd 库定义的 panel 对象

err

含义说明:失败时返回错误信息
数据类型:string
注意事项:成功时无此返回值
返回示例:"unsupported epd model"

示例

-- ===== 方式一:使用 SPI 编号 =====
-- 适合已用 spi.setup() 配置好 SPI 的场景,opts 里直接用 SPI 编号
local panel, err = epd.open(epd.MODEL_1IN54,
    { port = 0, pin_dc = 10, pin_rst = 1, pin_busy = 22 })
if not panel then
    log.error("epd", "打开屏幕失败", err)
    return
end

-- ===== 方式二:使用 SPI 设备对象(推荐)=====
-- 注意:spi_epd 不加 local,后续示例会继续复用该 SPI 设备对象
spi_epd = spi.deviceSetup(0, 8, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)
local panel, err = epd.open(epd.MODEL_1IN54,
    { port = "device", pin_dc = 10, pin_rst = 1, pin_busy = 22 }, spi_epd)
if not panel then
    log.error("epd", "打开屏幕失败", err)
    return
end

-- ===== 方式三:2.13 寸墨水屏(custom 模式)=====
-- epd 库内置型号只覆盖 1.54 寸,其他尺寸屏幕需用 custom 模式,
-- 通过命令序列描述控制器的初始化、刷新、休眠时序。
-- 以下示例为微雪 2.13 寸 e-Paper V4(122x250)的完整配置,其他型号需对照其官方驱动改写。
spi_epd = spi.deviceSetup(0, 8, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)

local panel, err = epd.open("custom", {
    port = "device",
    pin_dc = 10,          -- 数据/命令引脚
    pin_rst = 1,          -- 复位引脚
    pin_busy = 2,         -- 忙检测引脚
    width = 122,          -- 控制器 RAM 宽(竖屏 122x250)
    height = 250,         -- 控制器 RAM 高
    busy_level = 0,       -- BUSY 空闲电平
    busy_timeout = 30000, -- BUSY 等待超时(毫秒)
    -- 初始化命令序列(对照官方 EPD_2in13_V4_Init())
    init = {
        {reset = {high = 20, low = 2, high2 = 20}},   -- 复位时序
        {busy = 0},                                   -- 等待空闲
        {cmd = 0x12},                                 -- SWRESET 软复位
        {busy = 0},
        {cmd = 0x01, data = {0xF9, 0x00, 0x00}},      -- 驱动输出控制
        {cmd = 0x11, data = {0x03}},                  -- 数据进入模式
        {cmd = 0x44, data = {0x00, 0x0F}},            -- 设置 RAM X 范围
        {cmd = 0x45, data = {0x00, 0x00, 0xF9, 0x00}},-- 设置 RAM Y 范围
        {cmd = 0x4E, data = {0x00}},                  -- 设置 RAM X 指针
        {cmd = 0x4F, data = {0x00, 0x00}},            -- 设置 RAM Y 指针
        {cmd = 0x3C, data = {0x05}},                  -- 边框波形
        {cmd = 0x21, data = {0x00, 0x80}},            -- 显示更新控制
        {cmd = 0x18, data = {0x80}},                  -- 读取内置温度传感器
        {busy = 0},
    },
    -- 刷新命令序列(full 全刷 / partial 局部刷)
    refresh = {
        full = {
            {cmd = 0x44, data = {0x00, 0x0F}},
            {cmd = 0x45, data = {0x00, 0x00, 0xF9, 0x00}},
            {cmd = 0x4E, data = {0x00}},
            {cmd = 0x4F, data = {0x00, 0x00}},
            {write_ram = 0x24},       -- 写整帧 RAM(0x24)
            {write_ram2 = 0x26},      -- 写第二平面 RAM(0x26),建立局部刷新基帧
            {cmd = 0x22, data = {0xF7}},  -- 显示更新控制
            {cmd = 0x20},                 -- 激活显示更新
            {busy = 0},
        },
        partial = {
            {reset = {high = 0, low = 1, high2 = 20}},
            {cmd = 0x3C, data = {0x80}},
            {cmd = 0x01, data = {0xF9, 0x00, 0x00}},
            {cmd = 0x11, data = {0x03}},
            {cmd = 0x44, data = {0x00, 0x0F}},
            {cmd = 0x45, data = {0x00, 0x00, 0xF9, 0x00}},
            {cmd = 0x4E, data = {0x00}},
            {cmd = 0x4F, data = {0x00, 0x00}},
            {write_ram = 0x24},
            {cmd = 0x22, data = {0xFF}},  -- 局部刷新显示更新
            {cmd = 0x20},
            {busy = 0},
        },
    },
    -- 休眠命令序列(进入深度睡眠)
    sleep = {
        deep = {
            {cmd = 0x10, data = {0x01}},  -- 深度睡眠
            {delay = 100},
        },
    },
}, spi_epd)
if not panel then
    log.error("epd", "打开 2.13 寸屏失败", err)
    return
end

-- 旋转 90 度,将 122x250 竖屏变为 250x122 横屏使用
panel:setRotation(90)

4.1.2 panel:init()

功能

初始化墨水屏。执行屏幕上电、复位、初始化命令序列等操作。打开屏幕后必须先调用本方法,才能进行绘图和刷新。

参数

返回值

result

含义说明:初始化是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

err

含义说明:失败时的错误信息
数据类型:string
注意事项:成功时无此返回值
返回示例:"invalid parameter"

示例

-- 打开屏幕后必须先初始化
local panel, err = epd.open(epd.MODEL_1IN54,
    { port = "device", pin_dc = 10, pin_rst = 1, pin_busy = 22 }, spi_epd)
if not panel then
    log.error("epd", "打开屏幕失败", err)
    return
end

-- 初始化屏幕,成功后才能绘图和刷新
if not panel:init() then
    log.error("epd", "初始化失败")
    return
end

4.1.3 panel:close()

功能

关闭并释放墨水屏资源。关闭后 panel 对象不再可用,需要重新调用 epd.open() 才能再次使用屏幕。

参数

返回值

result

含义说明:关闭是否成功
数据类型:boolean
取值范围:true 成功
返回示例:true

示例

-- 使用完毕后关闭并释放屏幕资源
panel:close()

4.2 屏幕控制

4.2.1 panel:refresh([mode[, x, y, w, h]])

功能

刷新屏幕,将帧缓冲区内容显示到屏幕上。本方法为异步执行,返回一个可等待的结果对象,通过 .wait() 等待刷新完成。

参数

mode

参数含义:刷新模式
数据类型:number
取值范围:epd.FULL(默认)、epd.FAST、epd.PARTIAL、epd.PARTIAL_RECT、epd.AUTO
是否必选:否
注意事项:不带参数时默认全屏刷新(FULL)。FAST/PARTIAL/PARTIAL_RECT 需要屏幕硬件支持,可查看面板 info().caps 能力位确认
参数示例:epd.FULL

x

参数含义:局部刷新区域的起点 X 坐标
数据类型:number
取值范围:0~65535,且必须在画布范围内
是否必选:仅当 mode = epd.PARTIAL_RECT 时可选
注意事项:只有 PARTIAL_RECT 模式支持传入区域参数;其他模式传入多余参数会返回参数错误
参数示例:10

y

参数含义:局部刷新区域的起点 Y 坐标
数据类型:number
取值范围:0~65535,且必须在画布范围内
是否必选:仅当 mode = epd.PARTIAL_RECT 时可选
注意事项:只有 PARTIAL_RECT 模式支持传入区域参数
参数示例:16

w

参数含义:局部刷新区域的宽度
数据类型:number
取值范围:0~65535,且必须在画布范围内
是否必选:仅当 mode = epd.PARTIAL_RECT 时可选
注意事项:只有 PARTIAL_RECT 模式支持传入区域参数
参数示例:5

h

参数含义:局部刷新区域的高度
数据类型:number
取值范围:0~65535,且必须在画布范围内
是否必选:仅当 mode = epd.PARTIAL_RECT 时可选
注意事项:只有 PARTIAL_RECT 模式支持传入区域参数
参数示例:5

返回值

result

含义说明:异步刷新结果,需调用 .wait() 获取
数据类型:cwait 结果对象
取值范围:.wait() 返回 true 表示刷新成功;返回 false 和错误信息表示刷新失败
注意事项:刷新进行期间再次调用屏幕接口会返回 false, "busy"
返回示例:panel:refresh(epd.FULL).wait()

示例

-- 全屏刷新并等待完成
local ok, rerr = panel:refresh(epd.FULL).wait()
if not ok then
    log.error("epd", "全屏刷新失败", rerr)
end

-- 局部区域刷新(仅 PARTIAL_RECT 支持指定区域)
panel:pixel(12, 18, epd.BLACK)
local ok, rerr = panel:refresh(epd.PARTIAL_RECT, 10, 16, 5, 5).wait()
if not ok then
    log.error("epd", "局部刷新失败", rerr)
end

4.2.2 panel:sleep([mode])

功能

进入休眠状态,降低屏幕功耗。深度休眠后,再次刷新屏幕前需要重新调用 panel:init()

参数

mode

参数含义:休眠模式
数据类型:number/string
取值范围:epd.SLEEP_AUTO(默认)/ epd.SLEEP_STANDBY / epd.SLEEP_DEEP,或字符串 "auto" / "standby" / "deep"
是否必选:否
注意事项:不带参数时默认 SLEEP_AUTO。长时间不再刷新屏幕时建议使用 SLEEP_DEEP,功耗最低
参数示例:epd.SLEEP_DEEP

返回值

result

含义说明:休眠是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 长时间不再刷新时使用深度休眠,功耗最低
panel:sleep(epd.SLEEP_DEEP)

4.2.3 panel:setRotation(rotate)

功能

设置画布旋转方向。旋转后,逻辑画布宽高会互换(90/270 度),后续绘图坐标自动适配。

参数

rotate

参数含义:旋转角度
数据类型:number
取值范围:0/90/180/270(角度值),或 0/1/2/3(索引值)
是否必选:是
注意事项:旋转以屏幕物理方向为基准,旋转后 (0,0) 原点位置随之改变
参数示例:90

返回值

result

含义说明:设置是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 旋转 90 度后再绘图
panel:setRotation(90)
panel:line(0, 0, 100, 100, epd.BLACK)

4.2.4 panel:clear([color])

功能

清空画布为指定颜色。只修改内存中的帧缓冲区,需调用 panel:refresh() 刷新后屏幕才显示。

参数

color

参数含义:清屏颜色
数据类型:number
取值范围:epd.BLACK / epd.WHITE / epd.RED 等 3.2 章节颜色常量;不带参数时使用当前背景色
是否必选:否
注意事项:所传颜色必须是当前面板支持的逻辑颜色,否则返回 false
参数示例:epd.WHITE

返回值

result

含义说明:清屏是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 清屏为白色
panel:clear(epd.WHITE)

4.3 颜色设置

4.3.1 panel:setColor(fg, bg)

功能

设置当前前景色和背景色。设置后,后续未显式传颜色的绘图接口默认使用当前前景色绘制、背景色填充。

参数

fg

参数含义:前景色
数据类型:number
取值范围:epd.BLACK / epd.WHITE / epd.RED 等 3.2 章节颜色常量
是否必选:是
注意事项:前景色和背景色必须都是当前面板支持的逻辑颜色,否则返回 false
参数示例:epd.BLACK

bg

参数含义:背景色
数据类型:number
取值范围:同 fg
是否必选:是
注意事项:同上
参数示例:epd.WHITE

返回值

result

含义说明:设置是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 设置黑色前景、白色背景
panel:setColor(epd.BLACK, epd.WHITE)

4.3.2 panel:getColor()

功能

获取当前前景色和背景色。

参数

返回值

fg

含义说明:当前前景色
数据类型:number
取值范围:3.2 章节颜色常量
返回示例:epd.BLACK(数值 0)

bg

含义说明:当前背景色
数据类型:number
取值范围:3.2 章节颜色常量
返回示例:epd.WHITE(数值 1)

示例

-- 获取当前前景色和背景色
local fg, bg = panel:getColor()
log.info("epd", "fg", fg, "bg", bg)

4.3.3 panel:supportsColor(color)

功能

查询某个逻辑颜色是否受当前面板支持。

参数

color

参数含义:要查询的逻辑颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:是
参数示例:epd.RED

返回值

result

含义说明:颜色是否受支持
数据类型:boolean
取值范围:true 支持;false 不支持
返回示例:false  -- 黑白屏不支持红色

示例

-- 查询红色是否受当前面板支持
if panel:supportsColor(epd.RED) then
    log.info("epd", "支持红色")
end

4.4 基本图形绘制

4.4.1 panel:pixel(x, y[, color])

功能

在指定位置绘制一个像素点。

参数

x

参数含义:像素点 X 坐标
数据类型:number
取值范围:-32768~32767,实际有效范围为画布内
是否必选:是
参数示例:12

y

参数含义:像素点 Y 坐标
数据类型:number
取值范围:-32768~32767,实际有效范围为画布内
是否必选:是
参数示例:18

color

参数含义:像素颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 在 (12, 18) 绘制一个黑色像素点
panel:pixel(12, 18, epd.BLACK)

4.4.2 panel:line(x0, y0, x1, y1[, color])

功能

绘制一条直线,从起点 (x0, y0) 到终点 (x1, y1)。

参数

x0

参数含义:直线起点的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:0

y0

参数含义:直线起点的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:0

x1

参数含义:直线终点的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:100

y1

参数含义:直线终点的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:100

color

参数含义:线条颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 绘制从 (0,0) 到 (100,100) 的黑色直线
panel:line(0, 0, 100, 100, epd.BLACK)

4.4.3 panel:rect(x, y, x2, y2[, color[, fill]])

功能

绘制矩形,左上角 (x, y) 到右下角 (x2, y2)。

参数

x

参数含义:矩形左上角的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:0

y

参数含义:矩形左上角的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:0

x2

参数含义:矩形右下角的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:199

y2

参数含义:矩形右下角的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:199

color

参数含义:矩形颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

fill

参数含义:是否填充
数据类型:number
取值范围:0 空心(默认);1 实心
是否必选:否
注意事项:默认 0 空心
参数示例:1

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 绘制实心矩形
panel:rect(0, 0, 199, 199, epd.BLACK, 1)

-- 绘制空心矩形
panel:rect(20, 20, 80, 80, epd.BLACK, 0)

4.4.4 panel:circle(x, y, r[, color[, fill]])

功能

绘制圆形,圆心 (x, y),半径 r。

参数

x

参数含义:圆心的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:100

y

参数含义:圆心的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:100

r

参数含义:半径
数据类型:number
取值范围:0~255
是否必选:是
参数示例:50

color

参数含义:圆形颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

fill

参数含义:是否填充
数据类型:number
取值范围:0 空心(默认);1 实心
是否必选:否
注意事项:默认 0 空心
参数示例:0

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 绘制空心圆形
panel:circle(100, 100, 50, epd.BLACK, 0)

-- 绘制实心圆形
panel:circle(100, 100, 20, epd.BLACK, 1)

4.5 位图与二维码

4.5.1 panel:drawXbm(x, y, width, height, data[, fg[, bg]])

功能

绘制 XBM 格式位图。XBM 数据逐行存储,每行占 ceil(width/8) 字节,字节内低位在左。

参数

x

参数含义:位图左上角的 X 坐标
数据类型:number
取值范围:-32768~32767,允许负值,屏幕外部分自动裁剪
是否必选:是
参数示例:20

y

参数含义:位图左上角的 Y 坐标
数据类型:number
取值范围:-32768~32767,允许负值,屏幕外部分自动裁剪
是否必选:是
参数示例:30

width

参数含义:位图像素宽度
数据类型:number
取值范围:1~65535
是否必选:是
参数示例:8

height

参数含义:位图像素高度
数据类型:number
取值范围:1~65535
是否必选:是
参数示例:8

data

参数含义:XBM 位图数据
数据类型:string
取值范围:长度至少为 ceil(width/8) * height 字节,每行 ceil(width/8) 字节,低位在左
是否必选:是
参数示例:string.char(0x81, 0x42, 0x24, 0x18, 0x24, 0x42, 0x81, 0x00)

fg

参数含义:置位(1)像素颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

bg

参数含义:清零(0)像素颜色
数据类型:number/nil
取值范围:3.2 章节颜色常量;传 nil 表示透明(不绘制清零像素)
是否必选:否
注意事项:不带参数时使用当前背景色;传 nil 表示清零像素透明
参数示例:epd.WHITE

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 绘制 8x8 XBM 位图,置位像素黑色,清零像素白色
local xbm = string.char(0x81, 0x42, 0x24, 0x18, 0x24, 0x42, 0x81, 0x00)
panel:drawXbm(20, 30, 8, 8, xbm, epd.BLACK, epd.WHITE)

-- 清零像素透明模式
panel:drawXbm(20, 30, 8, 8, xbm, epd.BLACK, nil)

4.5.2 panel:qrcode(x, y, str[, size[, color]])

功能

在指定位置绘制二维码。

参数

x

参数含义:二维码左上角的 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:10

y

参数含义:二维码左上角的 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:10

str

参数含义:二维码内容
数据类型:string
取值范围:任意字符串,实际可编码长度受二维码版本和画布大小限制
是否必选:是
参数示例:"https://openluat.com"

size

参数含义:二维码像素边长
数据类型:number
取值范围:0~65535;0 表示按剩余区域自动适配
是否必选:否
注意事项:默认 0,自动适配。指定大小时建议留出定位角(白边)余量
参数示例:120

color

参数含义:二维码颜色
数据类型:number
取值范围:3.2 章节颜色常量
是否必选:否
注意事项:不带参数时使用当前前景色
参数示例:epd.BLACK

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 在 (10,10) 绘制内容为 https://openluat.com 的二维码,边长 120
panel:qrcode(10, 10, "https://openluat.com", 120, epd.BLACK)

4.6 文本显示(需固件启用 HZFont)

4.6.1 panel:drawHzfont(x, y, text, size)

功能

绘制 UTF-8 编码文本,支持中文。文本以基线为基准绘制,y 参数为基线 Y 坐标。需固件启用 HZFont 功能,未启用时返回错误。

参数

x

参数含义:文本起始 X 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
参数示例:10

y

参数含义:文本基线 Y 坐标
数据类型:number
取值范围:-32768~32767
是否必选:是
注意事项:y 为文本基线的 Y 坐标,不是文字顶部
参数示例:36

text

参数含义:要绘制的文本
数据类型:string
取值范围:UTF-8 编码字符串,支持中文
是否必选:是
参数示例:"合宙LuatOS"

size

参数含义:字号
数据类型:number
取值范围:1~255
是否必选:是
参数示例:24

注意事项:

  1. 当前版本仅支持上述 4 个参数,不提供第 5 个样式表参数style

  2. 文字的前景色和背景色通过 panel:setColor(fg, bg) 设置,drawHzfont 内部使用当前前景/背景色绘制

  3. 不支持抗锯齿级别、灰度阈值、抖动方式等样式调节

返回值

result

含义说明:绘制是否成功
数据类型:boolean
取值范围:true 成功;false 失败
注意事项:失败时返回 false 和错误信息字符串
返回示例:true

示例

-- 先设置文字前景色和背景色
panel:setColor(epd.BLACK, epd.WHITE)

-- 绘制中文文本,字号 24
panel:drawHzfont(10, 36, "合宙LuatOS", 24)

-- 绘制英文文本
panel:drawHzfont(10, 68, "Hello World", 20)

4.6.2 panel:getHzfontWidth(text, size)

功能

获取指定字号下文本的像素宽度,可用于计算文本绘制位置。

参数

text

参数含义:要计算宽度的文本
数据类型:string
取值范围:UTF-8 编码字符串
是否必选:是
参数示例:"Hello"

size

参数含义:字号
数据类型:number
取值范围:1~255
是否必选:是
参数示例:20

返回值

width

含义说明:文本像素宽度
数据类型:number
取值范围:0 表示参数错误或文本为空
返回示例:60

示例

-- 计算文本宽度,用于居中显示
local w = panel:getHzfontWidth("Hello", 20)
local x = math.floor((200 - w) / 2)  -- 200 为屏幕宽度,居中计算
panel:drawHzfont(x, 40, "Hello", 20)

4.7 面板信息查询

4.7.1 panel:info()

功能

获取面板详细信息,包括画布尺寸、帧缓冲格式、颜色支持、能力位等。

参数

返回值

info

含义说明:面板信息表
数据类型:table
取值范围:包含以下字段:

{
    参数含义:逻辑画布宽度(已按旋转方向调整)
    数据类型:number
    info.width ,

    参数含义:逻辑画布高度(已按旋转方向调整)
    数据类型:number
    info.height ,

    参数含义:物理面板宽度
    数据类型:number
    info.native_width ,

    参数含义:物理面板高度
    数据类型:number
    info.native_height ,

    参数含义:帧缓冲每行字节数
    数据类型:number
    info.stride ,

    参数含义:每个像素位数
    数据类型:number
    info.bits_per_pixel ,

    参数含义:帧缓冲平面数
    数据类型:number
    info.plane_count ,

    参数含义:帧缓冲格式
    数据类型:number
    取值范围:epd.FORMAT_INDEX1 / FORMAT_INDEX2 / FORMAT_INDEX4 / FORMAT_INDEX8 / FORMAT_PLANAR1
    info.format ,

    参数含义:调色板颜色数量
    数据类型:number
    info.color_count ,

    参数含义:调色板,按索引排列的颜色描述表
    数据类型:table
    取值范围:每个元素包含 color(逻辑颜色)/ code(存储编码)/ rgb(RGB 值)
    info.palette ,

    参数含义:能力位掩码
    数据类型:number
    取值范围:按 3.6 章节能力位常量按位组合
    info.caps ,

    参数含义:当前旋转角度
    数据类型:number
    取值范围:0/90/180/270
    info.rotate ,
}

示例

-- 查询面板信息
local info = panel:info()
log.info("epd", "size", info.width, info.height, "format", info.format, "caps", info.caps)

-- 判断屏幕是否支持局部区域刷新
if bit.band(info.caps, epd.CAP_REFRESH_PARTIAL_RECT) ~= 0 then
    log.info("epd", "支持局部区域刷新")
end

五、产品支持说明

不同产品的 LuatOS 固件对 epd 核心库的支持情况不同,具体支持型号以固件为准。

各产品固件支持核心库列表详细说明参考下面链接:

Air780EX2/Air700ECP/Air780EPM/Air780EGP固件支持列表

Air700ECH/Air780EHM/EHV/EGH/EGG/EHU/EHN固件支持列表

Air8000系列所有型号固件支持列表

Air8101系列所有型号固件支持列表

六、更新说明

epd V 1.0

  1. 更新时间:2026-08-07

  2. 更新内容:

    • 初版,基于 tiny_epd 组件实现墨水屏操作库

    • 支持 7 种内置 1.54 英寸墨水屏型号和自定义屏幕(custom)模式

    • 支持直线、矩形、圆形、像素点、XBM 位图、二维码、UTF-8 文本绘制

    • 支持全刷、快刷、局部刷新、局部区域刷新、自动刷新五种刷新模式

    • 支持画布旋转、前景/背景色设置、逻辑颜色自动映射

    • 刷新采用异步机制,通过 cwait 方式等待刷新结果

搜索