本专栏由非官方人员 王小小海 所著,其内容主要记录了在开发5340的过程中遇到的一些问题和解决方法,还有一些应用的例程。作者本人也是在实践应用中遇到的问题,想着把这些问题分享给可能遇到的朋友。仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。
本专栏不涉及基础的安装和环境搭建问题,本例程开发使用NCS 2.5.0开发,还请注意!。
本文代码位置
https://gitee.com/seliverwang/ncs_250_lvgl_demo.git
前言
nRF5340 作为Nordic 已推出系列中的 高端产品,拥有128Mhz的主频 和 32Mhz的SPI驱动能力。支持BLE 5.4 、LE Audio、AOA、Thread等多种协议,待机功耗在1~2个uA,很适合做低功耗的 手表 应用。今天就分享如何使用 zephyr 自带的 LVGL 组件进行 屏幕点亮,显示图标的教程。
所有分享内容
笔记分享
- 【笔记分享】NCS下radio_test添加FEM
- 【笔记分享】5340基于 BLE LBS 自定义网络核固件点亮LED并合并固件
- 【笔记分享】5340基于LBS自定义网络核双核DFU实现
- 【笔记分享】5340 设置public address 和 random address
- 【笔记分享】NCS nRF52/53 添加LVGL组件驱动屏幕
- 【笔记分享】VirtualBox Ubuntu22.04 不能使用nrfjprog问题记录
应用分享
暂无
文章目录
- 本文代码位置
- 前言
- 所有分享内容
- 笔记分享
- 应用分享
- NCS nRF52/53 添加LVGL组件驱动屏幕
- 前提准备和介绍
- 硬件准备
- 软件准备
- 开始操作
- 移植操作流程
- 设备树增加和修改
- 拓展 设置
- 软件拓展、
- 结束语
NCS nRF52/53 添加LVGL组件驱动屏幕
前提准备和介绍
准备材料
- NCS 2.5.0 开发环境。
- nRF52/nRF53 系列开发板。
- SPI TFT屏幕一个。
- 杜邦线若干条。
本文使用 nRF5340 通过SPI 连接 驱动芯片为ILI9341的 TFT显示屏。
硬件准备
将SPI TFT屏幕 通过 杜邦线 按照以下引脚排序 接入到 开发板上。
硬件由此接好之后,开始准备 NCS 开发环境。
nRF5340 | TFT ILI9311 |
---|---|
P1.15 | CS/CSN 片选 |
P1.14 | RESET 复位 |
P1.13 | DC/DCX 命令/数据 (低电平写命令,高电平写数据) |
P1.12 | MOSI |
P1.11 | SCK |
P1.10 | MISO |
VCC | LED(背光) |
VCC | VCC |
GND | GND |
软件准备
创建工程
- 首先打开 VS CODE.
- 点击 nrf-connect.
- 点击 Create a new appication .
- Copy a sample .
- 输入 lvgl .
- 选择 lvgl .
- 回车并 打开当前目录。
开始操作
创建工程
如果我们这个时候去选择板子编译,可以看到很多错误。
编译选择展示
报错展示
那么下面就开始解释如何编译成功。
移植操作流程
根据上面报错展示,展示了我们zephyr在调用时,调用了 设备树 CHOSEN 节点中的 zephyr_display 。由于没有这个节点,那么就直接报错。那么最简单的方式 就是 添加自己的设备树 overlay,在添加这个节点就可以了。详细过程见下节。
设备树增加和修改
- 创建 overlay文件,并创建设备树 zephyr_display节点。 根据自己的板子,创建不同名字的overlay, 此教程也适用 nRF52 系列。
创建完成之后,并添加 chosen节点 zephyr,display = &ili9341; ,其中 &ili9341 随意命名,但是最好就跟你 显示驱动的 IC芯片名称一致比较好,这个看个人规范爱好。
- 创建 之后,直接编译一次,可以看到它提示没有 ili9341 这个 label, 说明我们还需要定义 ili9341 的这个label。
ili9341 这个label怎么定义呢,我们完全不知道。这时候,就需要通过 github 去搜索了。
搜索介绍
- 打开 https://github.com/zephyrproject-rtos/zephyr zephyr的 github。
- 搜索 zephyr,display ,可见下图搜索结果。
- 任意点击一个搜索结果,查找 zephyr,display对应的 label 定义。
- 可以看到 原来 zephyr,display 节点关联的那个 ili9341 是 在 spi 节点定义的,那么我们就可以先把别人的拷贝出来,然后 修改成我们自己的。
- 拷贝过来之后,可以看到别人用的 SPI1,并且驱动芯片为 ssd16xx。那么就需要把这些东西修改成我们能用的。我们打算 不用 SPI1,用SPI4(因为5340的 SPI4 在 128Mhz的情况下是高速SPI,可以跑到32Mhz)。其中这个 ssd16xx 节点里面有很多我们不知道的东西,full , partial 这些东西。不知道的东西,我们都删掉。然后把 ssd16xx 改成 ili9341.
- 修改内容为以下截图:**注意一定要修改spi4中的 compatible = “nordic,nrf-spi”; 为 compatible = “nordic,nrf-spim”;不然会报错。
- 可以看到修改了之后,还剩下 ili9341 节点里面的 compatible 没有修改了。打开 zephyr sdk的目录下查看 zephyr现在支持哪些 显示驱动。其目录为:v2.5.0/zephyr/dts/bindings/display。
- 可以看到,它有我们需要的 ilitek,ili9341,那么直接修改 compatible 为:
- 点击编译,咱们试试能不能编译成功,编译之后,结果报,没有cmd-data-gpios 这个 属性,那奇怪了,我们上图不是有个 dc-gpios 吗,难道不一样 :
- 这时候我们就需要打开对应的 compatible 文件中的属性,具体查看怎么定义的了。我们就点击 ili9341 这个compatible 查找 cmd-data-gpios,最后发现这个cmd-data-gpios在 ili9xxx-common.yaml文件中:
- ili9xxx-common.yaml 这个文件中还定义了很多其他属性:
- reset-gpios: 复位引脚,必须。
- cmd-data-gpios:D/CX 引脚,必须。
- pixel-format 显示格式为 RGB565和RGB888,我们用SPI通常是RBG565,默认就是RGB565那么我们不修改了。
- rotation 旋转屏幕,0,90,180,270,我们暂时不修改。
- 那么根据上面的内容,我们对应自己的引脚修改完成overlay文件,修改overlay之后文件内容如下。那么修改完成不就OK了吗,完美!!!
- 那么我们开始下载编译吧,但是在这之前别忘了开启 log,不然不好调试,默认是开了log的,下载完成之后,你会发现什么情况,一直在不停的复位重启,复位重启。
什么鬼,为什么在一直不停的复位重启,那么我们看一看log里面是哪些地方错了。
我们发现报错中有一行: lvgl: Vertical resolution is larger than maximum。
然后又报了: lvgl: (0.385, +385) lv_disp_get_scr_act: no display registered to get its active screen (in lv_disp.c line #54)。
那么我们 打开 lvgl这个文件看看,到底是什么问题。
- 打开vs code的 nrf-connect 文件浏览这一栏,找到lvgl,并打开 lvgl.c,搜索 Vertical resolution,可以看到原来 这一行出错了,那这一行出错了之后,会影响哪里呢?根据搜索可以看到, lvgl_allocate_rendering_buffers因为错误 直接返回了,没有注册和初始化 lvgl 的显示驱动函数,那么为啥这个会报错呢?
- 问题分析,发现 设备树 ili9341 节点中的,width = <320>;height = <240>; 但是ili9341的驱动默认是 width= 240, height = 320.因此我们需要把 屏幕旋转一下,那么我们在步骤 11 看到的 rotation 那就非常有用了。
- 修改设备树,增加 rotation,增加完成之后如下图,我们在编译下载看看有没有问题。
- 编译运行测试,终于正常运行了,但是屏幕上的颜色怎么不对呢,默认颜色是蓝色。查看.config文件发现 CONFIG_LV_COLOR_16_SWAP 没有将颜色反转,那么我们将颜色进行反转,在pj.conf中添加 CONFIG_LV_COLOR_16_SWAP=y.
- 编译完成,运行正常,可以看到它的 label 每1S增加一次计数值。
拓展 设置
上面我们介绍了详细过程和思路。但是实际还需要查看LVGL一些配置相关的东西。
- 内存配置。LVGL 使用了2中内存管理方式,一就是 默认的 lvgl 自带mem管理,二是 使用自定义的 内存管理接口,比如:系统自带的 malloc ,或者zephyr定义的 lvgl_malloc。但是我们发现,实际lvgl的内存很小,只有 8 * 2048 = 16K。如果定义大的图片和显示多的控件就会内存不够,直接 HardFault。因此根据使用场景 加大 CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS的数量。
默认lvgl的配置
zephyr定义的malloc函数
软件拓展、
在测试过程中发现,nRF5340的 SPIM4没有跑到32Mhz,只有16Mhz,但是在main中又初始化了主频到128Mhz,后续根据排查发现,zephyr在配置spi参数时会检查当前的主频,如果在128Mhz则配置 32Mhz,如果不是,那么最高只有16Mhz,并且配置1次波特率之后,就不会在更新了。那么就需要把 切换128Mhz的函数 放在 SPI参数配置之前。
// 高频128Mhz 运行模式.
static int hfclock_config_and_start(void)
{
int ret;
/* Use this to turn on 128 MHz clock for cpu_app */
ret = nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1);
ret -= NRFX_ERROR_BASE_NUM;
if (ret) {
return ret;
}
nrfx_clock_hfclk_start();
while (!nrfx_clock_hfclk_is_running()) {
}
return 0;
}
// 初始化高频时钟128Mhz运行模式. 因为SPI配置的时候会判断当前是否在 高频模式,
SYS_INIT(hfclock_config_and_start, POST_KERNEL, 0);
结束语
以上为整个NCS nRF52/53 添加LVGL组件驱动屏幕的笔记分享,本文内容较多,不过大多数都是在 overlay中使能对应的 设备树节点,zephyr编译期间去识别对应的节点是否存在,然后在转换为宏来开启对应功能,不太明白可以看一下gitee中的代码。
有不明白的地方欢迎提问,也厚脸皮要个赞或者关注,谢谢各位啦。
本系列文章大多数是本人遇到和解决过的问题,难有疏忽之处,有什么问题或者不明白的地方,欢迎留言询问!