KDocs 研发资料库
  • 音频技术应用文档入口汇总
  • 杰理WINDOWS环境安装及其他事项
  • LINUX安装和编译
  • Linux环境编译SDK教程(ubuntu18.04)
  • 音频类补丁汇总表
  • 认证资料获取汇总(最新资料后台会更新)
  • 《Hi-Res申请指南v1.0》
  • FreeRTOS 开源协议版本
  • uCOS 开源协议版本信息
  • 各个模块关键资料汇总
  • 软件调试方法
  • Makefile编译
  • 提bug的规范
  • 常规设备使用指导
  • 对外特别发布开发注意点信息汇总
  • AD697X软件问题整理
  • AC700N软件问题整理
  • AC701X耳机软件问题整理
  • 951&961软件问题整理
  • AC104X软件问题整理
  • AC128N问题整理文档
  • 可视化工具调试问题整理
  • 耳机资料汇总
  • AC704N、 AC705N相关应用
  • AC695N&AC696N&AC608N音箱问题整理
  • JL701N音箱问题整理
  • AC692X软件问题整理
  • AC706N音箱问题整理
  • JL701N音箱问题整理(可视化工具SDK)
  • JL703N音箱问题整理
  • JL709N(JL689N)音箱问题整理
  • JL7094系列-入门到进阶开发指导
  • AC210N音箱问题整理
  • 无线麦系列版本支持指南
  • AW32N无线麦问题整理
  • lAD697X&JL701X 无线麦软件共性问题整理
  • AC706N无线麦问题整理
  • AW36N无线麦问题整理
  • AC710X无线麦问题整理
  • 唤醒源获取及唤醒IO设置
  • 电源
  • LVD
  • 长按复位配置方法
  • 低功耗应用
  • TIMER
  • UART
  • SPI
  • 内部FLASH空间添加用户自定义区域
  • IIC
  • GPIO
  • MCPWM
  • SD&U盘
  • 时钟&晶振
  • GPCNT
  • IO口crossbar映射功能
  • 文件系统使用总结
  • 复用应用
  • LINEIN_AUX相关应用
  • IIS音频接口应用
  • SPDIF模式相关(HDMI_ARC、光纤、同轴)
  • PDM LINK
  • 外设相关应用
  • 蓝牙相关
  • 杰理蓝牙距离调试文档
  • TWS耳机配对方式使用及生产把控指南
  • GFP谷歌快连及其认证流程指引
  • 蓝牙发射器(bt_emitter)相关
  • BLE应用
  • 关于提升BLE传输速率说明
  • BLE测试数据
  • MUSIC 模式相关应用
  • MIDI音乐实现
  • PC相关应用
  • FM相关应用
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20250107
  • fm应用详细设计说明书
  • 杰理FM硬件指南-20230315
  • ADC模块
  • AUDIO相关应用
  • 新Tools的音效调试使用
  • 混响应用使用说明
  • 音效调式
  • 音箱耳机低音小音量增强实现方法
  • DAC输出功率调试
  • DAC性能测试指南
  • 针对各类底噪、电流声分析流程
  • 录音相关应用
  • OPUS编解码相关
  • RTC相关应用
  • 升级相关
  • UI相关应用
  • 通话调试流程指南
  • 通话相关应用
  • 省电容mic使用手册
  • 如何测试验证手表通话系统的语音失真 V1.0
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 通话调试问题确定步骤
  • 内置触摸调试指南
  • 低功耗内置触摸介绍V2.2
  • 触摸相关文档
  • AC697X、AC698X内置触摸调试及整改方法V1.0
  • 产测相关应用
  • AC63X BLE DUT测试介绍
  • 兆华序列使用简易说明
  • JL_1T2蓝牙测试盒音频文件更换说明
  • ENC相关应用入口汇总
  • ANC相关应用入口汇总
  • JL DMS通话调试手册-V3.9.4
  • ANC-ENC结构设计要点-20240407
  • 半入耳式ANC耳机器件选型与结构设计指南V1.0
  • JL 耳道自适应调试指南
  • ANC相关问题处理
  • ANC调试文档
  • 评估蓝牙耳机通话上行降噪性能的方法 V1.0 (2)
  • FCC 或者 BQB 认证相关应用
  • BQB profile 测试中常遇到的问题点汇总
  • 蓝牙参数整理20210811
  • 杰理科技认证问题参考
  • 无线音频产品开发指南
  • 无线麦系列从入门到进阶开发指导
  • 量产烧录相关说明
  • 一拖八烧录器远程过程调用说明
  • 量产相关建议
  • EffectTool(eq)调试工具说明文档
  • AC897AD697系列的EQ调试方法-V3
  • 杰理调音指南-20220622
  • 音效模块总结
  • 简要调音步骤指引(可视化)
  • 耳机充电与通信调试指南
  • 充电仓硬件调试指南
  • 充电仓软件问题整理
  • AC951常用说明
  • AC951_AC961_开发板使用说明V1.0
  • 彩屏仓AC982 入门指导及FAQ
  • 蓝牙音频APP相关应用
  • 手机APP的简介和开发流程
  • 蓝牙音频系列-硬件设计指南
  • 静电测试及整改方法-20220706
  • TWS耳机底噪整改指南V1.2
  • 杰理蓝牙距离调试文档
  • 蓝牙RF硬件设计与调试V1.1-20250219
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20241228
  • 音效调试指南
  • 无线话筒K歌音箱标准开发流程
  • 杰理科技 700N TWS耳机产品标准-202303
  • 杰理科技 701N 广播产品标准-202303
  • JL-HAT ANC高效产测自适应
  • 无线话筒测试板使用介绍
  • 一拖八频偏校准使用说明
  • 领夹麦产测工具使用介绍
  • Dongle量产测试说明
  • Dongle+Tws或头戴式 SDK通过工具绑定配对功能说明文档
  • 双麦ENC产测宏配置验证方法 V1.0
  • JL耳机方案麦克风声学测试指令_V1.0
  • JL耳机方案麦克风声学测试指令_V2.0
  • JL_ENC自动测试命令_V0.0.1
  • JL蓝牙测试盒用例说明
  • LDAC自测环境搭建_ubuntu
  • 延迟小板使用手册
  • 杰理库文件的制作及添加实现过程
  • 关于 AC635N&AC636N系列免晶振兼容性补丁 说明
  • 关于 AC63系列VM兼容性修复补丁_20250224 说明
  • 关于 AC632N &AE632N_ 蓝牙& 低功耗兼容性修复补丁 说明
  • AD698N和AC638N电压优化补丁V3说明
  • 关于 AC635N&AC636N漏电和E&G版兼容联合补丁 说明
  • AD698N和AC638N电压优化补丁V2说明
  • 702相关应用
  • 2024-4-30 发布歌词显示SDK开发注意事项
  • BQB RF & FCC 认证测试固件问题汇总及源码
  • BQB profile 测试中常遇到的问题点汇总
  • 进dut测试模式方法及固件
  • 704-频偏修改bin文件合集
  • 701手表BQB PROFILE认证注意事项
  • 认证的干扰规避整改
  • 海外CRA认证报告生成说明
  • JL700N可视化工具问题处理文档
  • JL701X可视化工具问题处理文档
  • JL701N_earphone_release_v1.6.0_ANC 低功耗问题补丁
  • JL708X可视化工具问题处理文档
  • JL709N可视化工具问题处理文档
  • JLstudio可视化工具使用说明
  • 一拖二-串口_蓝牙_app在线EQ、通话参数及调试方式和内置触摸调试
  • 可视化JL701M_DONGLE_SDK添加MIC为发射源
  • 可视化JL701M_DONGLE_SDK添加按键切换usb audio与MIC发射源
  • JL701M_DONGLE_SDK_1.0.0_dongle输入linein输出dac
  • 701可视化_a2dp_to_le_demo说明
  • 耳机系列demo汇总
  • JL7018F&JL7006F_7003F AUX IIS
  • 一键连接应用
  • 普通SDK动态开关一拖二功能
  • 蓝牙分析仪(EllisysBluetoothAnalyzer)抓包例程
  • TWS配对常见应用
  • APP自定义按键的demo
  • AC700N 播歌双EQ DEMO示例及说明
  • AC698V164 MIC与蓝牙音乐共同输出DAC demo
  • 添加第三方算法以及多算法授权流程
  • 空间音频配置方法
  • 普通高低电平TWS耳机控制通讯
  • 入耳检测状态更新demo解析
  • 资源优化(非可视化的SDK)
  • 资源优化(可视化SDK)
  • 翻译耳机、语音识别应用demo
  • 耳机抗干扰问题排查和优化
  • AC698D2 抗干扰优化
  • AC696X软件问题整理
  • AC695X软件问题整理
  • AC695X软件问题整理_1722249702
  • AC608X软件问题整理
  • JL701N_2T1_DUPLEX 应用软件问题汇总
  • le_audio_1.0.0_patch05 以及之前的版本IRkey 功能异常修改
  • AC706N-le_audio-200SDK有线_无线麦录音demo
  • jl701n_le_audio_v200patch02 IO串口升级修改串口单次发送字节长度的修改办法
  • 703创建IIS 输入dac输出音频流demo
  • 703将媒体流音频同时上传PC_mic录音demo实现
  • 703四路IIS输入输出demo
  • 底噪调试
  • AW328A烧录说明
  • 文档合集
  • AC706N_wireless_mic_release_PATCH_20240712 补丁 说明
  • AC706N_wireless_mic_release_PATCH_20240726 补丁 说明
  • AC706N_wireless_mic_release_V1.0.0、1.0.1、1.0.2 补丁 说明
  • AC706N_wireless_mic_release_V1.1.2 中的2T1应用 RX端不绑定配对,TX端实现绑定配对的修改方法
  • 各系列省晶振实现方法
  • iis tx rx说明文档
  • spdif信号
  • 蓝牙电话本
  • 安卓手机同步时间补丁
  • CDC配置
  • PC模式下增加Teams唤起功能
  • 杰理HDMIARC开发实现过程
  • AC701N patch06之前的版本用第三方算法节点实现新版本的pcm delay节点功能
  • (K歌音箱)各SDK音效配置相关说明
  • 长文件录音
  • 点阵屏歌词字库相关(蓝牙歌词,普通歌词)
  • 字模提取工具说明
  • 音箱可视化彩屏-入门到进阶开发指导
  • 彩屏LVGL UI设计及工具使用
  • 使用内部UI框架进行UI调试的系列步骤
  • AD101C使用强制升级工具spi 烧录不了问题处理(测试版本)
  • AD161扩展灯板说明文档
  • 歌词显示器开发注意项
  • 使用硬件数字增益控制通话下行音量(可视化)
  • 杰理小牛产测资料
  • ENC配置说明
  • 通话调试流程指引
  • ANC相关功能demo
  • 无线麦硬件资料汇总
  • 无线麦相关应用
  • 无线麦复杂功能补丁包汇总
  • 无线话筒形态SDK程序&开发经验&问题点分享
  • 双模式结合应用问题汇总
  • 无线麦距离优化案例
  • 无线麦系列中的双工形态(duplex)演变开发对讲机方案开发资料
  • 音箱入门到进阶指导文档(编写中)
  • 蓝牙耳机品控和生产技巧
  • 982过_欠压标志获取异常
  • 如何获取最新涂鸦SDK及库文件
  • 无线话筒K歌音响-调音标准流程
  • 无线话筒产测流程

彩屏LVGL UI设计及工具使用

📎 原始文档:https://www.kdocs.cn/l/cu689yidv5lJ 彩屏LVGL UI设计及工具使用

💡资料链接:

  1. cmake(用于makefile的构建,目前使用的是3.26版本,建议安装在c盘)
  2. mingw(cmake需要依赖于mingw,目前使用的是8.10版本,建议安装在c盘) 👉cmake&mingw安装教程.otl👈
  3. LVGL设计辅助(提供可视化图形界面设计):
    • Squareline Studio
    • Gui Guider
  4. LVGL参考文档:
    1. https://docs.lvgl.io/8.3/index.html
    2. http://lvgl.100ask.net/7.11/
    3. https://lvgl.100ask.net/8.2/index.html
    4. https://deepinout.com/lvgl-tutorials/lvgl-getting-started/lvgl-intro.html
    5. LVGL源码中docs文件夹,可见于SDK的code\sdk\lv_charging_case\lv_frame\lvgl\docs路径
  5. LVGL工具 图片转换工具:
    1. https://lvgl.io/tools/imageconverter
    2. https://gitee.com/gzmarkz/Lvgl_image_convert_tool 字库转换工具:
    3. https://lvgl.io/tools/fontconverter
    4. https://www.armbbs.cn/forum.php?mod=viewthread&tid=99387
  6. vscode(用于代码编辑与编译)

📌简介:

彩屏SDK已移植官方LVGL,当前使用的LVGL版本是8.3.5,并且接入杰理imb 2D加速模块,用户可以参考相关说明文档(链接可见于文档顶部),使用LVGL进行UI设计开发,也可以使用上位机进行辅助开发,但需要注意上位机提及的相关条款。需要注意的是,LVGL使用到的资源文件格式与imb能识别的格式有所差别,因此SDK中提供资源打包工具,用于图片资源的格式转换与压缩。

⭐整体开发流程:

  1. 移植屏驱:先让屏幕亮起来,保证屏幕能正常显示
  2. 移植tp驱动:确保tp报点正常,LVGL的触摸能正常触发
  3. LVGL应用层逻辑开发:构建UI的布局,添加UI的事件处理
  4. 蓝牙通讯调试:UI交互与具体功能的结合

🤖UI开发流程:

image

  1. SDK重要文件说明
  2. LVGL相关文件路径说明 image

与LVGL相关模块全部放置于lv_charging_case路径下,其中:
GPU2D:LVGL接入imb 2D加速模块
lv_frame:LVGL源码、UI设计的应用层文件等
adapter:中间适配层,用于存放蓝牙、UI线程间交互的接口
custom:用于存放用户UI设计自定义代码
generated:用于存放用户UI设计逻辑相关代码
UI:用于存放用户UI设计逻辑相关代码
import:用于存放LVGL中使用到的图片资源
❗(以上4个路径设置仅作参考,不做硬性要求,用户可以根据自身需求来修改目录结构)
lvgl:用于存放LVGL源码
jlres:用于存放资源索引文件
porting:用于存放LVGL驱动层文件,包括显示,输入设备和文件系统,一般改动较少
res-pack-tools:资源打包工具

工具脚本:
makefile_clear.bat:用于删除过程文件
makefile_maker.bat:用于makefile文件的构建(该脚本依赖于cmake,其中cmake下载链接可见于文档顶部)

  1. SDK代码编译 ├─sdk │
    ├─lv_charging_case │ │
    │ ├─GPU2D │ │ gpu2d.mk │ │
    │ ├─lv_frame │ │ ├─custom │ │ │ custom.mk │ │ │
    │ │ ├─generated │ │ │ generated.mk │ │ ├─jlres │ │ │ jlres.mk │ │ ├─lvgl │ │ │ lvgl.mk │ │ └─ui │ │ ui.mk │ └─porting │ lv_port.mk │
    └─Makefile
    如上图所示,整个SDK工程通过Makefile进行管理(建议使用vscode进行编译),子目录下采用单个.mk文件进行管理,其中子目录下的.mk文件将当前路径下的所有.c文件的路径添加进编译路径,并添加查找头文件路径,最终汇总到sdk路径下的Makefile里面,此时运行Makefile即可编译到所有代码。

imageimage 在sdk路径下空白处右键,点击“Open with Code”,并点击菜单栏-终端-运行生成任务或者快捷键Ctrl+Shift+B即可进行编译。

*注意:至于 全编译 选项,vscode里面并没有提供,那么更换了.a文件以后怎样才能进行全编译,把新的.a文件编译进去呢?其实只需要在一个确保可以编译进去的文件里的空行处轻轻敲个回车就行,比如在app_main.c文件的末尾敲个回车,目的是为了让代码发生变化,只需要代码发生变化就会将新的.a文件重新编译,当然也不一定是要在空行处敲回车,只需要保证代码发生变化即可,在这里以回车为例是因为这样的操作不影响到原本代码的逻辑。

  1. 屏驱模块说明

2.1 推屏流程简介

SDK中已经集成屏幕驱动模块,用户只需要按照规则去使用即可。

image 整体推屏流程如上图所示:
用户需要提供屏幕的初始化命令,将相关设置配置到推屏接口,并完成lcd设备的注册,为了做好屏驱管理,用户可以添加相关的宏,去管理自己的屏驱驱动,完成lcd设备注册后,lcd驱动模块会获取到对应的屏驱信息,包括初始化命令,屏幕分辨率等,LVGL的显示驱动也会从lcd驱动模块中获取到对应信息,并调用杰理lcd推屏接口进行推屏。

2.2 屏驱重要参数说明

image 上图中列举了部分屏幕参数,其中:
LCD_DRIVE_CONFIG:推屏时序选择,如QSPI_RGB565_SUBMODE2_1T2B对应的是QSPI时序,数据结构为RGB565,数据4线等,具体可以参考SDK中的doc\固件资料\UI\701N屏幕驱动配置说明.pdf以及imd.h里面的注释说明。
SCR_X、SCR_Y:屏幕x轴和y轴偏移,不需要偏移的话默认填0即可。
SCR_W、SCR_H、LCD_W和LCD_H:屏驱宽高,一般填屏幕分辨率即可。
LCD_BLOCK_W:分块buf的宽度,一般是按行分块,宽度设置为跟LCD_W一致即可。
LCD_BLOCK_H:分块buf高度,可以根据需求修改。
BUF_NUM:buf数量默认设置2,一般不需要修改。
LCD_FORMAT:推屏数据格式,默认设置RGB565,一般不需要修改。
以上提及的数据,一般只需要修改SCR_W、SCR_H、LCD_W和LCD_H和LCD_BLOCK_W即可。

image 屏幕初始化命令如上图所示,用户添加新的屏驱时需要按照一定规则去修改屏驱初始化命令,其中_BEGIN_和_END_分别为开始标志位和结束标志位,这两个标志位跟实际上推屏数据无关,只是作为杰理lcd模块用于控制数据发送的信号。BEGIN_后的第一个参数是命令,后续的则是数据,如_BEGIN, 0xc0, 0x5a, 0x5a, _END_中,命令是0xc0,数据是0x5a, 0x5a。可以理解为,以上命令是屏厂驱动的SPI_WriteComm(0xc0);SPI_WriteData(0x5a);SPI_WriteData(0x5a);转换而来。

image

屏厂原始驱动

imageimage fps:fps为设置的帧率,默认为60,底层会根据fps算出合适的时钟速率,如果想要了解fps和时钟速率的一个对应关系,可以将app_config.c里面的log_tag_const_d_UI AT(.LOG_TAG_CONST)设置为true,在打印中搜索fps相关打印即可找到两者直接的对应关系。
debug_mode_en:debug模式开关,置为true后不会推合成后的数据,而是根据debug_mode_color设定的颜色值去显示,一般用于推屏数据的排查。
debug_mode_color:debug模式时显示的颜色值。

image 注册lcd设备,在这个步骤中,会将屏驱相关信息注册进去,用户可以根据需求修改logo以及名称。

2.3 屏驱移植

用户可以在板级文件(board_701n_demo.cfg)中,看到目前支持的屏驱,也可以自行添加新的屏驱,接下来我们以添加NB3030为例去了解如何新增屏驱:

2.3.1 添加屏幕驱动的宏

image

#define TCFG_LCD_NB3030_ENABLE              ENABLE_THIS_MOUDLE

如上图,添加TCFG_LCD_NB3030_ENABLE的宏,并开启该宏。

2.3.2 添加新的屏驱文件

image 在code/sdk/cpu/br28/ui_driver/lcd_drive/lcd_spi路径下,拷贝一份屏驱,如将lcd_spi_sh_8601a_454x454.c拷贝一份,并重新命名为oled_spi.nb3030_172x320.c。

2.3.3 在Makefile中添加屏驱

image

cpu/br28/ui_driver/lcd_drive/lcd_spi/oled_spi_nb3030_172x320.c \

在makefile中添加oled_spi_nb3030_172x320.c路径,才会将该文件编译。

2.3.4 修改相关参数

参考2.2章节去修改屏幕分辨率,初始化命令,时序等相关参数即可。

2.3.5 修改屏幕相关引脚

image 需要板级.c文件(当前使用的板级是board_701n_demo.c)里的引脚配置与原理图的一致。

到这一步为止,屏驱添加流程就结束了。

  1. TP驱动移植 TP驱动的宏管理与屏驱的类似,在板级文件中添加相关的宏进行管理:
    image 一般TP厂会提供驱动,只需要把iic接口换上,并且添加三个参数即可,需要添加的三个参数如下:
    imageimage
volatile u8 touch_down = 1; // 按下标志位
volatile int touch_x = 0;   // x轴报点
volatile int touch_y = 0;   // y轴报点

这三个参数是用于传递触摸事件信息给LVGL,只需要在TP驱动对应的touch_event_handler中添加这三个值的获取即可,LVGL的输入设备中会轮询读取这三个值,获取相应触摸事件。上图中touch_y = VK_Y - mytouch_data.point.y - 1;是对TP进行了镜像处理,若不需要镜像,修改为touch_y = mytouch_data.point.y;即可。

调试时,可以打开LVGL鼠标进行辅助:
image 在lv_rtos_port.c中,将lv_obj_add_flag(cursor_obj, LV_OBJ_FLAG_HIDDEN);注释掉,取消默认隐藏,即可显示鼠标,且跟随手拖动。其中lv_img_set_src(cursor_obj, &ID_ic_xia); 可以改为任意图片,只需要确保打包的资源里面存在对应图片即可,如将cursor.png添加打包后,可以通过lv_img_set_src(cursor_obj, "F:/cursor.bin");的方式进行加载,至于维护需要通过这种方式加载,可以参考下文。
4. LVGL UI设计

4.1 LVGL UI文件说明

以下提及的UI文件仅作参考,不需要完全按照所提及的形式去进行开发,用户可以根据自己的编程习惯以及工程管理习惯去进行开发。
SDK中的LVGL例程文件主要集中在generated路径下:
imageimage 其中gui_guider.c里面主要放置ui的程序入口函数setup_ui(),这个函数的具体的作用是加载对应页面,并且对该页面的控件进行初始化设置,其设置风格如下:
image LVGL中对控件的设置如上所示,LVGL提供了相当丰富的接口,供用户去修改控件的各个属性。

而events_init.c则是进行对应事件进行配置,可以根据以下例子进行了解:
image 回调函数添加事件处理,该回调事件是在图片控件按下时会执行,比如想要在某个图片控件按下时执行切换到上一首歌曲的操作,只需要在这里添加切换上一首歌曲的逻辑即可,这样就可以完成了UI交互层和功能逻辑层的合并。

image 最终会在上图所在添加事件回调,添加后等对应事件触发,就会执行相应回调。

4.2 LVGL常用接口

4.2.1 添加/清除标志

/**
 * Set one or more flags
 * @param obj   pointer to an object
 * @param f     R-ed values from `lv_obj_flag_t` to set.
 */
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);

/**
 * Clear one or more flags
 * @param obj   pointer to an object
 * @param f     OR-ed values from `lv_obj_flag_t` to set.
 */
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f);

/* example1:隐藏控件 */
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);

/* example2:显示控件 */
lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);

4.2.2 添加/清除状态

/**
 * Add one or more states to the object. The other state bits will remain unchanged.
 * If specified in the styles, transition animation will be started from the previous state to the current.
 * @param obj       pointer to an object
 * @param state     the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
 */
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state);

/**
 * Remove one or more states to the object. The other state bits will remain unchanged.
 * If specified in the styles, transition animation will be started from the previous state to the current.
 * @param obj       pointer to an object
 * @param state     the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
 */
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state);

/* example1:触发选中事件 */
lv_obj_add_state(obj, LV_STATE_CHECKED);

/* example2:清除选中事件 */
lv_obj_clear_state(obj, LV_STATE_CHECKED);

4.2.3 图片显示

/**
 * Set the image data to display on the object
 * @param obj       pointer to an image object
 * @param src_img   1) pointer to an ::lv_img_dsc_t descriptor (converted by LVGL's image converter) (e.g. &my_img) or
 *                  2) path to an image file (e.g. "S:/dir/img.bin")or
 *                  3) a SYMBOL (e.g. LV_SYMBOL_OK)
 */
void lv_img_set_src(lv_obj_t * obj, const void * src);

/* example1:将bg图片设置到img图片控件上进行显示 */
/* 这种方式对应以上说明的第一种,通过将图片转换为c数组的方式,去加载c数组进行显示 */
lv_img_set_src(img, &_bg_40x20);

/* example2:将bg.bin文件设置到img图片控件上进行显示 */
/* 这种方式对应以上说明的第二种,通过文件路径的形式去进行显示 */
/* 推荐使用第二种,结合资源打包工具使用流程较为简单,无需手动转换 */
lv_img_set_src(img, "F:/bg.bin");

4.2.4 文字显示

/**
 * Set a new formatted text for a label. Memory will be allocated to store the text by the label.
 * @param obj           pointer to a label object
 * @param fmt           `printf`-like format
 * @example lv_label_set_text_fmt(label1, "%d user", user_num);
 */
void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(2, 3);

/* example1:label控件格式化输出显示 */
static const char *string = “hello”;
lv_label_set_text_fmt(label, "%s", string);

以上为一些最基础的接口,更详细的接口说明可见于文档顶部中的LVGL参考链接。

  1. 工具使用说明 与资源相关的工具全部放置在code\sdk\lv_charging_case\res-pack-tools路径下:
    image

与makefile相关工具则放置在code\sdk\lv_charging_case路径下:
image

  1. 资源转换工具说明

👀提问:为什么需要进行资源转换?

答:为了进一步适配imb 2D加速模块
LVGL的资源访问方式主要有两种,就是以上提到的通过c数组的方式和通过bin文件路径的这两种方式,但这两种方式均是没有进行压缩,最终生成的资源文件空间较大,另一方面是部分图片格式数据结构与imb能识别的格式有所出入,故需要利用杰理资源转换工具进行生成,打包,以便于适配2D加速模块。

image 上图为资源访问的示意图,从LVGL应用层角度来说,跟LVGL访问资源的常规方式并无差别,只是底层针对性地做了适配,采用路径方式访问可以更好地获得加速效果,但也保留了原本的通过数组访问的方式。
另外杰理资源打包工具,会将图片资源进行压缩,进一步减少资源空间占用。 在此,建议用户使用路径的方式去访问图片,因为这种方式转换成本最低,SDK中提供转换工具进行转换使用,如图片名为bg.png,当需要把这张图片加载到图片控件上时,则建议用户“lv_img_set_src(img, "F:/bg.bin");”以路径的方式去使用,最后再采用资源打包工具将路径与id关联起来即可。

以上便是资源打包工具的作用。

❗资源打包工具使用说明

资源打包工具的目录是code\sdk\lv_charging_case\res-pack-tools\imb-rle-pack
image 工具以 可执行程序 的形式呈现,双击run.exe即可运行,无需依赖其他环境。

│ copy.bat │ run.exe │ run.py │
├─imbtools │ │ Clear.bat │ │ ResBuilder.exe │ │ ResBuilder.xml │ │
│ ├─images │ └─output │ ui.str │ ui_str_index.h │
└─output ui.res ui_pic_index.h usr_pic_index.c usr_pic_index.h
工具目录结构如上,其中重点的有几个部分:
images文件夹:存放图片原文件,可以理解为是工具的输入,默认支持.png和.bmp格式。
output文件夹:工具转换结束后的输出文件夹。
ui.res:打包压缩后的资源文件。
usr_pic_index.c:打包压缩后资源的路径id映射文件,底层会根据该路径转换为id访问资源。
usr_pic_index.h:打包压缩后资源访问id,可以直接通过id的方式去对资源进行访问。
使用步骤非常简单,将图片资源放到images文件夹,双击运行run.exe后进行资源打包,打包结束后,工具会自动调用copy.bat,将资源自动拷贝到sdk\cpu\br28\tools\ui_resource路径下,也就是下载目录,在编译代码时,download.bat会将ui.res进行打包并下载。至于使用的时机,则是资源发生变化时需要手动运行,比如替换了某张图片或者增加某张图片后,请在下载代码前双击运行,重新生成一下资源。

以下两个文件为核心工具,但一般情况下不需要修改,有兴趣的话可以稍作了解,但大部分情况下不需要人为去改动:
Resbuilder.exe:核心打包工具,会解析Resbuilder.xml,根据里面的配置去执行打包压缩。
Resbuilder.xml:可以理解为是打包工具的配置文件,可以在该文件下修改资源格式,如png格式可以选择修改为ARGB8565、ARGB8888等。

  1. 资源更换工具说明 在一些情况下,比如多个项目的功能需求一模一样,只是UI风格有所区别,此时如果手动更换UI,逐个控件去进行图片替换,是极为麻烦且耗时的,在此提供了一个转换工具,可以直接进行资源更换,但要满足一个大前提的情况下才能使用:
    两个项目的对应的图片尺寸,命名方式,格式必须完全一致。
    通过工具进行校验,若满足以上前提,则会自动生成图片资源。
    image 其中资源更换工具的目录是code\sdk\lv_charging_case\res-pack-tools\资源更换工具入口,双击 校验并生成图片.exe 运行。
    可以直接使用资源校验工具去进行图片对比,其中\res-pack-tools\imb-rle-pack\imbtools\images为开发者输入图片目录,也就是源参考的图片目录;而\res-pack-tools\资源更换工具入口\USER_IMAGE为客户端更换图片目录,也就是用于更换的新的图片,双击 校验并生成图片.exe 运行,工具会自动校验两个目录下图片的名字,尺寸,校验通过后会重新生产资源,校验失败则会有提示,用户可以根据提示去修改图片,如下所示:
    image 资源对比发现USER_IMAGE目录下缺少了0.png,以及ic_jia.png分辨率不一致,当前分辨率为(80, 60),应当修改为(60, 60),用户可以根据此提示去对不符合要求的图片进行整改。
    需要注意的是,当运行资源打包工具code\sdk\lv_charging_case\res-pack-tools\imb-rle-pack\run.exe时,会将USER_IMAGE覆盖,注意做好备份。

👉资源下载说明

在code\sdk\cpu\br28\tools\download\watch路径下的download.bat中配置需要下载的资源如下所示:
image

而资源文件则是存放在code\sdk\cpu\br28\tools\ui_resource路径下:
image 将资源文件的拷贝工作由脚本来完成。

  1. 图片缩放工具说明

image 该工具的目录是code\sdk\lv_charging_case\res-pack-tools\图片缩放工具,在UI开发过程中,我们需要对一些图片尺寸进行简单的微调,这个时候可以使用图片缩放工具进行处理,在input_folder_path中放入输入图片,双击 run.exe后,输入输出图片的宽高即可,如下图以将图片缩放到20*30为例:
image 此时会将图片按照要求将图片缩放到设定尺寸并输出至output_folder_path路径下。

  1. 用户动画更换入口

👀提问:什么是外部动画?

答:外部动画是相对于内部动画来说的,所谓的内部动画可以理解为LVGL原本就支持的动画控件的使用方式,常用方式如下:

const char * anim_imgs[5] = { 
    "F:/wallpaper_small_00.bin",
    "F:/wallpaper_small_01.bin",
    "F:/wallpaper_small_02.bin",
    "F:/wallpaper_small_03.bin",
    "F:/wallpaper_small_04.bin"
};

//Write codes anim
ui->anim = lv_animimg_create(ui->screen);
lv_animimg_set_src(ui->anim, (const void **) anim_imgs, 5);
lv_animimg_set_duration(ui->anim, 100*5);
lv_animimg_set_repeat_count(ui->anim, LV_ANIM_REPEAT_INFINITE);
// lv_animimg_start(ui->anim);
lv_obj_set_pos(ui->anim, 2, 2);
lv_obj_set_size(ui->anim, 140, 60);
lv_obj_add_flag(ui->anim, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(ui->anim, LV_OBJ_FLAG_SCROLLABLE);

以上代码配置了一个指针数组anim_imgs去存放内部动画所需要的切图资源,但这种做法在切换动画时就显得不太灵活,需要修改里面的切图路径,故推出外部动画,将每个动画打包成一份独立的资源文件,以文件名作为输入进行访问,同时不需要考虑更换动画时切图数量是否跟之前一致的问题。
故外部动画的优点在于使用灵活,能够快速方便地给动画控件进行资源切换,但缺点是会消耗一定的ram。

该工具目录位于code\sdk\lv_charging_case\res-pack-tools\用户动画更换入口,需要依赖于\code\sdk\lv_charging_case\res-pack-tools\helper-tools
image 该工具的作用是生成外部动画打包资源,其中外部动画的资源会被打包成.bin文件和.res的文件,最终被合并成以文件夹命名的文件,添加到下载目录。

这里以充电动画CHG为例进行一次讲解:
image code\sdk\lv_charging_case\res-pack-tools\用户动画更换入口\CHG路径下文件作用如下:
100ms文件夹:这里的“100ms”为动画切换间隔,工具会去解析该文件夹的文件名,获取动画切换的间隔,故在此必须按照xxxms这种方式命名,否则工具将无法获取动画间隔,从而导致生成资源失败,若想把动画间隔改为200ms,将该文件夹重命名为“200ms”即可,里面存放的则是动画的切图文件。
CHG.bin:该文件主要包含文件名,动画间隔以及图片数量的信息,用于给底层解析外部动画的信息。
CHG.res:打包后的外部动画资源文件,可以直观地看出当前动画资源文件为400kb,用户可以通过调整100ms文件夹中的图片去进一步缩减资源文件大小。

此时如果100ms同级目录下如果有gif图片,则会以gif优先,将gif解析为一张张切图,并放置在以gif播放间隔命名的文件夹中,并生成资源。

当所有动画资源生成完成后,可以将code\sdk\lv_charging_case\res-pack-tools\用户动画更换入口\pack_code.txt的内容复制到download.bat中,并决定需要将哪些外部动画添加下载:
image

之后调用usr_update_animing接口将动画控件与外部动画资源绑定在一起即可。

  1. Makefile生成工具

🙈提问:为什么需要使用Makefile生成工具?

答:为了针对目录结构发生改变后进行快速Makefile构建,以及便于移植。
在第一章中,提到了该SDK是通过Makefile进行管理的,那么当目录结构发生变化,比如/a路径下存在abc.c文件,若此时把abc.c移动到/b路径下,则需要手动将Makefile中abc.c的文件路径进行修改,否则编译时会报错,并提示“No rule to make /a/abc.o”。如果改动文件较少,一般不成问题,但如果改动较大,涉及到的文件有上百个,上千个,手动去修改是不太合理的,故可以通过工具去重新构建Makefile,避免人为修改。

image 工具目录为code\sdk\lv_charging_case,需要依赖cmake和mingw(下载链接可见于文档顶部),其中:
makefile_clear.bat:用于清除过程文件,包括.mk文件,工具会遍历\lv_charging_case路径下的所有过程文件并且进行删除。
makefile_maker.bat:用于重新构建Makefile,生成每个子目录下的.mk文件,工具会遍历\lv_charging_case路径下的所有.c文件,将.c文件的路径添加到编译路径,并且会遍历所有.h文件,将包含了头文件的路径添加到头文件查找路径。
以上两个均为批处理文件,双击运行即可。使用时机为\lv_charging_case路径下的目录结构发生变化时,若不希望手动修改Makefile,则可以通过工具重新构建Makefile。

  1. 其他UI框架接入耳机和982 在某些场景下,会有接入LVGL以外的UI框架的需求,此时能以LVGL的逻辑层为参考,去接入三方交互的逻辑,但在此之前,我们先了解一下耳机、982与充电仓之间是如何交互的。
    首先,耳机和982共同维护一套变量,这套变量已结构体的形式在充电仓SDK中呈现,其每个成员的意义如下(该结构体可见于code\sdk\apps\watch\smartbox\smartbox_user_app.h):
struct s_box_info {
    u8 phone_state ;    //手机连接状态,0:不连接 1:连接
    u8 earphone_state;  //耳机连接状态,0:不连接 1:连接
    u8 l_ear_bat ;      //L耳电量 
    u8 r_ear_bat ;      //R耳电量
    u8 box_bat ;        //充电仓电量
    u8 music_state;     //耳机播放状态
    u8 earphone_vol ;   //耳机音量
    u8 anc_mode ;       //anc模式,0关 1开 2通透
    u8 eq_mode;         //eq模式
    u8 ui_bl_levl;      //仓背光亮度
    u8 l_charging;      //L耳充电状态
    u8 r_charging;      //R耳充电状态
    u8 box_charging;    //充电仓充电状态
    u8 l_finding;       //查找L耳
    u8 r_finding;       //查找R耳
    u8 box_clid_status; //充电仓开关盖状态
    u8 language;        //语言
    u8 low_power;       //低电状态
    u8 phone_call_state;//通话状态
    u8 phone_call_mute; //通话是否静音
    u8 local_page;      //本地页面记录
    struct sys_time phone_time;//系统时间
};

其中,982通过串口与充电仓通信,而耳机则是通过ble与充电仓进行通信(使用RCSP),实时更新box_info的变量,UI再根据这些状态,去进行显示等操作。那么,接入其他UI框架之前,需要保证充电仓能正常与耳机,982进行通信,涉及到这块功能的关键文件如下:
- smartbox_user_app.c - smartbox_user_app.h - lib_wsbox.a - uart_test.c - uart_test.h - uart_types.h - uart_v1.c - uart.h 以上文件需要全部移植到用户的SDK中,移植成功后,SDK已经兼备了实现以上功能的具体文件,但还需要在充电仓中主动更新连接状态(可见于code\sdk\apps\watch\smartbox\bt_manage\bt_trans_data\le_smartbox_multi_client.c):
image 在上图两个地方调用sbox_ble_connect_flag_set、sbox_bt_connect_flag_set主动更新蓝牙连接,并且按照彩屏仓SDK板级文件board_701n_demo_cfg.h的宏进行配置,建议用对比工具将板级文件中蓝牙相关的配置进行对比,同步。以上操作完成后,彩屏仓与蓝牙、982的通信基本已经打通,至于UI与蓝牙之间的交互,可参考中间层文件events_adapter.c。

image 充电仓可以通过以下接口去获取box_info的状态值(可见于code\sdk\lv_charging_case\lv_frame\adapter\events_adapter.c):
image 在box_info_base_cb中,右边的函数如sbox_bt_connect_flag_get等为获取状态值的具体实现,而左边的带有lv前缀的函数如lv_phone_state_get则是用于UI线程中获取相关状态值,通过这种方式即可在UI中获取对应状态值并且进行相关处理。同时,充电仓也可以通过box_info_base_cb里面的接口,主动更新box_info的状态值。

UI除了获取状态以外,还需要主动与耳机去进行通信,如进行音量控制等,这些接口则是存放于box_info_send_cb中:
image 与box_info_base_cb类似,右边的接口为具体实现,而左边的则是在UI中直接调用的接口。在events_adapter.c中,box_info_base_cb、box_info_send_cb中配置的接口是直接跟耳机、982相关的,除此之外的则是跟LVGL相关的,如配置亮灭屏,RTC等,因此,在其他UI框架中与982、耳机进行通信,只需要将box_info_base_cb、box_info_send_cb里面使用到的配置接口,在其他UI框架中对应的回调函数里面进行调用即可。

接下来以LVGL的一个音乐播放暂停功能为例,介绍如何接入蓝牙相关接口:

static void screen_loop_imgbtn_music_play_or_stop_event_handler (lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);

    switch (code) {
    case LV_EVENT_CLICKED:
    {
        int music_status = box_info_base_cb.lv_music_state_get(); // 获取音乐播放状态
        switch (music_status)
        {
            case MUSIC_STATE_PAUSE:
                box_info_send_cb.lv_music_play_cmd_send(); // 发送播放音乐命令
                box_info_base_cb.lv_music_state_set(MUSIC_STATE_PLAY); // 主动更新状态为音乐播放
                break;
            case MUSIC_STATE_PLAY:
                box_info_send_cb.lv_music_pause_cmd_send(); // 发送暂停音乐命令
                box_info_base_cb.lv_music_state_set(MUSIC_STATE_PAUSE); // 主动更新状态为音乐暂停
                break;
            default:
                break;
        }
        break;
    }
    default:
        break;
    }
}

以上例子中,screen_loop_imgbtn_music_play_or_stop_event_handler作为screen_loop_imgbtn_music_play_or_stop控件的回调函数,当控件被点击时,回调函数会被执行,此时通过box_info_base_cb.lv_music_state_get()获取音乐状态,再根据状态去调用蓝牙命令发送接口,去实现音乐的播放暂停控制。故对于其他UI框架来说,在对应的回调中调用状态获取接口,状态设置接口,以及蓝牙命令发送接口即可。

总结一下,整体接入流程为:
1. 移植关键文件(涉及充电仓与耳机,982通信); 2. 充电仓中主动更新连接状态; 3. 比对充电仓板级文件中蓝牙相关配置; 4. 参考events_adapter.c中配置的接口,在用户UI框架对应的回调中去调用相关接口去搭建UI交互逻辑。

  1. 常见问题
  2. 其他UI框架如何进行屏幕旋转? 如果其他UI框架(包含杰理UI框架跟自有UI框架)的屏幕驱动使用的是公版sdk的流程,而不是自己重构流程,均可以使用以下补丁:
    lcd_drive.c下载链接
    image 用户可以根据自身需求更改旋转角度,其中scr_x,scr_y的配置与旋转的角度无关。

本文档包含以下子页面

  • cmake&mingw安装教程
  • 屏厂原始驱动
Prev
音箱可视化彩屏-入门到进阶开发指导
Next
使用内部UI框架进行UI调试的系列步骤