跳转至

01 lcd核心库应用

作者:沈园园 | 最后修改:2026-04-20

一、概述

AirLCD_1000 是合宙推出的一款SPI接口,3.5寸屏,480*320 的LCD配件板,其中:

1、显示屏的驱动IC是:ST7796;

2、8个插针管脚:LCD_CLK LCD_SDA LCD_RST LCD_RS LCD_CS BKL VCC GND;

  • BKL:背光控制管脚,默认高电平,背光常亮;低电平时背光熄灭;
  • VCC:2.8V-3.3V;

3、适用于Air780系列/Air8000系列;

airui 是基于 LVGL 9.4 版本进行图形层封装的 LuatOS 核心库,把常用组件、事件管理、输入和基础视觉主题封装为更易上手的 Lua 接口,便于在支持 LuatOS 的设备和 PC 上统一开发。

建议使用airui来开发显示界面,airui demo参考:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/ui/airui/single

二、演示功能概述

1、核心主程序模块

  1. main.lua - 主程序入口,负责系统初始化和任务调度
  2. ui_main.lua - 用户界面主控模块,管理页面切换和事件分发

2、显示页面模块

  1. home_page.lua - 主页模块,提供应用入口和导航功能
  2. lcd_page.lua - LCD图形绘制演示模块
  3. customer_font_page.lua - 自定义字体演示模块

注意:同时使用自定义字体和非自定义字体需要使用V2020版本及以上固件

3、驱动模块

  1. lcd_drv.lua - LCD显示驱动模块,基于lcd核心库,lcd_drv和exlcd_drv二选一使用

  2. exlcd_drv.lua - LCD显示驱动模块,基于exlcd扩展库,lcd_drv和exlcd_drv二选一使用

  3. key_drv.lua - 按键驱动模块,管理BOOT键和PWR键

  4. customer_font_drv.lua - 自定义外部字体驱动功能模块

  5. hzfont_drv.lua - 合宙软件矢量字库(开发中)

customer_font_drv、hzfont_drv

可以都不启用

可以仅启用一种

可以启用任意两种

可以全

三、按键消息介绍

"KEY_EVENT" - 按键事件消息,包含按键类型和状态

  • boot键事件:boot_down(按下)、boot_up(释放)
  • pwr键事件:pwr_down(按下)、pwr_up(释放)

按键功能定义:

  • 主页:boot键(按下)选择/切换选项,pwr键(按下)确认
  • LCD页面:pwr键(按下)返回,boot键无功能
  • 自定义字体页面:pwr键(按下)返回,boot键无功能

四、准备硬件环境

1、Air780EHV核心板 × 1

2、AirLCD_1000 配件板 × 1

3、母对母杜邦线 × 14

4、TYPE-C 数据线 × 1

5、Air780EHV核心板和 AirLCD_1000配件板的硬件接线方式为:

  • Air780EHV核心板通过 TYPE-C USB 口供电(核心板正面开关拨到 ON 一端),此种供电方式下,VDD_EXT 引脚为 3.3V,可以直接给 AirLCD_1000配件板供电;
  • 为了演示方便,所以 Air780EHV核心板上电后直接通过 VBAT 引脚给 AirLCD_1000配件板供电;
  • 客户在设计实际项目时,一般来说,需要通过一个 GPIO 来控制 LDO 给配件板供电,这样可以灵活地控制配件板的供电,可以使项目的整体功耗降到最低;

LCD 显示屏接线

Air780EHM/Air780EHV/Air780EGH 核心板 AirLCD_1000配件板
53/LCD_CLK SCLK/CLK
52/LCD_CS CS
49/LCD_RST RES/RST
50/LCD_SDA SDA/MOS
51/LCD_RS DC/RS
22/GPIO1 BLK
VBAT VCC
GND GND

五、准备软件环境

5.1 软件环境

在开始实践本示例之前,先筹备一下软件环境:

1、烧录工具:Luatools 下载调试工具

2、本demo开发测试时使用的固件为LuatOS-SoC_V2018_Air780EHV 1号固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;

注意:同时使用自定义字体和非自定义字体需要使用V2020版本及以上固件

3、脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/accessory_board/AirLCD_1000/lcd

4、lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件

准备好软件环境之后,接下来查看如何烧录项目文件到Air780EHV核心板,将本篇文章中演示使用的项目文件烧录到Air780EHV核心板中。

5.2 API 介绍

lcd 核心库:https://docs.openluat.com/osapi/core/lcd/

六、程序结构

AirLCD_1000/lcd/
│── font_drv
    │── customer_font_24.bin
    │── customer_font_drv.lua
    │── hzfont_drv.lua    
│── images   
    │── logo.jpg    
│── lcd_drv
    │── exlcd_drv.lua
    │── lcd_drv.lua     
│── tp_key_drv
    │── key_drv.lua 
│── ui
    │──  customer_font_page.lua 
    │──  home_page.lua
    │──  lcd_page.lua
    │──  ui_main.lua            
│── readme.md

6.1 文件说明

1、font_drv

  • customer_font_24.bin:自定义字体文件(和lua脚本文件一起烧录,会自动放置在/luadb/目录下)
  • 点击查看自定义字体生成和使用说明
  • customer_font_drv.lua:自定义外部字体驱动功能模块
  • hzfont_drv.lua:合宙软件矢量字库(开发中)

2、images

  • logo.jpg:演示图片文件(和lua脚本文件一起烧录,会自动放置在/luadb/目录下)

3、lcd_drv

  • lcd_drv.lua:LCD显示驱动模块,基于lcd核心库,lcd_drv和exlcd_drv二选一使用
  • exlcd_drv.lua:LCD显示驱动模块,基于exlcd扩展库,lcd_drv和exlcd_drv二选一使用

4、tp_key_drv

  • key_drv.lua:按键驱动模块,管理BOOT键和PWR键

5、ui

  • ui_main.lua:用户界面主控模块,管理页面切换和事件分发
  • home_page.lua:主页模块,提供应用入口和导航功能
  • lcd_page.lua:LCD图形绘制演示模块
  • customer_font_page.lua:自定义字体演示模块

七、代码详解

7.1 main.lua

主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。

7.2 customer_font_drv.lua

customer_font_drv是用户外部自定义外部点阵字体驱动功能模块,因为不需要进行初始化,所以本文件没有任何实质代码,只在此处描述在项目中如何使用。

--[[ 
说明:
customer_font_drv是用户外部自定义外部点阵字体驱动功能模块,因为不需要进行初始化,所以本文件没有任何实质代码,只在此处描述在项目中如何使用。
自定义字体制作说明可以参考lcd核心库自定义字体制作说明:https://docs.openluat.com/osapi/core/lcd/#_6
1、通过链接 https://gitee.com/Dozingfiretruck/u8g2_font_tool 下载字体文件制作工具
2、制作字体
   - 将.ttf和.otf格式字体加载到制作工具内
   - 选择自定义,输入需要生成的字体内容,调用自定义文字显示接口只能显示所输入的内容,其他内容需要切换支持的字体
   - 选择其他,则会按苏哦选编码格式生成对应的字体
   - 设置字体大小,生成合宙lcd核心库可加载的.bin格式的字体文件
3、使用lcd.setFontFile(font)接口设置
   - 其中font为字体文件路径
   - 若将生成的字体文件命名为customer_font_24.bin 并通过luatools工具同代码一起烧录到脚本分区,则设置接口为lcd.setFontFile("/luadb/customer_font_24.bin")
   - 若将生成的字体文件命名为customer_font_24.bin 并通过luatools工具同固件和代码一起烧录到文件系统,则设置接口为lcd.setFontFile("/customer_font_24.bin")
4、使用lcd.drawStr(x,y,str,fg_color)接口显示具体内容
]]

7.3 hzfont_drv.lua

合宙开发的一个内置矢量字体库,目前正在开发中

-- hzfont 是合宙开发的一个内置矢量字体库,目前正在开发中

7.4 exlcd_drv.lua

本模块为扩展LCD显示驱动功能模块,主要功能包括:

1、初始化AirLCD_1000扩展LCD显示;

2、配置显示缓冲区和自动刷新设置;

如果需要实现背光亮度调节,参考exlcd扩展库中的exlcd.set_bl(level)进行设置

local exlcd = require "exlcd"

local exlcd_drv = {}

--[[
初始化扩展LCD显示驱动

@api exlcd_drv.init()
@summary 配置并初始化AirLCD_1000扩展LCD显示
@return boolean 初始化成功返回true,失败返回false

@usage
-- 初始化扩展LCD显示
local result = exlcd_drv.init({})
if result then
    log.info("扩展LCD初始化成功")
else
    log.error("扩展LCD初始化失败")
end
]]

function exlcd_drv.init()
    local result = exlcd.init({lcd_model = "AirLCD_1000"})

    log.info("exlcd.init", result)

    if result then
        -- 显示设置
        lcd.setupBuff(nil, true)
        lcd.autoFlush(false)
    end

    return result
end

return exlcd_drv

7.5 lcd_drv.lua

本模块为LCD显示驱动功能模块,主要功能包括:

1、初始化AirLCD_1000 显示IC ST7796;

2、配置LCD显示参数和显示缓冲区;

3、支持多种屏幕方向和分辨率设置;

local lcd_drv = {}

--[[
初始化LCD显示驱动

@api lcd_drv.init()
@summary 配置并初始化ST7796 LCD控制器
@return boolean 初始化成功返回true,失败返回false

@usage
-- 初始化LCD显示
local result = lcd_drv.init()
if result then
    log.info("LCD初始化成功")
else
    log.error("LCD初始化失败")
end
]]

function lcd_drv.init()
    local result = lcd.init("st7796",
        {
            pin_rst = 36,                          -- 复位引脚
            pin_pwr = 1,                           -- 背光控制引脚GPIO的ID号
            port = lcd.HWID_0,                     -- 驱动端口
            -- pin_dc = 0xFF,          -- lcd数据/命令选择引脚GPIO ID号,使用lcd 专用 SPI 接口 lcd.HWID_0不需要填此参数,使用通用SPI接口需要赋值
            direction = 0,                         -- lcd屏幕方向 0:0° 1:90° 2:180° 3:270°,屏幕方向和分辨率保存一致
            w = 320,                               -- lcd 水平分辨率
            h = 480,                               -- lcd 竖直分辨率
            xoffset = 0,                           -- x偏移(不同屏幕ic 不同屏幕方向会有差异)
            yoffset = 0,                           -- y偏移(不同屏幕ic 不同屏幕方向会有差异)
            sleepcmd = 0X10,                       -- 睡眠命令,默认0X10
            wakecmd = 0X11,                        -- 唤醒命令,默认0X11
            -- bus_speed = 50*1000*1000,                            -- SPI总线速度,不填默认50M,若速率要求更高需要进行设置
            -- interface_mode = lcd.WIRE_4_BIT_8_INTERFACE_I,       -- lcd模式,默认lcd.WIRE_4_BIT_8_INTERFACE_I
            -- direction0 = {0x36,0x00},                            -- 0°方向的命令,(不同屏幕ic会有差异)
            -- direction90 = {0x36,0x60},                           -- 90°方向的命令,(不同屏幕ic会有差异)
            -- direction180 ={0x36,0xc0} ,                          -- 180°方向的命令,(不同屏幕ic会有差异)
            -- direction270 = {0x36,0xA0},                          -- 270°方向的命令,(不同屏幕ic会有差异)
            -- hbp = nil,                                           -- 水平后廊
            -- hspw = nil,                                          -- 水平同步脉冲宽度
            -- hfp = 0,                                             -- 水平前廊
            -- vbp = 0,                                             -- 垂直后廊
            -- vspw = 0,                                            -- 垂直同步脉冲宽度
            -- vfp = 0,                                             -- 垂直前廊
            -- initcmd = nil,                                       -- 自定义屏幕初始化命令表
            -- flush_rate = nil,                                    -- 刷新率
            -- spi_dev = nil,                                       -- spi设备,当port = "device"时有效,当port ≠ "device"时可不填或者填nil
            -- init_in_service = false,                             -- 允许初始化在lcd service里运行,在后台初始化LCD,默认是false,Air8000/G/W/T/A、Air780EHM/EGH/EHV 支持填true,可加快初始化速度,默认SPI总线速度80M
        })

    log.info("lcd.init", result)

    if result then
        -- 显示设置
        lcd.setupBuff(nil, true)
        lcd.autoFlush(false)
    end

    return result
end

return lcd_drv

7.6 key_drv.lua

本文件为按键驱动功能模块,核心业务逻辑为:

1、初始化BOOT键和PWR键的GPIO;

2、配置按键事件的中断处理函数;

3、实现按键防抖功能,防止误触发;

4、对外发布按键消息;

local key_drv = {}

-- 按键定义
local key_boot = 0           -- GPIO0按键(BOOT键)
local key_pwr = gpio.PWR_KEY -- 电源按键


-- 按键事件处理函数
local function handle_boot_key(val)
    -- print("key_boot", val)
    if val == 1 then
        sys.publish("KEY_EVENT", "boot_down")
    else
        sys.publish("KEY_EVENT", "boot_up")
    end
end

local function handle_pwr_key(val)
    -- print("key_pwr", val)
    if val == 1 then
        sys.publish("KEY_EVENT", "pwr_up")
    else
        sys.publish("KEY_EVENT", "pwr_down")
    end
end

--[[
初始化按键GPIO
配置BOOT键和PWR键的GPIO中断

@api key_drv.init()
@summary 配置BOOT键和PWR键的GPIO中断
@return bool 初始化只会返回true

@usage
local result = key_drv.init()
if result then
    log.info("按键驱动初始化成功")
end
]]
function key_drv.init()
    gpio.setup(key_boot, handle_boot_key, gpio.PULLDOWN, gpio.BOTH)
    gpio.debounce(key_boot, 50, 0)     -- 防抖,防止频繁触发

    gpio.setup(key_pwr, handle_pwr_key, gpio.PULLUP, gpio.BOTH)
    gpio.debounce(key_pwr, 50, 0)     -- 防抖,防止频繁触发

    log.info("key_drv", "按键初始化完成")
    return true
end

key_drv.init()
return key_drv

7.7 ui_main.lua

本模块为用户界面主控模块,主要功能包括:

1、管理页面切换和事件分发;

2、处理按键事件并调用对应页面的处理函数;

3、协调各页面之间的状态转移;

4、控制界面刷新频率;

-- 加载子页面
local home_page = require "home_page"
local lcd_page = require "lcd_page"
local customer_font_page = require "customer_font_page"

-- 当前页面状态
local current_page = "home"
local last_page = ""
frame_time = 20 * 1000

--[[
切换页面;
从当前页面切换到目标页面;

@api switch_page(new_page)
@summary 执行页面切换操作
@string new_page 目标页面名称
@valid_values "home", "lcd", "customer_font"
@return nil

@usage
-- 切换到主页
switch_page("home")

-- 切换到LCD演示页面
switch_page("lcd")
]]
local function switch_page(new_page)
    log.info("switch_page", "从", current_page, "切换到", new_page)

    -- 调用旧页面的退出函数(如果存在)
    if current_page == "home" and home_page.on_leave then
        home_page.on_leave()
    elseif current_page == "lcd" and lcd_page.on_leave then
        lcd_page.on_leave()
    elseif current_page == "customer_font" and customer_font_page.on_leave then
        customer_font_page.on_leave()
    end

    last_page = current_page
    current_page = new_page

    -- 调用新页面的进入函数(如果存在)
    if new_page == "home" and home_page.on_enter then
        home_page.on_enter()
    elseif new_page == "lcd" and lcd_page.on_enter then
        lcd_page.on_enter()
    elseif new_page == "customer_font" and customer_font_page.on_enter then
        customer_font_page.on_enter()
    end

    log.info("ui_main", "已切换到页面:", current_page)
end

--[[
处理按键事件;
根据按键类型和当前页面调用对应的处理函数;

@api handle_key_event(key_event)
@summary 处理按键事件并分发到对应页面
@string key_event 按键事件类型
@valid_values "boot_up", "pwr_up"
@return bool 事件处理成功返回true,否则返回false

@usage
-- 在ui_main任务中调用
local handled = handle_key_event("boot_up")
]]
local function handle_key_event(key_event)
    log.info("按键事件", "event:", key_event, "当前页面:", current_page)

    -- 只在按键释放时处理(防止重复触发)
    if key_event == "boot_up" then
        -- BOOT键:在主页作为方向键
        if current_page == "home" then
            -- 主页:向右移动光标
            return home_page.handle_key("next", switch_page)
        end
        -- 其他页面BOOT键无功能
        return false
    elseif key_event == "pwr_up" then
        -- PWR键:确认/返回功能
        if current_page == "home" then
            return home_page.handle_key("confirm", switch_page)
        elseif current_page == "lcd" then
            -- LCD页面:返回首页
            if lcd_page.handle_key then
                return lcd_page.handle_key("pwr_up", switch_page)
            end
        elseif current_page == "customer_font" then
            -- 自定义字体页面:返回首页
            if customer_font_page.handle_key then
                return customer_font_page.handle_key("pwr_up", switch_page)
            end
        end
    end

    return false
end

--[[
用户界面主任务;
初始化显示和按键驱动,启动UI主循环

@api ui_main()
@summary 初始化显示和按键驱动,启动UI主循环
@return nil

@usage
-- 在主程序中通过sys.taskInit调用
sys.taskInit(ui_main)
]]
local function ui_main()
    if not lcd_drv.init() then
        log.error("ui_main", "显示初始化失败")
        return
    end

    -- 初始化按键驱动
    if not key_drv.init() then
        log.error("ui_main", "按键驱动初始化失败")
        return
    end

    -- 默认使用系统自带的12号中文字体
    lcd.setFont(lcd.font_opposansm12_chinese)

    -- 调用主页的进入函数
    if home_page.on_enter then
        home_page.on_enter()
    end

    while true do
        -- 根据当前页面绘制内容
        if current_page == "home" then
            home_page.draw()
        elseif current_page == "lcd" then
            lcd_page.draw()
        elseif current_page == "customer_font" then
            customer_font_page.draw()
        end

        lcd.flush()

        -- 等待按键事件
        local result, key_event = sys.waitUntil("KEY_EVENT", frame_time)
        if result then
            handle_key_event(key_event)
        end
    end
end

sys.taskInit(ui_main)

7.8 home_page.lua

本模块为主页模块,主要功能包括:

1、提供应用入口和导航功能;

2、显示系统标题和操作提示;

3、管理三个功能按钮的选中状态;

4、处理主页面的按键事件;

local home_page = {}


-- 按钮区域定义
local buttons = {
    {name = "lcd", text = "lcd核心库演示", x1 = 10, y1 = 350, x2 = 150, y2 = 420, color = 0x001F},
    {name = "customer_font", text = "自定义字体", x1 = 170, y1 = 350, x2 = 310, y2 = 420, color = 0x07E0}
}

-- 当前选中项索引
local selected_index = 1

local title = "合宙lcd演示系统"
local content1 = "本页面使用的是系统内置的12号中文点阵字体"
local hint = "boot键:选择 pwr键:确认"

--[[
绘制光标指示
@local
@return nil
]]
local function draw_cursor()
    local btn = buttons[selected_index]

    -- 在选中按钮周围绘制矩形光标
    lcd.drawRectangle(btn.x1 - 2, btn.y1 - 2, btn.x2 + 2, btn.y2 + 2, 0x3186)  -- 蓝色外框
    lcd.drawRectangle(btn.x1 - 1, btn.y1 - 1, btn.x2 + 1, btn.y2 + 1, 0x0000)  -- 黑色内框
end

--[[
绘制主页界面;
绘制主页面所有UI元素,包括选中指示;

@api home_page.draw()
@summary 绘制主页面所有UI元素,包括选中指示
@return nil

@usage
-- 在UI主循环中调用
home_page.draw()
]]
function home_page.draw()
    lcd.clear()
    lcd.setColor(0xFFFF, 0x0000)
    lcd.setFont(lcd.font_opposansm12_chinese)

    -- 显示标题
    lcd.drawStr(106, 30, title, 0x0000)

    -- 显示说明文字
    lcd.drawStr(46, 48, content1, 0x0000)
    lcd.drawStr(86, 66, hint, 0x0000)

    -- 绘制所有按钮
    for i, btn in ipairs(buttons) do
        local color = btn.color
        if i == selected_index then
            -- 选中状态:颜色稍微变亮
            color = color + 0x0842
        end

        lcd.fill(btn.x1, btn.y1, btn.x2, btn.y2, color)

        -- 根据按钮调整文字位置
        if btn.name == "lcd" then
            lcd.drawStr(btn.x1 + 25, btn.y1 + 30, "lcd核心库演示", 0xFFFF)
        elseif btn.name == "customer_font" then
            lcd.drawStr(btn.x1 + 35, btn.y1 + 30, "自定义字体", 0xFFFF)
        end
    end

    -- 绘制光标指示
    draw_cursor()
end

--[[
处理主页按键事件;
根据按键类型执行相应的操作;

@api home_page.handle_key(key_type, switch_page)
@summary 处理主页按键事件
@string key_type 按键类型
@valid_values "confirm", "next", "prev", "back"
@function switch_page 页面切换回调函数
@return bool 事件处理成功返回true,否则返回false

@usage
-- 在UI主循环中调用
local handled = home_page.handle_key("next", switch_page)
]]
function home_page.handle_key(key_type, switch_page)
    log.info("home_page.handle_key", "key_type:", key_type, "selected_index:", selected_index)

    if key_type == "confirm" then
        -- 确认键:切换到选中的页面
        local btn = buttons[selected_index]
        switch_page(btn.name)
        return true
    elseif key_type == "right" or key_type == "next" then
        -- 向右/下一个
        selected_index = selected_index % #buttons + 1
        return true
    elseif key_type == "left" or key_type == "prev" then
        -- 向左/上一个
        selected_index = (selected_index - 2) % #buttons + 1
        return true
    elseif key_type == "back" then
        -- 返回键:可以执行其他操作或提示
        return false
    end
    return false
end

--[[
页面进入时重置选中状态;
重置选中状态为第一个按钮;

@api home_page.on_enter()
@summary 重置选中状态
@return nil

@usage
-- 在页面切换时调用
home_page.on_enter()
]]
function home_page.on_enter()
    selected_index = 1  -- 默认选中第一个
end

--[[
获取当前选中项信息;
用于调试或状态查询;

@api home_page.get_selected_info()
@summary 获取当前选中项信息
@return table 包含选中项信息的表
@field index number 当前选中项的索引
@field name string 当前选中项的名称
@field text string 当前选中项的显示文本

@usage
-- 获取当前选中项信息
local info = home_page.get_selected_info()
log.info("当前选中", info.name, info.text)
]]
function home_page.get_selected_info()
    local btn = buttons[selected_index]
    return {
        index = selected_index,
        name = btn.name,
        text = btn.text
    }
end

return home_page

7.9 lcd_page.lua

本模块为LCD图形绘制演示功能模块,主要功能包括:

1、展示LCD核心库的基本图形绘制功能;

2、演示点、线、矩形、圆形等基本图形绘制;

3、显示图片和二维码生成功能;

4、提供颜色示例展示;

local lcd_page = {}

-- 按钮区域定义
local back_button = { x1 = 10, y1 = 10, x2 = 80, y2 = 50 }

--[[
绘制LCD演示页面
绘制LCD演示页面的所有图形和UI元素

@api lcd_page.draw()
@summary 绘制LCD演示页面的所有图形和UI元素
@return nil

@usage
-- 在UI主循环中调用
lcd_page.draw()
]]
function lcd_page.draw()
    lcd.clear()
    lcd.setFont(lcd.font_opposansm12_chinese)

    -- 绘制返回按钮
    lcd.fill(back_button.x1, back_button.y1, back_button.x2, back_button.y2, 0xC618)
    lcd.setColor(0x07E0, 0x0000)
    lcd.drawStr(35, 35, "返回", 0x0000)
    -- 设置默认颜色
    lcd.setColor(0xFFFF, 0x0000)

    -- 显示标题
    lcd.drawStr(120, 33, "LCD核心库演示", 0x0000)
    lcd.drawLine(20, 55, 300, 55, 0x8410)

    -- === 第一区域:基本图形 ===
    lcd.drawStr(20, 75, "基本图形绘制:", 0x0000)

    -- 绘制点
    lcd.drawStr(30, 98, "点:", 0x0000)
    lcd.drawPoint(55, 98, 0xFCC0)
    lcd.drawPoint(65, 98, 0x07E0)
    lcd.drawPoint(75, 98, 0x001F)

    -- 绘制线
    lcd.drawStr(30, 125, "线:", 0x0000)
    lcd.drawLine(55, 113, 115, 113, 0xFCC0)
    lcd.drawLine(55, 118, 115, 123, 0x07E0)
    lcd.drawLine(55, 123, 115, 118, 0x001F)

    -- 绘制矩形(预留右侧空间)
    lcd.drawStr(30, 160, "矩形:", 0x0000)
    lcd.drawRectangle(65, 138, 105, 163, 0x7296)
    lcd.fill(120, 138, 160, 163, 0x07E0)

    -- 绘制圆(预留右侧空间)
    lcd.drawStr(30, 200, "圆形:", 0x0000)
    lcd.drawCircle(90, 193, 15, 0x001F)
    lcd.drawCircle(130, 193, 15, 0xFCC0)

    lcd.drawLine(170, 70, 170, 300, 0x8410) -- 垂直分隔线

    -- === 第二区域:图片和二维码 ===
    lcd.drawStr(180, 75, "图片/二维码:", 0x0000)

    -- 图片显示区域 (80x80)
    lcd.drawStr(180, 100, "LOGO:", 0x0000)
    lcd.drawRectangle(180, 110, 270, 200, 0x0000) 
    lcd.showImage(185, 115, "/luadb/logo.jpg")  

    -- 二维码区域 (80x80)
    lcd.drawStr(180, 215, "二维码:", 0x0000)
    lcd.drawRectangle(180, 225, 270, 308, 0x0000)
    lcd.drawQrcode(185, 226, "https://docs.openluat.com/air8000/", 80)

    lcd.drawLine(20, 325, 300, 325, 0x8410)

    -- === 第三区域:位图 ===
    lcd.drawLine(20, 235, 160, 235, 0x8410)

    -- 位图区域
    lcd.setFont(lcd.font_opposansm12_chinese)
    lcd.drawStr(20, 255, "位图示例:", 0x0000)

    -- 绘制位图
    local x_start = 30
    local y_start = 265
    lcd.drawXbm(x_start, y_start, 16, 16, string.char(
        0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x3F, 0x80, 0x00,
        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x7F, 0x00, 0x00))

    lcd.drawXbm(x_start + 20, y_start, 16, 16, string.char(
        0x00, 0x00, 0x80, 0x00, 0xC4, 0x7F, 0x28, 0x00, 0x10, 0x00, 0xD0, 0x3F, 0x42, 0x20, 0x44, 0x22,
        0x40, 0x24, 0xF0, 0xFF, 0x24, 0x20, 0x24, 0x22, 0x24, 0x20, 0xE2, 0x7F, 0x02, 0x20, 0x02, 0x1E))

    lcd.drawXbm(x_start, y_start + 20, 16, 16, string.char(
        0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x40, 0x02, 0x20, 0x04, 0x18, 0x18, 0xF4, 0x6F, 0x02, 0x00,
        0x00, 0x00, 0xF8, 0x1F, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0xF8, 0x1F, 0x08, 0x10))

    lcd.drawXbm(x_start + 20, y_start + 20, 16, 16, string.char(
        0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x7F, 0x02, 0x40, 0x02, 0x40, 0x00, 0x01, 0xFC, 0x3F,
        0x04, 0x21, 0x04, 0x21, 0xFC, 0x3F, 0x04, 0x21, 0x04, 0x21, 0x04, 0x21, 0xFC, 0x3F, 0x04, 0x20))

    -- === 第四区域:字体 ===
    lcd.drawStr(20, 345, "中英文字体示例:", 0x0000)

    -- 中文字体
    lcd.setFont(lcd.font_opposansm12_chinese)
    lcd.drawStr(20, 368, "中文字体ABC123", 0x0000)

    -- 英文字体
    local font_y = 388
    lcd.setFont(lcd.font_opposansm12)
    lcd.drawStr(20, font_y, "12px: ABCabc123", 0x0000)
    font_y = font_y + 18

    lcd.setFont(lcd.font_opposansm16)
    lcd.drawStr(20, font_y, "16px: ABCabc123", 0x0000)
    font_y = font_y + 22

    lcd.setFont(lcd.font_opposansm20)
    lcd.drawStr(20, font_y, "20px: ABCabc123", 0x0000)
    font_y = font_y + 26

    lcd.setFont(lcd.font_opposansm24)
    lcd.drawStr(20, font_y, "24px: ABCabc123", 0x0000)

    lcd.drawLine(20, 470, 300, 470, 0x8410)
end

--[[
处理按键事件;
根据按键类型执行相应的操作;

@api lcd_page.handle_key(key_type, switch_page)
@summary 处理LCD页面按键事件
@string key_type 按键类型
@valid_values "pwr_up"
@function switch_page 页面切换回调函数
@return bool 事件处理成功返回true,否则返回false

@usage
-- 在UI主循环中调用
local handled = lcd_page.handle_key("pwr_up", switch_page)
]]
function lcd_page.handle_key(key_type, switch_page)
    log.info("lcd_page.handle_key", "key_type:", key_type)

    if key_type == "pwr_up" then
        -- PWR键:返回首页
        switch_page("home")
        return true
    end
    -- BOOT键无功能
    return false
end

return lcd_page

7.10 customer_font_page.lua

本模块为自定义字体演示功能模块,主要功能包括:

1、展示外部自定义字体文件的加载和显示功能;

2、提供多颜色文字显示效果;

3、显示字体使用说明和接口信息;

local customer_font_page = {}

--[[
绘制自定义字体演示页面;
绘制自定义字体演示页面的所有UI元素和字体内容

@api customer_font_page.draw()
@summary 绘制自定义字体演示页面的所有UI元素和字体内容
@return nil

@usage
-- 在UI主循环中调用
customer_font_page.draw()
]]
function customer_font_page.draw()
    lcd.clear()
    lcd.setFont(lcd.font_opposansm12_chinese)

    -- 设置默认颜色
    lcd.setColor(0xFFFF, 0x0000)

    -- 显示标题(使用系统字体)
    lcd.drawStr(106, 20, "自定义点阵字体演示", 0x0000)

    -- 显示操作提示
    lcd.drawStr(20, 40, "按PWR键返回主页", 0x0000)

    -- 设置自定义字体文件
    lcd.setFontFile("/luadb/customer_font_24.bin")

    lcd.drawStr(112, 160, "上海合宙", 0xF800) -- 红色
    lcd.drawStr(120, 200, "LuatOS", 0x07E0) -- 绿色
    lcd.drawStr(100, 240, "演示demo", 0x001F) -- 蓝色

    -- 恢复系统字体显示说明
    lcd.setFont(lcd.font_opposansm12_chinese)
    lcd.setColor(0xFFFF, 0x0000)

    -- 显示说明信息
    lcd.drawStr(20, 320, "- 字体路径: /luadb/customer_font_24.bin", 0x0000)
    -- 显示使用说明
    lcd.drawStr(20, 340, "使用接口:", 0x0000)
    lcd.drawStr(20, 360, "lcd.setFontFile(字体路径)", 0x0000)
    lcd.drawStr(20, 380, "lcd.drawStr(x, y,文本)", 0x0000)

    -- 显示当前操作状态
    lcd.drawStr(20, 420, "当前页面: 自定义字体演示", 0x0000)
end

--[[
处理按键事件;
根据按键类型执行相应的操作;

@api customer_font_page.handle_key(key_type, switch_page)
@summary 处理自定义字体页面按键事件
@string key_type 按键类型
@valid_values "pwr_up"
@function switch_page 页面切换回调函数
@return bool 事件处理成功返回true,否则返回false

@usage
-- 在UI主循环中调用
local handled = customer_font_page.handle_key("pwr_up", switch_page)
]]
function customer_font_page.handle_key(key_type, switch_page)
    log.info("customer_font_page.handle_key", "key_type:", key_type)

    if key_type == "pwr_up" then
        -- PWR键:返回首页
        switch_page("home")
        return true
    end
    -- BOOT键无功能
    return false
end

--[[
页面离开时恢复系统字体;
恢复系统默认字体设置;

@api customer_font_page.on_leave()
@summary 恢复系统默认字体设置
@return nil

@usage
-- 在页面切换时调用
customer_font_page.on_leave()
]]
function customer_font_page.on_leave()
    -- 恢复使用12号中文字体
    lcd.setFont(lcd.font_opposansm12_chinese)
    log.info("customer_font_page", "已恢复系统字体")
end

return customer_font_page

八、显示效果展示

8.1 硬件准备

  1. 按照硬件接线表连接所有设备
  2. 确保电源连接正确,通过TYPE-C USB口供电
  3. 检查所有接线无误,避免短路

8.2 软件配置

main.lua中选择加载对应的驱动模块:

-- 加载显示屏驱动管理功能模块,有以下两种:
-- 1、使用lcd核心库驱动的lcd_drv.lua
-- 2、使用exlcd扩展库驱动的exlcd_drv.lua
-- 根据自己的需求,启用两者中的任何一种都可以
-- 也可以不启用任何一种,不使用显示屏功能
-- lcd_drv = require "lcd_drv"
lcd_drv = require "exlcd_drv"


-- 加载按键驱动管理功能模块
key_drv = require "key_drv"


-- 加载字库驱动管理功能模块,有以下两种:
-- 1、使用hzfont核心库驱动内核固件中支持的软件矢量字库的hzfont_drv.lua(正在开发中,后续补充)
-- 2、使用自定义字体
-- 根据自己的需求,启用两者中的任何几种都可以
-- 也可以不启用任何一种,只使用内核固件中自带的点阵字库
-- require "hzfont_drv"
-- 使用外部自定义字体不需要require "customer_font_drv",可以参照customer_font_drv.lua内的使用说明进行创建和加载字体文件


-- 加载输入法驱动管理功能模块(正在开发中,后续补充)


-- 加载lcd核心库实现的用户界面功能模块
-- 实现多页面切换、按键事件分发和界面渲染功能
-- 包含主页、lcd核心库功能演示页和自定义字体演示页
require "ui_main"

8.3 软件烧录

  1. 使用Luatools烧录最新内核固件
  2. 下载并烧录本项目所有脚本文件
  3. 将字体文件和图片文件随脚本文件一起烧录到脚本分区
  4. 烧录成功后设备自动重启后开始运行

8.4 功能测试

8.4.1 主页面操作

  1. 设备启动后显示主页面,包含三个功能按钮
  2. 查看系统功能概览信息
  3. 使用boot键切换选择,pwr键进入对应演示页面

8.4.2 LCD演示页面

  1. 查看基本图形绘制示例(点、线、矩形、圆形)
  2. 查看图片显示区域(显示logo图片)
  3. 查看二维码区域(合宙文档二维码)
  4. 查看位图和字体示例
  5. 按pwr键返回主页

8.4.3 自定义字体页面

  1. 查看外部字体文件显示效果
  2. 查看多颜色文字显示(红色、绿色、蓝色)
  3. 查看字体使用说明和接口信息
  4. 按pwr键返回主页

8.5 预期效果

  • 主页面:正常显示,使用boot键切换选项,pwr键确认
  • LCD演示页面:图形绘制清晰,图片和二维码显示正常,颜色示例完整,pwr键返回
  • 自定义字体页面:外部字体加载正确,多颜色文字显示正常,pwr键返回
  • 按键交互:所有按键操作响应及时准确,页面切换流畅

九、常见问题

  1. 显示异常:检查LCD接线是否正确,确认电源供电稳定
  2. 按键无响应:检查参数是否配置正确,确认按键驱动初始化成功
  3. 字体显示异常:确认字体文件路径正确
  4. 图片无法显示:确认图片文件已正确烧录到指定路径
  5. 系统卡顿:检查内存使用情况,适当调整刷新频率