找回密码
 立即注册
首页 业界区 安全 zephyr学习: 4.LVGL+LCD显示触摸

zephyr学习: 4.LVGL+LCD显示触摸

洪势 2025-8-17 01:30:46
 
 参考:ESP32移植Zephyr RTOS(二)-----使用LVGL_esp32 zephyr-CSDN博客
立创实战派开发板(esp32-s3)
 
1.  硬件结构

1.png

2.png

触摸屏是I2C接口,TFT是SPI接口(LCD_CS比较特殊,是由PCA9557扩展出来的)
3.png

IO扩展是由I2C驱动的
 
2. 配置LCD的设备树

2.1 配置SPI引脚复用( lc_shizhanpai-pinctrl.dtsi )


  • SCLK:GPIO41
  • MOSI:GPIO40
  • 使用SPI3/SPI2, SPI1已经被外部Flash使用了
  • 这里先不配置LCD_CS引脚,因为LCD_CS引脚不是MCU上的引脚。
  1. spim3_default: spim3_default {
  2.                 group1 {
  3.                         pinmux = <SPIM3_SCLK_GPIO41>;
  4.                 };
  5.                 group2 {
  6.                         pinmux = <SPIM3_MOSI_GPIO40>;
  7.                         output-low;
  8.                 };
  9.         };
复制代码
 
2.2  配置mipi_dbi

参考esp32的板子可以知道在驱动lcd时用了mipi_dbi的接口,对应zephyr,mipi-dbi-spi的驱动;
LCD驱动芯片是st7789,使用了兼容的sitronix,st7789v驱。

  •  配置DC引脚:GPIO39
  1. mipi_dbi {
  2.                 compatible = "zephyr,mipi-dbi-spi";
  3.                 dc-gpios = <&gpio1 39 GPIO_ACTIVE_HIGH>;
  4.                 spi-dev = <&spi3>;
  5.                 write-only;
  6.                 #address-cells = <1>;
  7.                 #size-cells = <0>;
  8.                 st7789v: st7789v@0 {
  9.                         compatible = "sitronix,st7789v";
  10.                         mipi-max-frequency = <80000000>;
  11.                         reg = <0>;
  12.                         width = <240>;
  13.                         height = <320>;
  14.                         x-offset = <0>;
  15.                         y-offset = <0>;
  16.                         vcom = <0x19>;
  17.                         gctrl = <0x35>;
  18.                         vrhs = <0x12>;
  19.                         vdvs = <0x20>;
  20.                         mdac = <0x00>;
  21.                         gamma = <0x01>;
  22.                         colmod = <0x55>;
  23.                         lcm = <0x2c>;
  24.                         porch-param = [0c 0c 00 33 33];
  25.                         cmd2en-param = [5a 69 02 01];
  26.                         pwctrl1-param = [a4 a1];
  27.                         pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23];
  28.                         nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23];
  29.                         ram-param = [00 F0];
  30.                         rgb-param = [CD 08 14];
  31.                         mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";
  32.                 };
  33.         };
复制代码
 
2.3 配置I2C0

配置pca9557IO扩展芯片和ft6336触摸屏

  • 两者共用I2C0
  • pca9557兼容nxp,pca9554
  • ft6336兼容focaltech,ft5336
  1. &i2c0 {
  2.     status = "okay";
  3.     clock-frequency = <I2C_BITRATE_STANDARD>;
  4.     pinctrl-0 = <&i2c0_default>;
  5.     pinctrl-names = "default";
  6.     pca9557_io_expander: pca9554@19 {
  7.         compatible = "nxp,pca9554";
  8.                 label = "PCA9557";
  9.                 status = "okay";
  10.                 reg = <0x19>;  
  11.                 gpio-controller;       
  12.                 #gpio-cells = <2>;
  13.                 ngpios = <8>;
  14.     };
  15.     ft6336_touch: ft5336@38 {
  16.                 status = "okay";
  17.                 compatible = "focaltech,ft5336";
  18.                 reg = <0x38>;
  19.         };
  20. };
复制代码
 
2.4 配置spi3


  • 关键在于要把LCD_CS脚配置成 cs-gpios
  • 由于这里的spi cs引脚依赖于 pca9557_io_expander,所以在工程prj.conf里面需要降低SPI的初始化优先级(CONFIG_SPI_INIT_PRIORITY=70)
  1. &spi3 {
  2.         status = "okay";
  3.         #address-cells = <1>;
  4.         #size-cells = <0>;
  5.         pinctrl-0 = <&spim3_default>;
  6.         pinctrl-names = "default";
  7.         cs-gpios = <&pca9557_io_expander 0 GPIO_ACTIVE_LOW>;
  8. };
复制代码
 
2.5 配置 chosen
  1. zephyr,display = &st7789v;
  2. zephyr,touch = &ft6336_touch;
复制代码
 
2.6 配置背光引脚和 lvgl


  • 背光引脚使用gpio-leds驱动
  • 把触摸屏信号配置成lvgl的输入接口
  1. leds {
  2.     compatible = "gpio-leds";
  3.     tft_backlight: led_0 {
  4.         gpios = <&gpio1 42 GPIO_ACTIVE_LOW>;
  5.         label = "TFT LCD Backlight";
  6.     };
  7. };
  8. lvgl_pointer {
  9.     input = <&ft6336_touch>;
  10.     compatible = "zephyr,lvgl-pointer-input";
  11. };
复制代码
 
 
完整propu_dts: 点击查看代码
  1. /* * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 *//dts-v1/;#include #include #include #include #include "lc_shizhanpai-pinctrl.dtsi"/ {        model = "lc_shizhanpai PROCPU";        compatible = "espressif,esp32s3";        aliases {                i2c0 = &i2c0;                watchdog0 = &wdt0;                sw2 = &button0;                backlight = &tft_backlight;        };        chosen {                zephyr,sram = &sram1;                zephyr,console = &uart0;                zephyr,shell-uart = &uart0;                zephyr,flash = &flash0;                zephyr,code-partition = &slot0_partition;                zephyr,bt-hci = &esp32_bt_hci;                zephyr,display = &st7789v;                zephyr,touch = &ft6336_touch;                // zephyr,camera = &lcd_cam;        };        buttons {                compatible = "gpio-keys";                button0: button_0 {                        gpios = ;                        label = "BOOT Button";                        zephyr,code = ;                };        };        mipi_dbi {
  2.                 compatible = "zephyr,mipi-dbi-spi";
  3.                 dc-gpios = <&gpio1 39 GPIO_ACTIVE_HIGH>;
  4.                 spi-dev = <&spi3>;
  5.                 write-only;
  6.                 #address-cells = <1>;
  7.                 #size-cells = <0>;
  8.                 st7789v: st7789v@0 {
  9.                         compatible = "sitronix,st7789v";
  10.                         mipi-max-frequency = <80000000>;
  11.                         reg = <0>;
  12.                         width = <240>;
  13.                         height = <320>;
  14.                         x-offset = <0>;
  15.                         y-offset = <0>;
  16.                         vcom = <0x19>;
  17.                         gctrl = <0x35>;
  18.                         vrhs = <0x12>;
  19.                         vdvs = <0x20>;
  20.                         mdac = <0x00>;
  21.                         gamma = <0x01>;
  22.                         colmod = <0x55>;
  23.                         lcm = <0x2c>;
  24.                         porch-param = [0c 0c 00 33 33];
  25.                         cmd2en-param = [5a 69 02 01];
  26.                         pwctrl1-param = [a4 a1];
  27.                         pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23];
  28.                         nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23];
  29.                         ram-param = [00 F0];
  30.                         rgb-param = [CD 08 14];
  31.                         mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";
  32.                 };
  33.         };        leds {                compatible = "gpio-leds";                tft_backlight: led_0 {                        gpios = ;                        label = "TFT LCD Backlight";                };        };        lvgl_pointer {                input = ;                compatible = "zephyr,lvgl-pointer-input";        };};&i2c0 {
  34.     status = "okay";
  35.     clock-frequency = <I2C_BITRATE_STANDARD>;
  36.     pinctrl-0 = <&i2c0_default>;
  37.     pinctrl-names = "default";
  38.     pca9557_io_expander: pca9554@19 {
  39.         compatible = "nxp,pca9554";
  40.                 label = "PCA9557";
  41.                 status = "okay";
  42.                 reg = <0x19>;  
  43.                 gpio-controller;       
  44.                 #gpio-cells = <2>;
  45.                 ngpios = <8>;
  46.     };
  47.     ft6336_touch: ft5336@38 {
  48.                 status = "okay";
  49.                 compatible = "focaltech,ft5336";
  50.                 reg = <0x38>;
  51.         };
  52. };&dma {        status = "okay";};&uart0 {        status = "okay";        current-speed = ;        pinctrl-0 = ;        pinctrl-names = "default";};&spi3 {
  53.         status = "okay";
  54.         #address-cells = <1>;
  55.         #size-cells = <0>;
  56.         pinctrl-0 = <&spim3_default>;
  57.         pinctrl-names = "default";
  58.         cs-gpios = <&pca9557_io_expander 0 GPIO_ACTIVE_LOW>;
  59. };&gpio0 {        status = "okay";};&gpio1 {        status = "okay";};&i2s0 {        pinctrl-0 = ;        pinctrl-names = "default";        status = "disabled";};&timer0 {        status = "disabled";};&timer1 {        status = "disabled";};&timer2 {        status = "disabled";};&timer3 {        status = "disabled";};&wdt0 {        status = "okay";};&trng0 {        status = "okay";};&usb_serial {        status = "disabled";};&esp32_bt_hci {        status = "okay";};&wifi {        status = "okay";};
复制代码
 
3. app程序

 3.1 获取背光引脚的信息

在适当时机打开背光。
  1. static const struct gpio_dt_spec backlight = GPIO_DT_SPEC_GET(DT_ALIAS(backlight), gpios);
  2. gpio_pin_configure_dt(&backlight, GPIO_OUTPUT);
  3. gpio_pin_set(backlight.port, backlight.pin, 1);
复制代码
 
3.2 创建界面


  • 创建按钮,绑定按键click事件回调,填充文本
  • 创建计数文本
  1. static char count_str[11] = {0};
  2. const struct device *display_dev;
  3. lv_obj_t *hello_world_label;
  4. lv_obj_t *count_label;
  5. lv_obj_t *hello_world_button;
  6. hello_world_button = lv_button_create(lv_screen_active());
  7. lv_obj_align(hello_world_button, LV_ALIGN_CENTER, 0, -15);
  8. lv_obj_add_event_cb(hello_world_button, lv_btn_click_callback, LV_EVENT_CLICKED,
  9.                     NULL);
  10. hello_world_label = lv_label_create(hello_world_button);
  11. lv_label_set_text(hello_world_label, "Hello world!");
  12. lv_obj_align(hello_world_label, LV_ALIGN_CENTER, 0, 0);
  13. count_label = lv_label_create(lv_screen_active());
  14. lv_obj_align(count_label, LV_ALIGN_BOTTOM_MID, 0, 0);
复制代码
 
 3.3 屏幕显示
  1. display_blanking_off(display_dev);
  2.     lv_timer_handler();
  3.         while (1) {
  4.                 if ((count % 100) == 0U) {
  5.                         sprintf(count_str, "%d", count/100U);
  6.                         lv_label_set_text(count_label, count_str);
  7.                 }
  8.                 lv_timer_handler();
  9.                 ++count;
  10.                 k_sleep(K_MSEC(10));
  11.         }
复制代码
 
prj.conf 配置:点击查看代码
  1. # General Config
  2. CONFIG_MAIN_STACK_SIZE=4096
  3. CONFIG_CONSOLE=y
  4. CONFIG_LOG=y
  5. CONFIG_SHELL=y
  6. # Device Config
  7. CONFIG_GPIO=y
  8. CONFIG_I2C=y
  9. CONFIG_SPI=y
  10. CONFIG_INPUT=y
  11. # SPI CS delay depends on PCA9557 IO
  12. CONFIG_SPI_INIT_PRIORITY=70
  13. # LVGL Config
  14. # 16KB
  15. CONFIG_LV_Z_MEM_POOL_SIZE=16384
  16. CONFIG_LV_Z_POINTER_INPUT=y
  17. CONFIG_LV_Z_SHELL=y
  18. CONFIG_LVGL=y
  19. CONFIG_LV_USE_LOG=y
  20. CONFIG_LV_USE_LABEL=y
  21. CONFIG_LV_USE_ARC=y
  22. CONFIG_LV_USE_MONKEY=y
  23. CONFIG_LV_FONT_MONTSERRAT_14=y
  24. # 16-bit color depth RGB565
  25. CONFIG_LV_COLOR_DEPTH_16=y      
  26. CONFIG_LV_USE_PERF_MONITOR=y
  27. CONFIG_LV_COLOR_16_SWAP=y
  28. # Display Config
  29. CONFIG_DISPLAY=y
  30. CONFIG_DISPLAY_LOG_LEVEL_ERR=y
复制代码
 
主程序:点击查看代码
  1. /* * Copyright (c) 2018 Jan Van Winkel  * * SPDX-License-Identifier: Apache-2.0 */#include #include #include #include #include #include #include #include #include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL#include LOG_MODULE_REGISTER(app);static uint32_t count;static const struct gpio_dt_spec backlight = GPIO_DT_SPEC_GET(DT_ALIAS(backlight), gpios);#ifdef CONFIG_GPIOstatic struct gpio_dt_spec button_gpio = GPIO_DT_SPEC_GET_OR(DT_ALIAS(sw0), gpios, {0});static struct gpio_callback button_callback;static void button_isr_callback(const struct device *port, struct gpio_callback *cb, uint32_t pins){        ARG_UNUSED(port);        ARG_UNUSED(cb);        ARG_UNUSED(pins);        count = 0;}#endif /* CONFIG_GPIO */#ifdef CONFIG_LV_Z_ENCODER_INPUTstatic const struct device *lvgl_encoder =        DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_lvgl_encoder_input));#endif /* CONFIG_LV_Z_ENCODER_INPUT */#ifdef CONFIG_LV_Z_KEYPAD_INPUTstatic const struct device *lvgl_keypad =        DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_lvgl_keypad_input));#endif /* CONFIG_LV_Z_KEYPAD_INPUT */static void lv_btn_click_callback(lv_event_t *e){        ARG_UNUSED(e);        count = 0;}int main(void){        static char count_str[11] = {0};        const struct device *display_dev;        lv_obj_t *hello_world_label;        lv_obj_t *count_label;        display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));        if (!device_is_ready(display_dev)) {                LOG_ERR("Device not ready, aborting test");                return 0;        }        lv_obj_t *hello_world_button;        hello_world_button = lv_button_create(lv_screen_active());        lv_obj_align(hello_world_button, LV_ALIGN_CENTER, 0, -15);        lv_obj_add_event_cb(hello_world_button, lv_btn_click_callback, LV_EVENT_CLICKED,                                NULL);        hello_world_label = lv_label_create(hello_world_button);        lv_label_set_text(hello_world_label, "Hello world!");        lv_obj_align(hello_world_label, LV_ALIGN_CENTER, 0, 0);        count_label = lv_label_create(lv_screen_active());        lv_obj_align(count_label, LV_ALIGN_BOTTOM_MID, 0, 0);    gpio_pin_configure_dt(&backlight, GPIO_OUTPUT);        gpio_pin_set(backlight.port, backlight.pin, 1);        display_blanking_off(display_dev);
  2.     lv_timer_handler();
  3.         while (1) {
  4.                 if ((count % 100) == 0U) {
  5.                         sprintf(count_str, "%d", count/100U);
  6.                         lv_label_set_text(count_label, count_str);
  7.                 }
  8.                 lv_timer_handler();
  9.                 ++count;
  10.                 k_sleep(K_MSEC(10));
  11.         }}
复制代码
 
 4.  最终结果

 
4.gif

 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册