杰理JL703N SSD1306 OLED(128x64) 点阵屏移植说明

JL703N SSD1306 OLED(128x64) 点阵屏移植说明

目标平台:JL703N / br27

目标SDK: JL703N_le_audio_2.0.0_patch_01_11

参考实现:demo_701_142_oled_pixscoll\sdk(JL701N/br28,OLED 可正常工作)

效果:SSD1306 128x64 正常点亮,SOUNDBOX 风格 UI 显示,中文字库正常,音乐模式歌名可显示。

遗留:PC 模式界面因资源未画全而不完整(见 §8)。


部分UI界面效果

一、背景:703 SDK 里并存两套互斥的 UI 框架

这是整个移植的核心。JL703N SDK 内同时保留了新旧两套 UI 框架,用 EXPORT_DOT_UI_ENABLE 二选一,

但原厂只做了源码层的开关,没有把库和头文件的切换做进构建系统,导致点阵屏那套没有编不进去。

点阵屏(OLED) 彩屏(默认)
静态库 ui_dot.a ui_draw.a res.a font.a ui_cpu.a ui_new.a ui_draw_new.a res_new.a font_new.a
头文件路径 interface/utils/ui interface/ui/jl_ui
框架代码 apps/common/ui/interface/*(软件 SPI 推屏) cpu/br27/ui_driver/*(IMD 硬件推屏)
屏驱注册宏 REGISTER_LCD_DEVICE() → 全局变量 lcd_drive REGISTER_LCD_DEVICE_NEW().lcd_device_info
屏驱文件 oled_spi_ssd1306_128x64.c lcd_spi_st7789v_240x240.c

两套框架的屏驱注册方式不兼容,且都会注册 lcd_interface.lcd_if_info 段,必须严格二选一


二、问题与处理过程

问题 1:编译报大量 undefined reference

现象

复制代码
undefined reference to `platform_get_file' / `ui_draw' / `ui_platform_init'
undefined reference to `ui_file_check_valid' / `ui_upgrade_file_check_valid'

根因

实际是:

复制代码
cpu/br27/ui_driver/interface/ui_platform.c:3271: error: use of undeclared identifier 'STRPIC_1'

该文件末尾的 "ui test demo" 段无条件引用了 STRPIC_1/PNG_PIC/TEXT_1 等控件 ID,

而这些 ID 只在 CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX 时定义。编译失败 → 没生成 .o → 链接时符号全缺。

处理:给该 demo 段加风格条件编译(见改动 9)。

教训:make -j 出现 undefined reference 时,先往前翻找真正的 error:,别被链接错误误导。


问题 2:ASSERT lcd_device_begin != lcd_device_end

现象

log打印出现:

复制代码
find logo st7789v
ASSERT-FAILD: lcd_device_begin != lcd_device_end don't find lcd device!

根因

屏驱注册表 .lcd_device_info 段为空:

  1. 编译进来的 3 个彩屏驱动各自被 TCFG_LCD_SPI_ST7789V_ENABLE 等宏包住,而这些宏均为 0 → 文件全空;
  2. SSD1306 屏驱属于点阵屏那套,而 EXPORT_DOT_UI_ENABLE 从未被定义过,整段不参与编译。

处理:切换到点阵屏框架(改动 1~5)。


问题 3:切换框架后 33 个编译错误

现象 :切到 apps/common/ui 后报缺头文件、函数参数个数不符、结构体字段不存在。

根因

新库的头文件 去编译老框架的代码 。这套代码配套的是 interface/utils/ui(老 UI 库),

include_dir.txt 里只挂了 interface/ui/jl_ui(新库)。

处理 :头文件路径和静态库一起切到老库(改动 1、2)。切换后编译错误 33 → 1


问题 4:链接缺 ui_page_* 等 13 个符号

现象

编译出现:

复制代码
undefined reference to `ui_page_init' / `ui_page_add' / `get_direction' / `g_cur_left' ...

根因

lcd_ui_api.c 里的卡片滑动翻页 功能依赖新库 ui_new.a 才有的接口,老库 ui_dot.a 不提供。

参考 SDK 里这段代码是包在 #if (CONFIG_UI_STYLE == STYLE_JL_WTACH_NEW) 内的,703N 版本把条件去掉了。

处理 :加 UI_CARD_SLIDE_ENABLE 开关(改动 7)。点阵屏无触摸屏,用不上该功能。


问题 5:ui_core_malloc ASSERT / open_resfile fail!

现象

log出现:

复制代码
open faild!
open_resfile fail!
ASSERT-FAILD: p != NULL ui_core_malloc   (ui_core_dot.c:127)

根因

ui_resources_manager.c:191 把资源路径硬编码RES_PATH"JL/JL.res"(即 flash/res/JL/JL.res),

download.bat 打包的是 JL_OLED 目录 → 烧进去是 flash/res/JL_OLED/JL.res,路径对不上。

资源打不开 → jlui_load_window() 读到垃圾 window.lenmalloc 失败 → ASSERT。

处理 :打包前先把选中屏型的资源同步到 JL 目录,统一打包 JL(改动 6)。


问题 6:UI 只有几个模式文字,没有完整界面

根因

703N 自带的 JL_OLED 资源是近乎空的占位包

文件 703N 原始 701 参考
JL.res(图片) 41708 30057
JL.str(文字) 28 24336
JL.sty(页面布局) 6392 41480
控件 ID 数 76 471

处理 :移植 701 的 128x64 UI 工程与资源,风格切到 STYLE_JL_SOUNDBOX(改动 3、10、11、12)。

移植前验证过可行性:703N 的 STYLE_SOUNDBOX 业务代码引用 208 个控件 ID,

其中 189 个(91%)在 701 资源表中已有 ,缺的 19 个里 18 个是 SPDIF(701 无此模式)、1 个是触摸 demo 用的 PNG_PIC

而这两部分对应的源文件本来就不参与编译(TCFG_APP_SPDIF_EN=0、触摸 demo 已排除)。


问题 7:打包报文件名超长

现象

复制代码
ERROR: The length(16) of the file name "JL.res.bak_empty" exceeds 15 characters.

根因 :备份文件放在了会被打包的资源目录里,xcopy *.* 把它一起复制进 JL/

处理 :备份移出资源目录;同步改为只复制 JL.res/JL.str/JL.sty 三个文件(改动 6)。

注意:资源目录内的文件名不得超过 15 字符,且不要放任何无关文件。


问题 8:歌曲名不显示(无任何报错)

现象 :日志证明链路完全正常,但屏上就是不显示歌名。

log打印:

复制代码
__FUNCTION__ =music_start type =show_lyric 0              ← 消息到达
>>>[ui test]:filename = 10kHz_sin_10min.wav, len = 19     ← 文件名取到
music start is_unicode = 1                                ← 走宽字符渲染
31 00 30 00 6B 00 48 00 7A 00 ...                         ← UTF-16LE 数据正确
(之后无任何输出,也无报错)

根因ui_synthesis_oled.c:772

c 复制代码
info = font_open(NULL, language);
ASSERT(info, "font_open fail!");                    // 未触发,所以日志毫无异常
if (info && (FT_ERROR_NONE == (info->sta & (~FT_ERROR_NOTABFILE | FT_ERROR_NOPIXFILE)))) {
    ... 真正画字 ...                                 // 被静默跳过
}

font/ 目录只有 F_UNIC.PIX缺配套的 .TAB 索引文件

font_open 返回非 NULL(不触发 ASSERT),但 info->staFT_ERROR_NOTABFILE 标志,

导致整个渲染分支被跳过 ------ 表现为"文字不显示且日志无任何报错"。

模式名等文字能显示,是因为它们走 JL.str 里的字符串图片,不经过字库。

处理 :补入 F_GB2312.PIX + F_GB2312.TAB(改动 14)。

日志中 language:1 对应 Chinese_Simplified(见 font/language_list.h),正好匹配 GB2312 字库。

字库文件必须 .PIX.TAB 成对存在,否则文字静默不渲染。


问题 9:PC模式界面左右各缺一块、电量图标无格数

现象:PC 模式首页左右两侧各缺一块内容,只有中间正常;电量图标不显示具体电量。两个 SDK 都有。

排查过程

第一层原因:703N 的 STYLE_SOUNDBOX 目录里没有 pc_action.c (701 的 STYLE_02 有)。

该文件负责 PC_VOL_LAYOUT 的"按音量键弹出、3 秒后自动收起":

c 复制代码
case UI_KEY_VOLUME_INC:
case UI_KEY_VOLUME_DEC:
    ui_show(PC_VOL_LAYOUT);                                   // 按键才显示
static void pc_vol_lay_timeout(void *p) {
    if (ui_get_disp_status_by_id(id) == TRUE) ui_hide(id);    // 3秒后收起
}

缺该文件时音量布局按资源默认状态常驻,压在界面上。移植后(见改动 13)该问题解决,但左右缺块依旧

第二层原因(根本原因):统计各页面控件数后真相明确 ------

页面 控件数 页面 控件数
PAGE_7 SYS 132 PAGE_10 REC 45
PAGE_4 MUSIC 95 PAGE_9 LINEIN 43
PAGE_3 CLOCK 46 PAGE_2 FM 26
PAGE_1 BT 45 PAGE_8 PC 7

ui_128_64_JL02 工程里 PAGE_8 只画了骨架PC_LAYER/PC_LAYOUT/PC_PIC/PC_BAT/PC_VOL_LAYOUT/PC_VOL_PIC/PC_VOL_NUM),

没有状态栏、EQ、菜单等其它页面都有的元素。左右两侧在资源里压根没有内容,代码补不出来

电量方面:pc_action.cbt_action.cbattery_onchange 代码逐字相同

(都是 ui_battery_set_level(battery, get_vbat_percent(), incharge) + 1 秒定时刷新),

所以代码无误,嫌疑同样在 PC_BAT 的资源配置(ui_battery 需绑定各电量档位图片)。

处理 :移植 pc_action.c(解决音量布局常驻);界面补全需用 UI 绘图工具改工程,见 §8 已知限制。

判断"是代码问题还是资源问题"的快捷方法:统计目标页面的控件数,与同类页面横向对比。

差一个数量级基本可断定是资源没画。


三、改动总览

3.1 修改/新增的代码文件(14 个)

编号与「§4 修改内容详解」一致,可直接对照查看改动细节。

# 文件 改动内容 分类
1 build/Makefile.mk UI 静态库切到点阵屏版本(含原本从未链接的 ui_cpu.a 构建
2 build/include_dir.txt UI 头文件路径 interface/ui/jl_uiinterface/utils/ui(原位替换) 构建
3 apps/soundbox/include/app_config.h 新增 USE_SSD1306_OLED 覆盖块 + EXPORT_DOT_UI_ENABLE 定义 构建
4 build/genFileList.c SSD1306 屏驱移出彩屏分支;OLED 下排除触摸 demo 构建
5 build/fileList.c 彩屏框架加 #ifndef EXPORT_DOT_UI_ENABLE 互斥保护(该文件实为死代码,仅为语义一致) 构建
6 cpu/br27/tools/download.c 打包前同步资源到 JL 目录,统一打包 JL 构建
7 apps/common/ui/lcd/lcd_ui_api.c 新增 UI_CARD_SLIDE_ENABLE 开关;平台数据补 .spi_cfg 源码
8 apps/common/ui/interface/ui_pushScreen_manager.c asm/spi.hspi.hspi_devhw_spi_dev 源码
8b apps/soundbox/device_config.c #if SUPPORT_SPI2#if SUPPORT_SPI2 && TCFG_HW_SPI2_ENABLE 源码
9 cpu/br27/ui_driver/interface/ui_platform.c 末尾 ui test demo 段加风格条件编译 源码
10 apps/soundbox/include/ui/style_jl02.h 控件 ID 表换成 701 的 471 个 ID(保留风格条件包裹) 源码
11 apps/soundbox/include/ui/ui_style.h ID_WINDOW_SPDIF/ID_WINDOW_SINKPAGE_11/12 不存在时降级为 (-1) 源码
12 apps/soundbox/include/ui/res_config.h 表盘功能按屏类型开关;补 #include "app_config.h" 源码
13 apps/soundbox/ui/lcd/STYLE_SOUNDBOX/pc_action.c 新增: 从701移植PC模式UI(音量布局弹出/收起、电量刷新) 源码
--- apps/soundbox/board/br27/sdk_config.h 在 JLStudio 工具端设置(屏型、SPI1、引脚),勿手改,见 §5 工具

3.2 替换的资源文件(6 个)

路径 原大小 新大小 说明
cpu/br27/tools/JL_OLED/JL.res 41708 30057 图片资源(来自 701)
cpu/br27/tools/JL_OLED/JL.str 28 24336 字符串图片,原为空壳
cpu/br27/tools/JL_OLED/JL.sty 6392 41480 页面布局,原为空壳
cpu/br27/tools/JL/JL.res 41708 30057 ↓ 以下 3 个由 download.bat 自动同步
cpu/br27/tools/JL/JL.str 28 24336 无需手动维护
cpu/br27/tools/JL/JL.sty 6392 41480 无需手动维护

3.3 新增的文件与文件夹(5 项)

类型 路径 大小 说明
文件 cpu/br27/tools/font/F_GB2312.PIX 261702 简体中文字库(对应 language=1
文件 cpu/br27/tools/font/F_GB2312.TAB 45008 字库索引表,缺它文字静默不渲染
文件夹 cpu/br27/tools/LCD_UI工程/ui_128_64_JL02/ --- 128x64 UI 绘图工程(含 project.bin/ename.h/工具脚本),从 701 复制
文件 apps/soundbox/ui/lcd/STYLE_SOUNDBOX/pc_action.c --- PC模式UI,从701的 STYLE_02 移植并适配703N接口
文件 doc_SSD1306_OLED移植说明.md --- 本文档

3.4 自动生成,无需手动维护

这些文件也会出现在 git status 里,但都是工具或构建产生的:

路径 来源
cpu/br27/tools/download.bat download.c 预处理生成
build/fileList.mkbuild/fileList.dumy genFileList.c / fileList.c 生成
cpu/br27/sdk.ld sdk_ld.c 生成
apps/soundbox/movable/section.txtsdk_used_list.used 由对应 .c 预处理生成
apps/soundbox/board/br27/sdk_config.cjlstream_node_cfg.h JLStudio 工具生成
cpu/br27/tools/*.bin *.elf *.map *.bc *.ufw 编译/打包产物

四、修改内容详解

构建配置

1. build/Makefile.mk --- UI 静态库切换到点阵屏版本

diff 复制代码
-	cpu/br27/liba/res_new.a \
-	cpu/br27/liba/ui_draw_new.a \
-	cpu/br27/liba/font_new.a \
-	cpu/br27/liba/ui_new.a \
+	cpu/br27/liba/res.a \
+	cpu/br27/liba/ui_draw.a \
+	cpu/br27/liba/font.a \
+	cpu/br27/liba/ui_dot.a \
+	cpu/br27/liba/ui_cpu.a \

注意 ui_cpu.a 是原 Makefile 从未链接过的,缺它会缺 imd_wait 等符号。

2. build/include_dir.txt --- UI 头文件路径切换(保持原有顺序位置,勿置顶)

diff 复制代码
--Iinterface/ui/jl_ui
--Iinterface/ui/jl_ui/ui/cpu/br27
+-Iinterface/utils/ui
+-Iinterface/utils/ui/ui/cpu/br27

必须替换在原位置。若置于文件开头,老库的 includes.h 会覆盖 interface/system/includes.h

导致 late_initcall 等宏失效,全工程报错。

3. apps/soundbox/include/app_config.h --- 屏配置覆盖 + 框架选择

c 复制代码
#define USE_SSD1306_OLED            1
#if USE_SSD1306_OLED
#undef  CONFIG_UI_STYLE
#define CONFIG_UI_STYLE             STYLE_JL_SOUNDBOX
#undef  TCFG_LCD_OLED_ENABLE
#define TCFG_LCD_OLED_ENABLE        1
#undef  TCFG_OLED_SPI_SSD1306_ENABLE
#define TCFG_OLED_SPI_SSD1306_ENABLE 1
#undef  TCFG_SPI_LCD_ENABLE
#define TCFG_SPI_LCD_ENABLE         0
#undef  TCFG_LCD_SPI_ST7789V_ENABLE
#define TCFG_LCD_SPI_ST7789V_ENABLE 0
#endif

#if TCFG_LCD_OLED_ENABLE
#define EXPORT_DOT_UI_ENABLE        1
#endif

不要直接改 sdk_config.h ------ 它由 JLStudio 工具从 src/UI配置.json 生成并双向同步,手改会被覆盖。

排查过程中就遇到工具把 OLED 配置覆写回彩屏、导致构建突然失败的情况。

EXPORT_DOT_UI_ENABLE#ifndef 判断,不用时必须整个不定义,不能定义为 0

4. build/genFileList.c --- SSD1306 屏驱移出彩屏分支 + 排除触摸 demo

c 复制代码
// 屏驱挂到 OLED 开关下,否则选 OLED 时屏驱不编译,链接缺 lcd_drive
#if TCFG_OLED_SPI_SSD1306_ENABLE
c_SRC_FILES += apps/common/ui/lcd_drive/lcd_spi/oled_spi_ssd1306_128x64.c
#endif

// 触摸 demo 引用的 PNG_PIC 不在点阵屏 UI 工程中,点阵屏无触摸屏
#if (!TCFG_LCD_OLED_ENABLE)
c_SRC_FILES += apps/soundbox/ui/lcd/STYLE_SOUNDBOX/ui_touch_demo.c
#endif

5. build/fileList.c --- 彩屏框架加互斥保护

c 复制代码
#ifndef EXPORT_DOT_UI_ENABLE
objs += $(ROOT)/cpu/br27/ui_driver/interface/ui_platform.o \
        $(ROOT)/cpu/br27/ui_driver/lcd_drive/lcd_drive.o \
        ...
#endif

注意fileList.c 实为死代码。顶层 Makefile:208 先用 genFileList.c 生成 fileList.mk

Makefile.mk:143 include 它取得 c_SRC_FILES(链接实际使用的是它);之后 Makefile.mk 的 pre_build

才用 fileList.c 覆盖该文件,对本次构建已无影响。真正生效的是 genFileList.c

这里改它只为保持两个文件语义一致,避免后人误读。

6. cpu/br27/tools/download.c --- 资源目录同步与打包路径对齐

bat 复制代码
if %LCD_SOURCE_ENABLE%A==2A (
    if exist JL_OLED\JL.res copy /Y JL_OLED\JL.res JL\ >nul
    if exist JL_OLED\JL.str copy /Y JL_OLED\JL.str JL\ >nul
    if exist JL_OLED\JL.sty copy /Y JL_OLED\JL.sty JL\ >nul
    set LCD_SOURCE_FILES=%LCD_SOURCE_FILES% font JL
)

彩屏分支同样处理。逐个文件复制而非通配符,避免把无关文件打包进去。

源码适配

7. apps/common/ui/lcd/lcd_ui_api.c --- 卡片滑动翻页开关

c 复制代码
#ifdef EXPORT_DOT_UI_ENABLE
#define UI_CARD_SLIDE_ENABLE    0
#else
#define UI_CARD_SLIDE_ENABLE    1
#endif

用它包住 g_cur_left/page_auto_scroll/ui_card_*/ui_page_* 相关代码段,

以及 3 处 #if 1 ui_card_ontouch(&t); #else ui_event_ontouch(&t); #endif 的分发开关。

8. apps/common/ui/interface/ui_pushScreen_manager.c --- 新旧 SDK 的 API 差异

diff 复制代码
-#include "asm/spi.h"
+#include "spi.h"     // 本SDK硬件SPI接口头位于 interface/driver/cpu/periph
-int __spi_dma_send(spi_dev spi, ...)
+int __spi_dma_send(hw_spi_dev spi, ...)

8b. apps/soundbox/device_config.c --- SPI2 配置的连带修复

diff 复制代码
-#if SUPPORT_SPI2
+#if SUPPORT_SPI2 && TCFG_HW_SPI2_ENABLE

开启 TCFG_HW_SPI1_ENABLEspix_p_data[] 才参与编译,其中的 SPI2 分支会引用未定义的

TCFG_HW_SPI2_PORT_CLK 等宏,需补上使能判断。

9. cpu/br27/ui_driver/interface/ui_platform.c --- demo 段风格隔离

把文件末尾 "ui test demo" 段(ui_test_cb/ui_test_demo/TEXT1_onchange/REGISTER_UI_EVENT_HANDLER(TEXT_1)

包进 #if (CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX),保留其外的 REGISTER_UI_STYLE

(该文件在 OLED 配置下已不参与编译,此修复是为彩屏配置保留正确性)

10. apps/soundbox/include/ui/style_jl02.h --- 控件 ID 表替换

用 701 的 style_jl02.h471 个控件 ID ,由 ui_128_64_JL02 工程导出)替换原有的表,

外层保留 #if (CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) 包裹。

必须保留风格条件,否则会与 style_soundbar.h 产生 880 个宏重定义警告

ui_style.h 会同时 include 两个头文件)。

11. apps/soundbox/include/ui/ui_style.h --- SPDIF/SINK 页面降级

c 复制代码
#ifdef PAGE_11
#define ID_WINDOW_SPDIF       PAGE_11
#else
#define ID_WINDOW_SPDIF       (-1)     // ui_128_64_JL02 工程只画到 PAGE_10
#endif

ID_WINDOW_SINK 同理。模式功能仍可用,只是没有对应 UI 页面。

12. apps/soundbox/include/ui/res_config.h --- 表盘功能按屏类型关闭

c 复制代码
#if TCFG_LCD_OLED_ENABLE
#define UI_WATCH_RES_ENABLE     0//表盘功能
#else
#define UI_WATCH_RES_ENABLE     1//表盘功能
#endif

并补 #include "app_config.h"

表盘功能(watch1~5 多表盘 + 表盘升级)只适用于彩屏手表产品,点阵屏开启会去加载不存在的 watch 资源,

并引用已废弃的 VM_WATCH_SELECT 等接口。

注意FONT_PATH 等路径定义要保持在 #if (TCFG_UI_ENABLE) 分支内不变。

若整体切到简版分支,FONT_PATH 会丢掉 font/ 子目录,导致字库也找不到。

13. apps/soundbox/ui/lcd/STYLE_SOUNDBOX/pc_action.c (新增)--- PC模式UI

从 701 的 STYLE_02/pc_action.c 移植,负责 PC 页面的音量布局弹出/收起、电量定时刷新、按键处理。

移植时需适配 701→703N 的三处接口差异:

项目 701 703N
按键常量 KEY_MENU/KEY_OK/KEY_UP... UI_KEY_* 前缀(14 处)
按键动作 app_task_put_key_msg(KEY_MUSIC_PP, 0) app_send_message(APP_MSG_MUSIC_PP, 0)(5 处)
关机 power_off_deal(NULL, e->value - KEY_POWER_START) power_off_deal(APP_MSG_KEY_POWER_OFF) 单参数

老的按键消息枚举在 703N 的 key_event_deal.h:7 里整个被 #if 0 禁用,必须换成 APP_MSG_*

PC 模式的按键消息表 mode/pc/pc_key_msg_table.c 用的正是这套,语义一致。

另需补 #include "app_msg.h""idle.h",并把编译条件加上模式使能:

c 复制代码
#if (TCFG_UI_ENABLE && (CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) && TCFG_PC_ENABLE)

资源与字库

14. cpu/br27/tools/font/ --- 补入简体中文字库

复制代码
+ F_GB2312.PIX   261702    (简体中文字库,对应 language=1)
+ F_GB2312.TAB    45008    (索引表,缺它文字静默不渲染)

15. cpu/br27/tools/JL_OLED/JL/ --- 替换为 701 的完整 128x64 资源

复制代码
JL.res  41708 → 30057
JL.str     28 → 24336
JL.sty   6392 → 41480

16. cpu/br27/tools/LCD_UI工程/ui_128_64_JL02/ (新增目录)

从 701 复制的 128x64 UI 绘图工程,含 project.binename.himagelist.txt

及绘图/资源生成工具启动脚本,后续可直接用它调整界面。


五、板级硬件配置(sdk_config.h,工具端设置)

c 复制代码
TCFG_HW_SPI1_ENABLE        1
TCFG_HW_SPI1_PORT_CLK      IO_PORTA_07    // → OLED D0/SCL
TCFG_HW_SPI1_PORT_DO       IO_PORTA_08    // → OLED D1/SDA
TCFG_HW_SPI1_BAUD          24000000

TCFG_TFT_LCD_DEV_SPI_HW_NUM 1             // 即 HW_SPI1
TCFG_LCD_PIN_RESET         IO_PORTA_01    // RES
TCFG_LCD_PIN_CS            IO_PORTA_02    // CS
TCFG_LCD_PIN_DC            IO_PORTA_04    // DC

lcd_ui_api.c 的平台数据里 .spi_cfg = TCFG_TFT_LCD_DEV_SPI_HW_NUM


六、编译与烧录

bash 复制代码
make -j20          # 期望:0 error / 0 undefined reference / 0 macro redefined

烧录直接运行 cpu/br27/tools/download.bat,它会自动把 JL_OLED 同步到 JL 再打包。

验证启动日志的关键行

复制代码
spi pin rest:1, cs:2, rs:4, spi:1      ← 引脚与 SPI 口正确
spi open succ                           ← SPI1 打开成功
ui_platform_init :: [0,0,128,64]        ← OLED 分辨率正确
open success: 0x419a4c                  ← 资源文件打开成功(不是 open faild!)
dc->width : 128, dc->lines : 64
dc->data_format: 4                      ← 4 = DC_DATA_FORMAT_MONO 单色

页面对应关系ui_style.h,SOUNDBOX 风格)

页面 用途 页面 用途
PAGE_0 主页 PAGE_6 关机/待机
PAGE_1 蓝牙 PAGE_7 系统设置
PAGE_2 FM PAGE_8 PC
PAGE_3 时钟 PAGE_9 LINEIN
PAGE_4 音乐 PAGE_10 录音
PAGE_5 开机 --- ---

七、注意事项

  1. sdk_config.h 不要手改 ------ JLStudio 工具会覆盖。配置改动统一写在 app_config.h#undef + #define
  2. 两套 UI 框架必须二选一 ------ 同时链接会导致 lcd_get_hdl() 取到哪一套不确定。
  3. build/fileList.c 是死代码 ------ 改文件列表请改 build/genFileList.c
  4. 字库 .PIX/.TAB 必须成对 ------ 缺 .TAB 时文字静默不渲染且无任何报错。
  5. 资源目录保持干净 ------ 文件名 ≤15 字符,不要放备份等无关文件,否则打包报错。
  6. 改 UI 界面 ------ 用 LCD_UI工程/ui_128_64_JL02/模式界面/ 下的工具,导出后需同步更新
    style_jl02.h 的控件 ID 表(工程导出的 ename.h,记得保留风格条件包裹)。
  7. font.a 的调试打印 ------ 运行时会持续打印 language_id == 1 / comming in Chinese_Simplified
    这是库内部裸 log_print(无 TAG 开关),属正常现象,量产时关 TCFG_DEBUG_UART_ENABLE 即可。

八、已知限制

  • PC 模式界面不完整ui_128_64_JL02 工程里 PAGE_8 只有 7 个控件(同类的 LINEIN 页有 43 个),
    左右两侧无内容、电量图标无格数,属资源未画全,代码无法弥补。补全方法:

    复制代码
    SDK/cpu/br27/tools/LCD_UI工程/ui_128_64_JL02/模式界面/
        step1-打开UI绘图工具.bat      ← 打开 PAGE_8,参考 PAGE_9(LINEIN) 布局补画
        step2-打开UI资源生成工具.bat  ← 导出新的 JL.res/JL.str/JL.sty
        project/ename.h               ← 导出后控件ID表会更新

    导出后把三个资源文件放回 cpu/br27/tools/JL_OLED/,用新 ename.h 更新 style_jl02.h
    (保留外层 #if (CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) 包裹);新增控件若需代码驱动,
    再往 pc_action.c 里加对应的 REGISTER_UI_EVENT_HANDLER

  • SPDIF / SINK 模式无 UI 页面ui_128_64_JL02 工程只画到 PAGE_10,二者的 ID_WINDOW_* 已降级为 (-1)
    需要时用 UI 绘图工具补页面,并同步更新 style_jl02.h

  • 卡片滑动翻页功能不可用 :老 UI 库 ui_dot.a 不提供 ui_page_* 接口,点阵屏无触摸屏,不影响使用。

  • 表盘功能不可用 :点阵屏已关闭 UI_WATCH_RES_ENABLE


九、移植到其它 SDK 版本

JL703N_le_audio_2.0.0_patch_01_03_offline 为例(已完成并编译通过)。

不同 SDK 版本的构建系统可能完全不同,移植点要跟着变。

9.1 先确认构建系统类型

本 SDK offline 版
源文件列表 build/genFileList.c 预处理生成,支持 #if 条件 硬编码在顶层 Makefilec_SRC_FILESmake 语法无法条件编译
UI 库 / include 路径 build/Makefile.mkbuild/include_dir.txt 都在顶层 Makefile
build/fileList.mk 实际生效 没被 include,是死文件

判断方法:grep -n "^include\|c_SRC_FILES" Makefile,看列表从哪来。

9.2 offline 版的移植要点

顶层 Makefile 三处

  1. include 路径 -Iinterface/ui/jl_ui-Iinterface/utils/ui(连同 /ui/cpu/br27
  2. UI 库 → res.a ui_draw.a font.a ui_dot.a ui_cpu.a
  3. c_SRC_FILES:加入点阵屏框架 7 个文件 + pc_action.c删除彩屏 IMD 框架 5 个文件

为什么彩屏框架必须从列表删除,不能靠 C 宏

c 复制代码
#include "asm/imb.h"          // ← 第11行,属新版UI库
...
#if (...) && !defined(EXPORT_DOT_UI_ENABLE)   // ← 第19行,太晚了

#include 在条件之前就被处理,切到老库后直接 fatal error: 'asm/imb.h' file not found

C 宏只能挡住代码体,挡不住 #include

编辑 c_SRC_FILES 的坑 :不要在列表中间插空行或注释,会打断续行符 \

导致后面以 Tab 开头的行被当成 recipe,报 recipe commences before first target

说明文字要写在 c_SRC_FILES := \ 之前。

靠 C 宏排除的文件(Makefile 无法条件编译,只能改源码条件)

文件 原条件 改为
spdif_action.c #if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) 追加 && TCFG_APP_SPDIF_EN
sink_action.c 同上 追加 && TCFG_LOCAL_TWS_ENABLE
ui_touch_demo.c 同上 追加 && !TCFG_LCD_OLED_ENABLE

这三个文件原本只判断 UI 风格,切到 SOUNDBOX 后会被编译,但它们引用的

SPDIF_*/SINK_*/PNG_PIC 控件不在 128x64 工程里。改完后 .o 为空文件。

9.3 可直接复制的文件

两版内容一致,可直接覆盖:

res_config.hui_style.hstyle_jl02.hlcd_ui_api.cui_pushScreen_manager.c

ui_platform.cpc_action.c,以及资源(JL_OLED/*)、字库(font/F_GB2312.*)、UI工程目录。

不能直接覆盖 的:app_config.h(两版有 41 行配置差异,需插入式修改)。

可能不用改 的:device_config.c ------ patch 版官方已修好 #if TCFG_HW_SPI2_ENABLE && SUPPORT_SPI2

9.4 板级差异要单独核对

offline 版的屏挂在 SPI2 而非 SPI1:

本 SDK offline 版
TCFG_TFT_LCD_DEV_SPI_HW_NUM 1 (HW_SPI1) 2 (HW_SPI2)
屏 CLK / DO SPI1 = PA07 / PA08 SPI2 = PA07 / PA08(物理引脚相同)
SPI1 用途 其它外设(PB14/PB13/PB12)

物理接线一样,只是挂在不同 SPI 控制器上。因此 app_config.h 的覆盖块里不要 强制

TCFG_HW_SPI1_ENABLE,屏用哪个口应由工具端 TCFG_TFT_LCD_DEV_SPI_HW_NUM 决定,

只需保证对应的 TCFG_HW_SPIx_ENABLE 为 1。移植到新板子时务必先核对这一项。

相关推荐
wabs6662 小时前
关于图论【最短路径之Bellman_ford 算法(单源有限最短路)|卡码网96.城市间货物运输III的思考】
数据结构·算法·图论·卡码网·bellman_ford·单源有限最短路
芯岭技术郦4 小时前
OM6625A芯片 Timer 定时器计数模式使用说明
stm32·单片机·嵌入式硬件
lsylalalala4 小时前
常见的排序算法1
数据结构·算法·排序算法
想吃火锅10055 小时前
【leetcode】54. 螺旋矩阵
算法·leetcode·矩阵
想吃火锅10055 小时前
【leetcode】300. 最长递增子序列
算法·leetcode·职场和发展
imaol15 小时前
数据结构---队列
java·数据结构·算法
数模竞赛Paid answer5 小时前
2026年电工杯数学建模A题绿电直连型电氢氨园区优化运行求解全过程论文及程序
算法·数学建模·电工杯
疯狂打码的少年5 小时前
【数据结构】串的模式匹配:KMP算法(重点)
数据结构·笔记·算法
Dr.kangder6 小时前
嵌入式面试总结(八)——大小端
嵌入式硬件·面试·职场和发展·架构·嵌入式