diff --git a/docs/_static/display/digit_cube_driver_CH450.png b/docs/_static/display/digit_cube_driver_CH450.png deleted file mode 100755 index 81db70b85..000000000 Binary files a/docs/_static/display/digit_cube_driver_CH450.png and /dev/null differ diff --git a/docs/_static/display/mirror_x.png b/docs/_static/display/mirror_x.png deleted file mode 100644 index 9f6c582ec..000000000 Binary files a/docs/_static/display/mirror_x.png and /dev/null differ diff --git a/docs/_static/display/mirror_xy.png b/docs/_static/display/mirror_xy.png deleted file mode 100644 index fd2b5f4ba..000000000 Binary files a/docs/_static/display/mirror_xy.png and /dev/null differ diff --git a/docs/_static/display/mirror_y.png b/docs/_static/display/mirror_y.png deleted file mode 100644 index 1f68021b2..000000000 Binary files a/docs/_static/display/mirror_y.png and /dev/null differ diff --git a/docs/_static/display/original.png b/docs/_static/display/original.png deleted file mode 100644 index 4818bcf9a..000000000 Binary files a/docs/_static/display/original.png and /dev/null differ diff --git a/docs/_static/display/screen/lcd_cmd_colmod.png b/docs/_static/display/screen/lcd_cmd_colmod.png new file mode 100644 index 000000000..46c7827b4 Binary files /dev/null and b/docs/_static/display/screen/lcd_cmd_colmod.png differ diff --git a/docs/_static/display/screen/lcd_cmd_control.png b/docs/_static/display/screen/lcd_cmd_control.png new file mode 100644 index 000000000..ceac02fb1 Binary files /dev/null and b/docs/_static/display/screen/lcd_cmd_control.png differ diff --git a/docs/_static/display/screen/lcd_connection_i80.png b/docs/_static/display/screen/lcd_connection_i80.png new file mode 100644 index 000000000..06199e537 Binary files /dev/null and b/docs/_static/display/screen/lcd_connection_i80.png differ diff --git a/docs/_static/display/screen/lcd_connection_qspi.png b/docs/_static/display/screen/lcd_connection_qspi.png new file mode 100644 index 000000000..e73a8d4d2 Binary files /dev/null and b/docs/_static/display/screen/lcd_connection_qspi.png differ diff --git a/docs/_static/display/screen/lcd_connection_rgb.png b/docs/_static/display/screen/lcd_connection_rgb.png new file mode 100644 index 000000000..352dc5133 Binary files /dev/null and b/docs/_static/display/screen/lcd_connection_rgb.png differ diff --git a/docs/_static/display/screen/lcd_connection_spi.png b/docs/_static/display/screen/lcd_connection_spi.png new file mode 100644 index 000000000..dbbbabd64 Binary files /dev/null and b/docs/_static/display/screen/lcd_connection_spi.png differ diff --git a/docs/_static/display/screen/lcd_driver_ic.png b/docs/_static/display/screen/lcd_driver_ic.png new file mode 100644 index 000000000..d0c897abb Binary files /dev/null and b/docs/_static/display/screen/lcd_driver_ic.png differ diff --git a/docs/_static/display/screen/lcd_gc9a01_block.png b/docs/_static/display/screen/lcd_gc9a01_block.png new file mode 100644 index 000000000..e480e3228 Binary files /dev/null and b/docs/_static/display/screen/lcd_gc9a01_block.png differ diff --git a/docs/_static/display/screen/lcd_hardware.png b/docs/_static/display/screen/lcd_hardware.png new file mode 100644 index 000000000..886a9c33b Binary files /dev/null and b/docs/_static/display/screen/lcd_hardware.png differ diff --git a/docs/_static/display/screen/lcd_hw_framework_qspi_with_gram.png b/docs/_static/display/screen/lcd_hw_framework_qspi_with_gram.png new file mode 100644 index 000000000..ea4e621da Binary files /dev/null and b/docs/_static/display/screen/lcd_hw_framework_qspi_with_gram.png differ diff --git a/docs/_static/display/screen/lcd_hw_framework_qspi_without_gram.png b/docs/_static/display/screen/lcd_hw_framework_qspi_without_gram.png new file mode 100644 index 000000000..f1a86b5cb Binary files /dev/null and b/docs/_static/display/screen/lcd_hw_framework_qspi_without_gram.png differ diff --git a/docs/_static/display/screen/lcd_hw_framework_rgb.png b/docs/_static/display/screen/lcd_hw_framework_rgb.png new file mode 100644 index 000000000..3b405ed9a Binary files /dev/null and b/docs/_static/display/screen/lcd_hw_framework_rgb.png differ diff --git a/docs/_static/display/screen/lcd_hw_framework_spi_i80.png b/docs/_static/display/screen/lcd_hw_framework_spi_i80.png new file mode 100644 index 000000000..9c217bb8d Binary files /dev/null and b/docs/_static/display/screen/lcd_hw_framework_spi_i80.png differ diff --git a/docs/_static/display/screen/lcd_resolution.png b/docs/_static/display/screen/lcd_resolution.png new file mode 100644 index 000000000..3415aefd6 Binary files /dev/null and b/docs/_static/display/screen/lcd_resolution.png differ diff --git a/docs/_static/display/screen/lcd_rgb_color_port.png b/docs/_static/display/screen/lcd_rgb_color_port.png new file mode 100644 index 000000000..ad27fdacc Binary files /dev/null and b/docs/_static/display/screen/lcd_rgb_color_port.png differ diff --git a/docs/_static/display/screen/lcd_shape_rect.png b/docs/_static/display/screen/lcd_shape_rect.png new file mode 100644 index 000000000..1b9c83130 Binary files /dev/null and b/docs/_static/display/screen/lcd_shape_rect.png differ diff --git a/docs/_static/display/screen/lcd_shape_round.png b/docs/_static/display/screen/lcd_shape_round.png new file mode 100644 index 000000000..6110b8ae7 Binary files /dev/null and b/docs/_static/display/screen/lcd_shape_round.png differ diff --git a/docs/_static/display/screen/lcd_size.png b/docs/_static/display/screen/lcd_size.png new file mode 100644 index 000000000..085beaa14 Binary files /dev/null and b/docs/_static/display/screen/lcd_size.png differ diff --git a/docs/_static/display/screen/lcd_st7701_color_format.png b/docs/_static/display/screen/lcd_st7701_color_format.png new file mode 100644 index 000000000..14d2522a9 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_color_format.png differ diff --git a/docs/_static/display/screen/lcd_st7701_interface_type.png b/docs/_static/display/screen/lcd_st7701_interface_type.png new file mode 100644 index 000000000..e616c191d Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_interface_type.png differ diff --git a/docs/_static/display/screen/lcd_st7701_rgb_de.png b/docs/_static/display/screen/lcd_st7701_rgb_de.png new file mode 100644 index 000000000..cee79ca51 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_rgb_de.png differ diff --git a/docs/_static/display/screen/lcd_st7701_rgb_pin.png b/docs/_static/display/screen/lcd_st7701_rgb_pin.png new file mode 100644 index 000000000..0bb24cd88 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_rgb_pin.png differ diff --git a/docs/_static/display/screen/lcd_st7701_rgb_select.png b/docs/_static/display/screen/lcd_st7701_rgb_select.png new file mode 100644 index 000000000..f448bc0a1 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_rgb_select.png differ diff --git a/docs/_static/display/screen/lcd_st7701_rgb_sync.png b/docs/_static/display/screen/lcd_st7701_rgb_sync.png new file mode 100644 index 000000000..80ce24522 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_rgb_sync.png differ diff --git a/docs/_static/display/screen/lcd_st7701_spi_pin.png b/docs/_static/display/screen/lcd_st7701_spi_pin.png new file mode 100644 index 000000000..89b7c3e7e Binary files /dev/null and b/docs/_static/display/screen/lcd_st7701_spi_pin.png differ diff --git a/docs/_static/display/screen/lcd_st7789_interface.png b/docs/_static/display/screen/lcd_st7789_interface.png new file mode 100644 index 000000000..08c205558 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7789_interface.png differ diff --git a/docs/_static/display/screen/lcd_st7789_spi_3_4-line.png b/docs/_static/display/screen/lcd_st7789_spi_3_4-line.png new file mode 100644 index 000000000..9bcd073c2 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7789_spi_3_4-line.png differ diff --git a/docs/_static/display/screen/lcd_st7789_spi_interface_I_II.png b/docs/_static/display/screen/lcd_st7789_spi_interface_I_II.png new file mode 100644 index 000000000..5f9d7c7e4 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7789_spi_interface_I_II.png differ diff --git a/docs/_static/display/screen/lcd_st7789_spi_pin.png b/docs/_static/display/screen/lcd_st7789_spi_pin.png new file mode 100644 index 000000000..9ad6f7cd7 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7789_spi_pin.png differ diff --git a/docs/_static/display/screen/lcd_st7789_spi_select.png b/docs/_static/display/screen/lcd_st7789_spi_select.png new file mode 100644 index 000000000..b1fff40e7 Binary files /dev/null and b/docs/_static/display/screen/lcd_st7789_spi_select.png differ diff --git a/docs/_static/display/screen/lcd_st77903_color_format.png b/docs/_static/display/screen/lcd_st77903_color_format.png new file mode 100644 index 000000000..3fa85b600 Binary files /dev/null and b/docs/_static/display/screen/lcd_st77903_color_format.png differ diff --git a/docs/_static/display/screen/lcd_st77903_interface_type.png b/docs/_static/display/screen/lcd_st77903_interface_type.png new file mode 100644 index 000000000..8af19b92b Binary files /dev/null and b/docs/_static/display/screen/lcd_st77903_interface_type.png differ diff --git a/docs/_static/display/screen/lcd_sw_framework.png b/docs/_static/display/screen/lcd_sw_framework.png new file mode 100644 index 000000000..509c02f7f Binary files /dev/null and b/docs/_static/display/screen/lcd_sw_framework.png differ diff --git a/docs/_static/display/screen_driver_RGB565.png b/docs/_static/display/screen_driver_RGB565.png deleted file mode 100755 index d193cd7d1..000000000 Binary files a/docs/_static/display/screen_driver_RGB565.png and /dev/null differ diff --git a/docs/_static/display/screen_driver_gray.png b/docs/_static/display/screen_driver_gray.png deleted file mode 100755 index ed2d3df0a..000000000 Binary files a/docs/_static/display/screen_driver_gray.png and /dev/null differ diff --git a/docs/_static/display/screen_driver_mono.png b/docs/_static/display/screen_driver_mono.png deleted file mode 100755 index 35ef5c41a..000000000 Binary files a/docs/_static/display/screen_driver_mono.png and /dev/null differ diff --git a/docs/_static/display/screen_driver_structure.png b/docs/_static/display/screen_driver_structure.png deleted file mode 100644 index 0deb7f3bd..000000000 Binary files a/docs/_static/display/screen_driver_structure.png and /dev/null differ diff --git a/docs/_static/display/screen_offset.png b/docs/_static/display/screen_offset.png deleted file mode 100644 index e7cc44348..000000000 Binary files a/docs/_static/display/screen_offset.png and /dev/null differ diff --git a/docs/_static/display/screen_offset_rotate.png b/docs/_static/display/screen_offset_rotate.png deleted file mode 100644 index b67e30661..000000000 Binary files a/docs/_static/display/screen_offset_rotate.png and /dev/null differ diff --git a/docs/_static/display/swap_xy.png b/docs/_static/display/swap_xy.png deleted file mode 100644 index 2d0806f08..000000000 Binary files a/docs/_static/display/swap_xy.png and /dev/null differ diff --git a/docs/_static/display/swap_xy_mirror_x.png b/docs/_static/display/swap_xy_mirror_x.png deleted file mode 100644 index d11f74b42..000000000 Binary files a/docs/_static/display/swap_xy_mirror_x.png and /dev/null differ diff --git a/docs/_static/display/swap_xy_mirror_xy.png b/docs/_static/display/swap_xy_mirror_xy.png deleted file mode 100644 index 99a4c0a56..000000000 Binary files a/docs/_static/display/swap_xy_mirror_xy.png and /dev/null differ diff --git a/docs/_static/display/swap_xy_mirror_y.png b/docs/_static/display/swap_xy_mirror_y.png deleted file mode 100644 index 0f4454cae..000000000 Binary files a/docs/_static/display/swap_xy_mirror_y.png and /dev/null differ diff --git a/docs/en/display/index.rst b/docs/en/display/index.rst index a6f87ca1a..b069c98cf 100644 --- a/docs/en/display/index.rst +++ b/docs/en/display/index.rst @@ -7,7 +7,7 @@ Display .. toctree:: :maxdepth: 1 - Screen + LCD Screen Digit Tube LED lndicator diff --git a/docs/en/display/lcd/index.rst b/docs/en/display/lcd/index.rst new file mode 100644 index 000000000..4827f1b43 --- /dev/null +++ b/docs/en/display/lcd/index.rst @@ -0,0 +1,12 @@ +LCD Screen +********** + +:link_to_translation:`zh_CN:[中文]` + +.. toctree:: + :maxdepth: 2 + + LCD Introduction + LCD Development Guide + SPI LCD Introduction + RGB LCD Introduction diff --git a/docs/en/display/lcd/lcd_development_guide.rst b/docs/en/display/lcd/lcd_development_guide.rst new file mode 100644 index 000000000..0858d3261 --- /dev/null +++ b/docs/en/display/lcd/lcd_development_guide.rst @@ -0,0 +1,6 @@ +LCD Development Guide +===================== + +:link_to_translation:`zh_CN:[中文]` + +Coming soon... diff --git a/docs/en/display/lcd/lcd_guide.rst b/docs/en/display/lcd/lcd_guide.rst new file mode 100644 index 000000000..b73a8f290 --- /dev/null +++ b/docs/en/display/lcd/lcd_guide.rst @@ -0,0 +1,6 @@ +LCD Introduction +================ + +:link_to_translation:`zh_CN:[中文]` + +Coming soon... diff --git a/docs/en/display/lcd/rgb_lcd.rst b/docs/en/display/lcd/rgb_lcd.rst new file mode 100644 index 000000000..2278f0684 --- /dev/null +++ b/docs/en/display/lcd/rgb_lcd.rst @@ -0,0 +1,6 @@ +RGB LCD Introduction +==================== + +:link_to_translation:`zh_CN:[中文]` + +Coming soon... diff --git a/docs/en/display/lcd/spi_lcd.rst b/docs/en/display/lcd/spi_lcd.rst new file mode 100644 index 000000000..9c7666438 --- /dev/null +++ b/docs/en/display/lcd/spi_lcd.rst @@ -0,0 +1,6 @@ +SPI LCD Introduction +==================== + +:link_to_translation:`zh_CN:[中文]` + +Coming soon... diff --git a/docs/en/display/screen.rst b/docs/en/display/screen.rst deleted file mode 100644 index d59eaa2d1..000000000 --- a/docs/en/display/screen.rst +++ /dev/null @@ -1,275 +0,0 @@ -Screen -=========== -:link_to_translation:`zh_CN:[中文]` - -Screen is a very important display device as many information from various applications needs to be displayed to users. Both ESP32 and ESP32-S2 chips support screens driven by I2C interface, 8080 parallel interface, SPI interface and etc. The supported types of screen controllers are listed in the following table: - -+------------+----------------+------------+ -| Controller | Max Resolution | Type | -+============+================+============+ -| NT35510 | 480 x 865 | Color | -+------------+----------------+------------+ -| ILI9806 | 480 x 865 | Color | -+------------+----------------+------------+ -| RM68120 | 480 x 865 | Color | -+------------+----------------+------------+ -| ILI9486 | 320 x 480 | Color | -+------------+----------------+------------+ -| ILI9341 | 240 x 320 | Color | -+------------+----------------+------------+ -| ST7789 | 240 x 320 | Color | -+------------+----------------+------------+ -| ST7796 | 320 x 480 | Color | -+------------+----------------+------------+ -| SSD1351 | 128 x 128 | Color | -+------------+----------------+------------+ -| SSD1306 | 128 x 64 | Mono | -+------------+----------------+------------+ -| SSD1307 | 128 x 39 | Mono | -+------------+----------------+------------+ -| SSD1322 | 480 x 128 | Gray | -+------------+----------------+------------+ - -.. note:: The 8080 parallel interface is implemented via the LCD mode in the I2S of ESP32, so sometimes it is called ``I2S interface`` in this document. - -Screen Driver Structure ----------------------------------- - -.. figure:: ../../_static/display/screen_driver_structure.png - :align: center - :width: 500px - - Screen Driver Structure Diagram - -In order to be more in line with the actual situation where a screen controller has multiple interfaces, the screen driver is divided into two parts: the ``interface driver`` and the ``controller driver``. - -- The interface driver: conduct basic reads and writes of commands and data -- The controller driver: display information on screen via interfaces - -A controller driver can be designed to switch between different interfaces in hardware level by calling corresponding interface drivers. - -Screen Types -------------------- - -A discussion about screen types will help us to have a clear understanding of drivers. Here, we use colors that can be displayed on the screen to classify screens, rather than the panel material of them such as OLED, LCD and etc. In general, the colors displayed on screen determines the BPP (Bits Per Pixel), and the differences in BPP lead to differences in how the program handles it. Here, we list some ways in which GRAM is mapped to pixel points in below: - -.. figure:: ../../_static/display/screen_driver_RGB565.png - :align: center - :width: 600px - - BPP = 16 GRAM Structure - -.. figure:: ../../_static/display/screen_driver_mono.png - :align: center - :width: 600px - - BPP = 1 GRAM Structure - -.. figure:: ../../_static/display/screen_driver_gray.png - :align: center - :width: 600px - - BPP = 4 GRAM Structure - -From above figures, we can see that there are mainly two types of mapping: - -- When BPP >= 8, it is usually a color screen that supports RGB888, RGB666, RGB565 and other codings. -- When BPP < 8, it is usually a mono screen that may either be black-and-white or gray. - -When BPP < 8, a byte is mapped to multiple pixels, so a single pixel cannot be controlled directly. In this case, :c:func:`draw_pixel` is not supported in the driver, and the parameters of :c:func:`set_window` are also limited. When BPP >= 8, each single pixel can be accessed easily. - - -.. attention:: For color screens, the driver only supports RGB565 color coding. - -Interface Driver ------------------------ - -A screen controller usually has multiple interfaces. On ESP32, three kinds of interfaces as ``8080 parallel interface``, ``SPI`` and ``I2C`` are typically used to connect to the screen. You can choose one of them as the interface when creating interface drivers via :c:func:`scr_interface_create`. - -.. note:: Please remember to select corresponding parameter types when creating different interfaces using :c:func:`scr_interface_create`, e.g., select :cpp:type:`i2s_lcd_config_t` for I2S interface; select :cpp:type:`scr_interface_spi_config_t` for SPI interface. - -To facilitate the use of these interfaces in the driver, all interfaces are defined in :component_file:`display/screen/screen_utility/interface_drv_def.h`, which can be called easily by less parameters. - -.. note:: Most screens use big-endian order to store data, while ESP32 uses small-endian mode. You can switch between them in the interface driver you used, based on ``swap_data`` configurations. **Please note:** when using the SPI interface, the received data **must** be stored in RAM because the IDF's SPI driver itself does not support this swapping function and an additional program in the interface driver will do the work, which require the data to be writable. - -Controller Driver ----------------------- - -Some common functions of the screen are abstracted using :cpp:type:`scr_driver_t` in this section according to display and other functions of different screen controllers, in order to port these common functions to different GUI libraries easily. For some non-generic functions of the screen, you need to call its specific functions. - -Not all screens have implemented these common functions, since different screen controller has their own functions. For example, for screens with BPP < 8, the function :c:func:`draw_pixel` is not supported. And calling an unsupported function will return :cpp:enumerator:`ESP_ERR_NOT_SUPPORTED`. - -Display Direction -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The screen display direction set here is implemented entirely by the screen hardware, and this feature varies from one screen controller to another. There are 8 possible display directions. A display can be rotated by 0°, 90°, 180° or 270° and can also be viewed from the top or bottom, with 0° and top view as its default direction. These 8 (4 × 2) directions can also be represented as a combination of 3 binary switches: X-mirroring, Y-mirroring and X/Y swapping. - -The total 8 combinations of display directions are listed in the following table. If the direction of your display is not correct, please check the configuration switches below to make it work properly. - -================== ====================== ==================== =========================== -|original| 0 |mirror_y| SCR_MIRROR_Y - [SCR_DIR_LRTB] [SCR_DIR_LRBT] ------------------- ---------------------- -------------------- --------------------------- -|mirror_x| SCR_MIRROR_X |mirror_xy| SCR_MIRROR_X| - [SCR_DIR_RLTB] SCR_MIRROR_Y - [SCR_DIR_RLBT] ------------------- ---------------------- -------------------- --------------------------- -|swap_xy| SCR_SWAP_XY |swap_xy_mirror_y| SCR_SWAP_XY| - [SCR_DIR_TBLR] SCR_MIRROR_Y - [SCR_DIR_BTLR] ------------------- ---------------------- -------------------- --------------------------- -|swap_xy_mirror_x| SCR_SWAP_XY| |swap_xy_mirror_xy| SCR_SWAP_XY| - SCR_MIRROR_X SCR_MIRROR_X| - [SCR_DIR_TBRL] SCR_MIRROR_Y - [SCR_DIR_BTRL] -================== ====================== ==================== =========================== - -.. |original| image:: ../../_static/display/original.png - :height: 50px - :width: 100px - -.. |mirror_y| image:: ../../_static/display/mirror_y.png - :height: 50px - :width: 100px -.. |mirror_x| image:: ../../_static/display/mirror_x.png - :height: 50px - :width: 100px -.. |mirror_xy| image:: ../../_static/display/mirror_xy.png - :height: 50px - :width: 100px - -.. |swap_xy| image:: ../../_static/display/swap_xy.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_x| image:: ../../_static/display/swap_xy_mirror_x.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_y| image:: ../../_static/display/swap_xy_mirror_y.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_xy| image:: ../../_static/display/swap_xy_mirror_xy.png - :height: 100px - :width: 50px - -The implementations of display directions are not exactly the same for different screen controllers, and are usually divided into the following cases: - - - For color screens, 8 directions are supported. - - For mono screens, e.g., SSD1306, only the first 4 directions defined in :cpp:type:`scr_dir_t` are supported, which means they do not support X/Y swapping. - -.. note:: - The display direction is also related to the screen panel you used, and you may encounter two types of abnormal cases: - - - The display direction is set to :cpp:enumerator:`SCR_DIR_LRTB`, but the screen does not show as what listed in the above table. This may be because the alignment on the screen panel is mirrored in the X/Y direction, in which case you need to adjust the rotation to get the desired direction. - - After rotated, the screen does not show anything any more. This may be because the resolution of the screen panel is smaller than that of the screen controller, making the display area not falling completely on the screen panel, in which case you need to set a proper offset for the display area. - -Offset of the Display Area -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In some small screens, the resolution of the display area is usually smaller than that of the controller window. Please refer to the following figure: - -.. image:: ../../_static/display/screen_offset.png - :align: center - :width: 350px - -In this figure, ``Controller window`` is the window for screen controller, with its resolution as 240 × 320; ``Panel window`` is the window for screen panel, with its resolution as 135 × 240, which is the display area. From this figure, we can see that the display area is shifted by 52 pixels horizontally and by 40 pixels vertically. - -When the screen is rotated 90° anticlockwise, the display area is shifted by 40 pixels horizontally and by 53 pixels vertically, as shown in the figure below: - -.. image:: ../../_static/display/screen_offset_rotate.png - :align: center - :width: 420px - -The screen controller driver will help you to change the offset value automatically according to the rotation of the screen to maintain a proper display. All you need to do is to properly configure the screen offset and the screen panel size in :cpp:type:`scr_controller_config_t` when it is in ``SCR_DIR_LRTB`` direction. - -.. note:: - - - This only supports screens with BPP >= 8. - - When the resolution of your screen controller is configurable and you find something wrong with the offset, it may be because the selected resolution does not match the actual one, and you should make modifications accordingly, for example, set the ``ILI9806_RESOLUTION_VER`` in ``ili9806.c`` as the actual resolution for ILI9806. - - -Application Example --------------------------- - -.. note:: - - The following examples are no longer maintained. For LCD and LVGL examples, please refer to: `i80_controller `_、 `rgb_panel `_ And `spi_lcd_touch `_ - -Initialize the Screen -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code:: c - - scr_driver_t g_lcd; // A screen driver - esp_err_t ret = ESP_OK; - - /** Initialize 16bit 8080 interface */ - i2s_lcd_config_t i2s_lcd_cfg = { - .data_width = 16, - .pin_data_num = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 - }, - .pin_num_cs = 45, - .pin_num_wr = 34, - .pin_num_rs = 33, - .clk_freq = 20000000, - .i2s_port = I2S_NUM_0, - .buffer_size = 32000, - .swap_data = false, - }; - scr_interface_driver_t *iface_drv; - scr_interface_create(SCREEN_IFACE_8080, &i2s_lcd_cfg, &iface_drv); - - /** Find screen driver for ILI9806 */ - ret = scr_find_driver(SCREEN_CONTROLLER_ILI9806, &g_lcd); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "screen find failed"); - return; - } - - /** Configure screen controller */ - scr_controller_config_t lcd_cfg = { - .interface_drv = iface_drv, - .pin_num_rst = -1, // The reset pin is not connected - .pin_num_bckl = -1, // The backlight pin is not connected - .rst_active_level = 0, - .bckl_active_level = 1, - .offset_hor = 0, - .offset_ver = 0, - .width = 480, - .height = 854, - .rotate = SCR_DIR_LRBT, - }; - - /** Initialize ILI9806 screen */ - g_lcd.init(&lcd_cfg); - -.. note:: - - By default, only the driver of ILI9341 screen is enabled. If you need to use other drivers, please go to ``menuconfig -> Component config -> LCD Drivers -> Select Screen Controller`` to enable the corresponding screen drivers. - -Display Images -^^^^^^^^^^^^^^^^^^^^ - -.. code:: c - - /** Draw a red point at position (10, 20) */ - lcd.draw_pixel(10, 20, COLOR_RED); - - /** Draw a bitmap */ - lcd.draw_bitmap(0, 0, width_of_pic, height_of_pic, pic_data); - -Obtain Screen Information -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code:: c - - scr_info_t lcd_info; - lcd.get_info(&lcd_info); - ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", lcd_info.name, lcd_info.width, lcd_info.height); - -API Reference ------------------ - -.. include-build-file:: inc/screen_driver.inc - -.. include-build-file:: inc/scr_interface_driver.inc diff --git a/docs/zh_CN/display/index.rst b/docs/zh_CN/display/index.rst index 2e4d98afb..ade8713cf 100644 --- a/docs/zh_CN/display/index.rst +++ b/docs/zh_CN/display/index.rst @@ -1,12 +1,11 @@ - 显示 ************************* :link_to_translation:`en:[English]` .. toctree:: - :maxdepth: 1 + :maxdepth: 1 - 显示屏 + LCD 显示屏 数码管 LED 指示灯 diff --git a/docs/zh_CN/display/lcd/index.rst b/docs/zh_CN/display/lcd/index.rst new file mode 100644 index 000000000..85c96351d --- /dev/null +++ b/docs/zh_CN/display/lcd/index.rst @@ -0,0 +1,12 @@ +LCD 显示屏 +*********************** + +:link_to_translation:`en:[English]` + +.. toctree:: + :maxdepth: 2 + + LCD 概述 + LCD 开发指南 + SPI LCD 详解 + RGB LCD 详解 diff --git a/docs/zh_CN/display/lcd/lcd_development_guide.rst b/docs/zh_CN/display/lcd/lcd_development_guide.rst new file mode 100644 index 000000000..3849d0287 --- /dev/null +++ b/docs/zh_CN/display/lcd/lcd_development_guide.rst @@ -0,0 +1,192 @@ +LCD 开发指南 +========================= + +:link_to_translation:`en:[English]` + +本指南主要包含如下内容: + +.. list:: + + - `支持的接口类型`_:乐鑫各系列芯片对不同 LCD 接口的支持情况。 + - `驱动及示例`_:乐鑫提供的 LCD 驱动及示例。 + - `开发框架`_:使用乐鑫芯片开发 LCD 的软硬件框架。 + - `开发步骤`_:使用乐鑫芯片开发 LCD 应用的详细步骤。 + +支持的接口类型 +---------------------------- + +乐鑫芯⽚已经⽀持了 :ref:`LCD 概述 - 驱动接口 ` 一节介绍的全部接⼝类型,各系列 ESP 芯⽚的具体⽀持情况如下: + +.. list-table:: + :widths: 20 20 20 20 20 + :header-rows: 1 + + * - Soc + - SPI(QSPI) + - I80 + - RGB + - MIPI-DSI + * - ESP32 + - |supported| + - + - + - + * - ESP32-C3 + - |supported| + - + - + - + * - ESP32-C6 + - |supported| + - + - + - + * - ESP32-S2 + - |supported| + - |supported| + - + - + * - ESP32-S3 + - |supported| + - |supported| + - |supported| + - + * - ESP32-P4 + - |supported| + - |supported| + - |supported| + - |supported| + +.. |supported| image:: https://img.shields.io/badge/-Supported-green + +.. _LCD_开发指南_驱动及示例: + +驱动及示例 +--------------------- + +**LCD 外设驱动** 位于 **ESP-IDF** 下的 `components/esp_lcd `_ 目录,目前支持 ``I2C``、 ``SPI(QSPI)``、 ``I80`` 以及 ``RGB`` 接口,详细介绍请参考 `文档 `_。下面是乐鑫官方基于 ``esp_lcd`` 移植的 **LCD 驱动组件** : + +.. _lcd_驱动组件: + + - `ESP-IDF `_ 中:st7789、nt35510、ssd1306。 + - `ESP 组件管理器 `_ 中:gc9a01、ili9341、ra8875、sh1107、st7796、st7701、gc9503、gc9b71、spd2010、...(持续更新中) + +**LCD 示例** 位于 **ESP-IDF** 下的 `examples/peripherals/lcd `_ 目录和 **esp-iot-solution** 下的 :project:`examples/display/lcd ` 目录。 + +.. note:: + + #. 推荐基于 ESP-IDF `release/v5.1 `_ 及以上版本分支进行开发,因为低版本不支持部分重要的新特性,尤其是对于 ``RGB`` 接口。 + #. 对于使用 ``3-wire SPI + RGB`` 接口的 LCD,请参考示例 `esp_lcd_st7701 - Example use `_。 + #. 即使 LCD 驱动 IC 的型号相同,不同的屏幕往往需要使用各自厂商提供的初始化命令配置,大部分驱动组件支持在初始化 LCD 设备时传入自定义的初始化命令,若不支持,请参考 `方法 `_ 。 + +开发框架 +------------------------- + +硬件框架 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +对于 SPI/I80 LCD,ESP 可以通过单一的外设接口发送 **命令** 来配置 LCD 以及传输 **局部的色彩数据** 来刷新屏幕。LCD 的驱动 IC 会将接收到的色彩数据存储在 **全屏大小的 GRAM** 内,并按照固定的刷新速率把 **全屏的色彩数据** 显示到面板上,这两个过程是异步进行的。 + +.. figure:: ../../../_static/display/screen/lcd_hw_framework_spi_i80.png + :align: center + :scale: 40% + :alt: 硬件驱动框架示意图 - SPI/I80 LCD + + 硬件驱动框架示意图 - SPI/I80 LCD + +对于大多数 RGB LCD,ESP 需要使用两种不同的接口,一方面通过 ``3-wire SPI`` 接口发送 **命令** 来配置 LCD ,另一方面通过 ``RGB`` 接口传输 **全屏的色彩数据** 来刷新屏幕。由于 LCD 的驱动 IC 没有内置的 GRAM,它会将接收到的色彩数据直接显示到面板上,因此这两个过程是同步进行的。 + +.. figure:: ../../../_static/display/screen/lcd_hw_framework_rgb.png + :align: center + :scale: 40% + :alt: 硬件驱动框架示意图 - RGB LCD + + 硬件驱动框架示意图 - RGB LCD + +通过对比这两种框架可以看出,RGB LCD 相较于 SPI/I80 LCD,不仅需要 ESP 使用两种接口来分别实现传输命令和色彩数据,还要求 ESP 提供全屏大小的 GRAM 来实现屏幕刷新(由于芯片内的 SRAM 的空间比较有限,通常将 GRAM 放在 PSRAM 上)。 + +对于 QSPI LCD,不同型号的驱动 IC 可能需要不同的驱动方式,比如 SPD2010 这款 IC 内置 GRAM,其驱动方式与 SPI/I80 类似,而 ST77903 这款 IC 内部没有 GRAM,其驱动方式与 RGB LCD 类似,但是它们都是通过用单一的外设接口传输命令和色彩数据。 + +.. figure:: ../../../_static/display/screen/lcd_hw_framework_qspi_with_gram.png + :align: center + :scale: 50% + :alt: 硬件驱动框架示意图 - QSPI LCD(有 GRAM) + + 硬件驱动框架示意图 - QSPI LCD(有 GRAM) + +.. figure:: ../../../_static/display/screen/lcd_hw_framework_qspi_without_gram.png + :align: center + :scale: 50% + :alt: 硬件驱动框架示意图 - QSPI LCD(无 GRAM) + + 硬件驱动框架示意图 - QSPI LCD(无 GRAM) + +软件框架 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +软件开发框架主要由 SDK、Driver 和 APP 三个层次组成: + + #. **SDK 层**:ESP-IDF 作为框架的基础部分,不仅包含了驱动 LCD 所需的 ``I2C``、 ``SPI(QSPI)``、 ``I80`` 和 ``RGB`` 等多种外设,还通过 ``esp_lcd`` 组件提供了统一的 APIs 来操作接口和 LCD,如命令及参数的传输,LCD 的图像刷新、反转、镜像等功能。 + #. **Driver 层**:基于 SDK 提供的 APIs 可以实现各种设备驱动,并通过初始化接口设备和 LCD 设备实现 LVGL(GUI 框架)的移植。 + #. **APP 层**:使用 LVGL 提供的 APIs 实现各种 GUI 功能,如显示图片、动画、文字等。 + +.. figure:: ../../../_static/display/screen/lcd_sw_framework.png + :align: center + :scale: 50% + :alt: 软件开发框架示意图 + + 软件开发框架示意图 + +开发步骤 +------------------------- + +初始化接口设备 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +首先,初始化与 LCD 接口对应的外设。然后,创建接口设备并获取其句柄,该句柄的数据类型应为 ``esp_lcd_panel_io_handle_t``。这样即可使用统一的 `接口通用 APIs `_ 进行数据传输。 + +.. note:: + + 对于仅采用 ``RGB`` 接口的 LCD,不需要创建其接口设备,请直接参考 :ref:`LCD 初始化 `。 + +不同类型的 LCD 接口需要使用不同的外设,下面对几种常用接口的设备初始化过程进行说明: + + #. :ref:`SPI LCD 详解 - 初始化接口设备 ` + #. :ref:`RGB LCD 详解 - 初始化接口设备 ` + #. I80 LCD 详解 - 初始化接口设备(待更新) + #. QSPI LCD 详解 - 初始化接口设备(待更新) + +关于这部分更加详细的说明,请参考 `ESP-IDF 编程指南 `_。 + +初始化 LCD 设备 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +由于不同型号的 LCD 驱动 IC 可能具有不同的命令(寄存器)和参数,并且不同的接口类型也可能采用不同的数据格式和驱动方式,首先需要针对特定的接口利用 `接口通用 APIs `_ 来移植目标 LCD 驱动,然后创建 LCD 设备并获取数据类型为 ``esp_lcd_panel_handle_t`` 的句柄,最终使得应用程序能够通过统一的 `LCD 通用 APIs `_ 来操作 LCD 设备。 + +.. note:: + + 对于仅采用 ``RGB`` 接口的 LCD,不需要移植其驱动组件,请直接参考 :ref:`LCD 初始化 ` 。 + +在移植驱动组件前,请先尝试直接从 :ref:`LCD 驱动组件 ` 中获取目标 LCD 驱动 IC 的组件。若该组件不存在,那么也可以基于已有的并且接口类型相同的组件进行移植。不同接口类型的 LCD 驱动可能具有不同的移植原理,下面对几种常用接口的 LCD 驱动组件的移植方法进行说明: + + #. :ref:`SPI LCD 详解 - 移植驱动组件 ` + #. :ref:`RGB LCD 详解 - 移植驱动组件 ` + #. I80 LCD 详解 - 移植驱动组件(待更新) + #. QSPI LCD 详解 - 移植驱动组件(待更新) + +.. _lcd_初始化: + +然后,利用驱动组件就可以实现 LCD 的初始化,下面对几种常用接口的 LCD 初始化进行说明: + + #. :ref:`SPI LCD 详解 - 初始化 LCD 设备 ` + #. :ref:`RGB LCD 详解 - 初始化 LCD 设备 ` + #. I80 LCD 详解 - 初始化 LCD 设备 (待更新) + #. QSPI LCD 详解 - 初始化 LCD 设备 (待更新) + +关于这部分更加详细的说明,请参考 `ESP-IDF 编程指南 `_。 + +移植 LVGL +^^^^^^^^^^^^^^^^^^^^^^^^^ + +设计 GUI +^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/display/lcd/lcd_guide.rst b/docs/zh_CN/display/lcd/lcd_guide.rst new file mode 100644 index 000000000..269c55a09 --- /dev/null +++ b/docs/zh_CN/display/lcd/lcd_guide.rst @@ -0,0 +1,356 @@ +LCD 概述 +=============== + +:link_to_translation:`en:[English]` + +通常所说的 LCD 是 TFT-LCD (薄膜晶体管液晶显示器)的统称。它是⼀种常⻅的数字显示技术,常⽤于显示图像和⽂字。LCD 使⽤液晶材料和偏振光技术,当液晶分⼦受电场影响时,会改变光的偏振⽅向,从⽽控制光线强度,使图像或⽂字显示在屏幕上。 + +.. figure:: ../../../_static/display/screen/lcd_hardware.png + :align: center + :scale: 50% + :alt: TFT-LCD 的硬件框图 + + TFT-LCD 的硬件框图 + +LCD 具有很多优点,例如:能耗低、寿命⻓、可靠性⾼、清晰度⾼、占⽤空间⼩、颜⾊还原度⾼、抗眩光能⼒强等。因此,它已⼴泛应⽤于各种电⼦设备,如家电、便携式设备、可穿戴设备等。同时,LCD 技术持续进步和完善,其中包括不同的面板类型如 IPS、VA、TN,以及新的 LED 背光技术,这些都进一步提高了 LCD 的性能和用户体验。 + +本指南包含如下内容: + +.. list:: + + - `结构`_:LCD 模块的主要结构,主要包含面板、背光源、驱动 IC 和 FPC。 + - `形态`_:LCD 模块的常见形态,主要有矩形屏和圆形屏。 + - `驱动接口`_:LCD 模块的驱动接口,包含 SPI、QSPI、I80、RGB 和 MIPI-DSI。 + - `典型连接方式`_:LCD 模块的典型连接方式,包含 LCD 的通用引脚以及不同类型的接口引脚。 + - `帧率`_:LCD 应用的帧率,包含渲染帧率、接口帧率和屏幕刷新率。 + - `相关文档`_:LCD 相关的文档资料。 + +结构 +--------------- + +为了让 LCD 能够稳定工作并且方便开发,厂商通常将 LCD 封装成一个 **集成的模块** 供用户使用,它主要由以下四个部分组成: + +- **面板**:⾯板决定了 LCD 模块的⾊彩、可视⻆度、分辨率。⾯板的价格⾛势直接影响到模块的价格,⾯板的质量、技术的好坏关系到模块整体性能的⾼低。常⻅的⾯板类型有 IPS、VA、TN 等。 +- **背光源**:液晶分⼦⾃身⽆法发光,因此若想出现画⾯,液晶屏需要专⻔的发光源来提供光线,然后经过液晶分⼦的偏转来产⽣不同的颜⾊。背光源起到的是提供光能的作⽤,⼀般可以通过 PWM 控制它的亮度。 +- **驱动 IC**:驱动 IC 通过特定的接⼝对外通信,并控制输出电压让液晶扭转,使其发⽣⾊阶及明暗的变化。它通常包含控制电路和驱动电路两部分。控制电路负责接收来⾃主控芯⽚的信号,以及图像信号的转换与处理, 驱动电路负责输出图像信号并显示到⾯板上。 +- **FPC**:FPC 是 LCD 模块的对外接⼝,⽤于连接驱动 IC、外部驱动电路与主控芯⽚。FPC 由于其出色的柔性和可靠性,可以解决传统刚性线路板的接触问题和较差的抗振动性,从而增强了模块的稳定性和使用寿命。 + +通常,LCD 模块的选型主要基于其 **面板** 和 **驱动 IC**。例如,我们会考虑面板的类型和分辨率以及驱动 IC 支持的接口类型和色彩格式。驱动 IC 体积很小,通常被贴在 FPC 与面板的连接部位,如图示。 + +.. figure:: ../../../_static/display/screen/lcd_driver_ic.png + :align: center + :scale: 50% + :alt: LCD 模块的驱动 IC + + LCD 模块的驱动 IC + +形态 +--------------- + +对于 LCD 的面板外形,大多数形状都是采用矩形或圆形,生活中最常见到的就是矩形屏,圆形屏多为小尺寸屏幕。 + +.. figure:: ../../../_static/display/screen/lcd_shape_rect.png + :align: center + :scale: 40% + :alt: LCD 矩形屏 + + LCD 矩形屏 + +.. figure:: ../../../_static/display/screen/lcd_shape_round.png + :align: center + :scale: 25% + :alt: LCD 圆形屏 + + LCD 圆形屏 + +它们的特点及应用场景如下: + +.. list-table:: + :widths: 10 30 30 + :header-rows: 1 + + * - 类型 + - 特点 + - 应用场景 + * - 矩形屏 + - ⾯积⼤、效果好、信息呈现更多,应⽤范围更⼴ + - 手机、平板电脑、控制面板 + * - 圆形屏 + - 时尚轻便、占⽤空间⼩,有效利⽤设备⾯积 + - 智能穿戴、电动⻋仪表盘、汽⻋显示仪表、智能家电、智能⼿持设备 + +通常使用 LCD 面板的对角线长度来衡量其 **尺寸** 的大小,单位是英寸或寸,比如常说的 1.28 寸屏和 3.5 寸屏。除了屏幕的物理尺寸,开发者往往更加关心屏幕的 **分辨率**,它是指面板所能显示的像素点数量,代表了屏幕图像的精密度:可显示的像素越多,画面就越精细,同样的屏幕区域内能显示的信息越多,对主控芯片的性能要求也越高,所以分辨率是个非常重要的参数指标。 + +.. figure:: ../../../_static/display/screen/lcd_size.png + :align: center + :scale: 25% + :alt: 屏幕尺寸 + + 屏幕尺寸 + +.. figure:: ../../../_static/display/screen/lcd_resolution.png + :align: center + :scale: 25% + :alt: 屏幕分辨率 + + 屏幕分辨率 + +尺寸与分辨率之间不是一一对应的关系,但是总体呈正比的趋势,比如,一般情况下,2.4 寸或者 2.8 寸的屏幕常见分辨率为 320x240,3.2 寸或 3.5 寸的屏幕常见分辨率为 320x480。尺寸大的屏幕,其分辨率不一定会比更小尺寸的屏幕更高,因此,在进行屏幕选型前,需要根据应用场景和需求确定好屏幕的尺寸与分辨率。 + +.. _LCD_概述_驱动接口: + +驱动接口 +--------------- + +对于开发者而言,通常更加关心 LCD 的驱动接口,目前在物联网领域比较常见的接口类型有 ``SPI``、 ``QSPI``、 ``I80``、 ``RGB`` 和 ``MIPI-DSI``,它们在 ``占用 IO 数量``、 ``并行数据位数``、 ``数据传输带宽``、 ``显存(GRAM)位置`` 等方面的参数对比如下: + +参数对比 +^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: 10 75 5 5 5 10 + :header-rows: 1 + + * - 类型 + - 描述 + - 占用 IO 数量 + - 并行数据位数 + - 数据传输带宽 + - GRAM 位置 + * - SPI + - 串行接口,以 SPI 总线协议为基础,通常采用 4 线或 3 线模式 + - 最少 + - 1 + - 最小 + - LCD + * - QSPI(Quad-SPI) + - SPI 接口的一种扩展,可以使用 4 根数据线并行传输 + - 较少 + - 4 + - 较小 + - LCD 或主控 + * - I80(MCU、DBI) + - 并行接口,以 I80 总线协议为基础 + - 较多 + - 8/16 + - 较大 + - LCD + * - RGB(DPI) + - 并行接口,一般需搭配 3-wire SPI 接口 + - 最多 + - 8/16/18/24 + - 较大 + - 主控 + * - MIPI-DSI + - 采⽤差分信号传输⽅式的串⾏接⼝,基于 MIPI 的⾼速、低功率可扩展串⾏互联的 D-PHY 物理层规范 + - 较多 + - 4/6 + - 最大 + - LCD 或主控 + +.. note:: + + 1. 对于 ``QSPI`` 接口,不同型号的驱动 IC 可能采用不同的驱动方式,如 *SPD2010* 内置 GRAM,其驱动方式与 ``SPI/I80`` 接口类似,而 *ST77903* 没有内置 GRAM,其驱动方式与 ``RGB`` 接口类似。 + 2. 对于 ``MIPI-DSI`` 接口,采用 Command 模式需要 LCD 内置 GRAM,而 Video 模式则不需要。 + +总结如下: + +1. ``SPI`` 接口的数据传输带宽小,比较适用于低分辨率的屏幕。 +2. ``QSPI`` 和 ``I80`` 接口的数据传输带宽更大,所以能够支持较高分辨率的屏幕,但是 ``I80`` 接口要求 LCD 内置 GRAM,导致屏幕成本较高,并且难以做到大屏。 +3. ``RGB`` 与 ``I80`` 接口类似,但是 ``RGB`` 接口无需 LCD 内置 GRAM,因此适用于更高分辨率的屏幕。 +4. ``MIPI-DSI`` 接口适用于高分辨率、高刷新率的屏幕。 + +接口详解 +^^^^^^^^^^^^^^^ + +驱动 LCD 的第一步是确定它的接口类型,对于大部分常见的驱动 IC,如 *ST7789*、 *GC9A01*、 *ILI9341* 等,它们一般都会支持多种接口,但是屏幕厂商在封装成模块的时候通常只对外留出其中一种接口(RGB LCD 通常会也会使用 SPI 接口,参考 `资料 `_)。以 *GC9A01* 为例,它的硬件框图如下: + +.. figure:: ../../../_static/display/screen/lcd_gc9a01_block.png + :align: center + :scale: 50% + :alt: GC9A01 的硬件框图 + + GC9A01 的硬件框图 + +很多 LCD 驱动 IC 的实际接口类型是由其 ``IM[3:0]`` 引脚的高低电平来决定的,大部分屏幕在内部已经固定了这些引脚的配置,但是也有一些屏幕会预留出这些引脚以及所有的接口引脚,这种情况下用户可以自行配置。以 *ST7789* 为例,它的接口类型配置如下: + +.. figure:: ../../../_static/display/screen/lcd_st7789_interface.png + :align: center + :scale: 50% + :alt: ST7789 的驱动接口配置 + + ST7789 的接口配置 + +因此,仅仅知道驱动 IC 的型号并不能确定屏幕的接口类型,在这种情况下可以咨询屏幕厂商,或者查阅屏幕的数据手册,也可以通过原理图结合经验进行判断,下面是各种接口的屏幕引脚对比: + +.. list-table:: + :widths: 15 85 + :header-rows: 1 + + * - 类型 + - 引脚 + * - LCD 通用 + - RST(RESET)、Backlight(LEDA、LEDK)、TE(tear effect)、Power(VCC、GND) + * - SPI + - CS、SCK(SCL)、SDA(MOSI)、SDO(MISO)、DC(RS) + * - QSPI + - CS、SCK(SCL)、SDA(DATA0)、DATA1、DATA2、DATA3 + * - I80 + - CS(CSX)、RD(RDX)、WR(WRX)、DC(D/CX)、D[15:0](D[7:0]) + * - RGB + - CS、SCK(SCL)、SDA(MOSI)、HSYNC、VSYNC、PCLK、DE、D[23:0](D[17:0]/D[7:0]) + +常用接口 LCD 的详细介绍如下: + +.. list:: + + - :doc:`./spi_lcd` + - :doc:`./rgb_lcd` + +典型连接方式 +---------------------- + +对于通用的 LCD 引脚,通常采用如下的连接方式: + +1. **RST(RESET)**:推荐连接至 GPIO,并根据 LCD 驱动 IC 的数据手册,在上电时输出复位时序。一般情况下也可以使用上拉/下拉电阻连接系统电源。 +2. **Backlight(LEDA、LEDK)**:推荐 LEDA 连接至系统电源,LEDK 使用开关元器件连接至系统电源,并通过 GPIO 控制亮灭,或者通过 LEDC 外设输出 PWM 以调节背光亮度。 +3. **TE(tear effect)**:推荐连接至 GPIO,通过 GPIO 中断来获取 TE 信号,以实现帧同步。 +4. **Power(VCC、GND)**:推荐全部连接至对应的系统电源,而不要让一部分引脚浮空。 + +对于不同接口类型的引脚,主控 MCU 需要采用不同的连接方式,下面将分别介绍 ``SPI`` ``QSPI`` ``I80`` 和 ``RGB`` 四种接口的典型连接方式。 + +SPI 接口 +^^^^^^^^^^^^^^^ + +``SPI`` 接口的 LCD 硬件设计请参考开发板 `ESP32-C3-LCDkit `_ 及其 `LCD 子板 `__,其典型连接示意图如下: + +.. figure:: ../../../_static/display/screen/lcd_connection_spi.png + :align: center + :scale: 50% + :alt: SPI 接口典型连接示意图 + + SPI 接口典型连接示意图 + +.. note:: + + 1. 由于 ``3-line 模式`` (无 D/C 信号线)下,每传输单位数据(通常为字节)都需要先传输 D/C 信号(1-bit),而目前 ESP 的 SPI 外设不支持直接传输 9-bit 数据,因此通常采用上图所示的 ``4-line 模式`` 。 + 2. ``Interface II 模式``需要使用 ``MISO & MOSI`` 两根数据线。 + 3. ``Interface I 模式``仅需使用 ``SDA`` 一根数据线。 + +QSPI 接口 +^^^^^^^^^^^^^^^ + +``QSPI`` 接口的典型连接示意图如下: + +.. figure:: ../../../_static/display/screen/lcd_connection_qspi.png + :align: center + :scale: 50% + :alt: QSPI 接口典型连接示意图 + + QSPI 接口典型连接示意图 + +.. note:: + + 1. 不同型号驱动 IC 的 ``QSPI`` 接口连接方式可能不同,上图仅以 *ST77903* 为例。 + 2. 写入数据时需要使用 ``SDA0`` 和 ``SDA[1:3]`` 四根数据线。 + 3. 读取数据时仅使用 ``SDA0`` 一根数据线。 + +I80 接口 +^^^^^^^^^^^^^^^ + +``I80`` 接口的 LCD 硬件设计请参考开发板 `ESP32-S3-LCD-EV-Board `_ 及其 `LCD 子板 `__ (3.5' LCD_ZJY),其典型连接示意图如下: + +.. figure:: ../../../_static/display/screen/lcd_connection_i80.png + :align: center + :scale: 50% + :alt: I80 接口典型连接示意图 + + I80 接口典型连接示意图 + +.. note:: + + 1. 图中虚线表示可选引脚。 + 2. ESP 的 I80 外设不支持使用 ``RD`` 信号进行读取操作,因此实际连接时需要将该信号拉高。 + +RGB 接口 +^^^^^^^^^^^^^^^ + +``RGB`` 接口的 LCD 硬件设计请参考开发板 `ESP32-S3-LCD-EV-Board `_ 及其 `LCD 子板 `__ (3.95' LCD_QMZX),其典型连接示意图如下: + +.. figure:: ../../../_static/display/screen/lcd_connection_rgb.png + :align: center + :scale: 50% + :alt: RGB 接口典型连接示意图 + + RGB 接口典型连接示意图 + +.. note:: + + 1. 图中虚线表示可选引脚。 + 2. ``DE`` 用于 DE 模式下。 + 3. ``CS``、 ``SCK`` 和 ``SDA`` 为 3-wire(3-line) SPI 接口引脚,用于发送命令及参数对 LCD 进行配置,一些屏幕可能没有这些引脚,因此也不需要进行初始化配置。由于 ``3-wire SPI`` 接口可以仅用于进行 LCD 的初始化,而无需用于后续的屏幕刷新,因此,为了节省 IO 数量,可以将 ``SCK`` 和 ``SDA`` 与任意 ``RGB`` 接口引脚进行复用。 + +帧率 +--------------- + +对于 LCD 应用来说,屏幕上的动画是通过显示多个连续的静止图像来实现的,这些图像被称为 **帧**。 **帧率** 就是显示新帧的速率,它通常表示为每秒变化的帧数,简称为 FPS。帧率越高,每秒显示的帧就越多,动画变化得也更平滑、更逼真。 + +但是一帧图像的显示并不是仅由主控一次性完成的,而是经过渲染、传输、显示等多个步骤,因此,帧率的高低不仅取决于主控的性能,还取决于 LCD 的接口类型和刷新率等因素。 + +渲染 +^^^^^^^^^^^^^^^ + +渲染是指主控通过计算生成图像数据的过程,其快慢可以用 **渲染帧率** 来衡量。 + +渲染帧率一方面取决于主控的性能,另一方面也受动画复杂程度的影响,比如,局部变化的动画通常比全屏变化的动画渲染帧率更高,纯色填充通常图层混叠的渲染帧率更高。因此,渲染帧率在图像变化时一般是不固定的,如 LVGL 运行时统计的 FPS。 + +.. figure:: https://dl.espressif.com/AE/esp-iot-solution/lcd_fps_lvgl.gif + :height: 504 px + :width: 453 px + :align: center + :alt: LVGL 运行时统计的 FPS + + LVGL 运行时统计的 FPS + +传输 +^^^^^^^^^^^^^^^ + +传输是指主控将渲染好的图像数据通过外设接口传输到 LCD 驱动 IC 的过程,其快慢可以用 **接口帧率** 来衡量。 + +接口帧率取决于 LCD 的接口类型和主控的数据传输带宽,通常在外设接口初始化完成后就会固定,因此可以通过公式计算得出: + +.. math:: + + 接口帧率 = \frac{接口的数据传输带宽}{一帧图像的数据大小} + +**对于 SPI/I80 接口**: + +.. math:: + + 接口帧率 = \frac{时钟频率 \times 数据线位数}{色彩位数 \times 水平分辨率 \times 垂直分辨率} + +**对于 RGB 接口**: + +.. math:: + + 接口帧率 = \frac{时钟频率 \times 数据线位数}{色彩位数 \times 水平周期 \times 垂直周期} + + 水平周期 = 水平脉冲宽度 + 水平后廊 + 水平分辨率 + 水平前廊 + + 垂直周期 = 垂直脉冲宽度 + 垂直后廊 + 垂直分辨率 + 垂直前廊 + +显示 +^^^^^^^^^^^^^^^ + +显示是指 LCD 的驱动 IC 将接收到的图像数据显示到屏幕上的过程,其快慢可以用 **屏幕刷新率** 来衡量。 + +对于 SPI/I80 接口的 LCD,屏幕刷新率是由 LCD 驱动 IC 决定的,一般可以通过发送特定的命令来设置,如 *ST7789* 的 ``FRCTRL2(C6h)`` 命令;对于 RGB 接口的 LCD,屏幕刷新率是由主控决定的,其等价于接口帧率。 + +相关文档 +--------------------- + +- `I80(MCU)接口 与 RGB 接口 `_ +- `串行接口与并行接口 `_ +- `MIPI-DSI 接口 `_ +- `常见 LCD 驱动 IC 的数据手册 `_ +- `其他 LCD 文档资源 `_ diff --git a/docs/zh_CN/display/lcd/rgb_lcd.rst b/docs/zh_CN/display/lcd/rgb_lcd.rst new file mode 100644 index 000000000..873094fdd --- /dev/null +++ b/docs/zh_CN/display/lcd/rgb_lcd.rst @@ -0,0 +1,469 @@ +RGB LCD 详解 +=========================== + +:link_to_translation:`en:[English]` + +.. contents:: 目录 + :local: + :depth: 2 + +接口模式 +--------------------- + +大多数 RGB LCD 采用 ``SPI + RGB`` 接口,它们需要通过 ``SPI`` 接口发送命令对 LCD 进行初始化,也可以在初始化后根据需要动态修改相关配置,如垂直/水平镜像,更具灵活性。一些 RGB LCD 仅采用 ``RGB`` 接口,它们无需发送命令对 LCD 进行初始化,但也无法修改任何配置,驱动方法更加简单。下图为 *ST7701S* 的接口类型选择: + +.. figure:: ../../../_static/display/screen/lcd_st7701_interface_type.png + :align: center + :scale: 80% + :alt: ST7701S 的接口类型选择 + + ST7701S 的接口类型选择 + +从上图中可以看出, *ST7701S* 是通过 ``IM[3:0]`` 引脚来选择 ``SPI + RGB`` 接口的配置。通常来说,这类 LCD 会选择 ``3-wire SPI + RGB`` 的接口类型,对应于上图中的 ``RGB+9b_SPI(rise/fall)``,其中, ``9b_SPI`` 表示 ``SPI`` 接口的 :ref:`3-line 模式 ` (一般称为 ``3-wire``), ``rise/fall`` 表示 ``SCL`` 信号的有效边沿, ``rise`` 表示上升沿有效(SPI 模式 0/3), ``fall`` 表示下降沿(SPI 模式 1/2)。 + +下图为 *ST7701S* 的 ``SPI`` 和 ``RGB`` 接口的引脚描述: + +.. figure:: ../../../_static/display/screen/lcd_st7701_spi_pin.png + :align: center + :scale: 80% + :alt: ST7701S SPI 接口的引脚描述 + + ST7701S SPI 接口的引脚描述 + +.. figure:: ../../../_static/display/screen/lcd_st7701_rgb_pin.png + :align: center + :scale: 60% + :alt: ST7701S RGB 接口的引脚描述 + + ST7701S RGB 接口的引脚描述 + +对于采用 ``SPI + RGB`` 接口的 LCD,一般可以通过命令配置 ``RGB`` 接口为 ``DE 模式`` 或者 ``SYNC 模式``,下面以 *ST7701S* 为例介绍这两种模式。 + +模式选择 +^^^^^^^^^^^^^^^^ + +.. figure:: ../../../_static/display/screen/lcd_st7701_rgb_select.png + :align: center + :scale: 60% + :alt: ST7701S RGB 接口的模式选择 + + ST7701S RGB 接口的模式选择 + +从图中可以看出, *ST7701S* 可以通过命令 ``C3h`` 配置 RGB 的模式。需注意,不同型号的 LCD 驱动 IC 可能使用不同的命令,如 *GC9503* 是通过命令 ``B0h`` 进行配置的。 + +DE 模式 +^^^^^^^^^^^^^^^^ + +.. figure:: ../../../_static/display/screen/lcd_st7701_rgb_de.png + :align: center + :scale: 50% + :alt: ST7701S DE 模式的时序图 + + ST7701S DE 模式的时序图 + +SYNC 模式 +^^^^^^^^^^^^^^^^ + +.. figure:: ../../../_static/display/screen/lcd_st7701_rgb_sync.png + :align: center + :scale: 50% + :alt: ST7701S SYNC 模式的时序图 + + ST7701S SYNC 模式的时序图 + +模式对比 +^^^^^^^^^^^^^^^^ + +通过对比 ``DE 模式`` 和 ``SYNC 模式`` 的时序图,可以看出它们的主要区别在于是否使用 DE 信号线以及对于消隐区域(Blanking Porch)的配置要求,总结为下表: + +.. list-table:: + :widths: 20 30 50 10 + :header-rows: 1 + + * - 模式 + - 是否使用 DE 信号线 + - 是否配置消隐区域寄存器 + - ESP 是否支持 + * - DE 模式 + - 是 + - 否 + - 是 + * - SYNC 模式 + - 否 + - 是 + - 是 + +色彩格式 +--------------------- + +大多数 RGB LCD 支持多种色彩(输入数据)格式,包括 ``RGB565`` 、 ``RGB666`` 、 ``RGB888`` 等,通常可以使用 ``COLMOD(3Ah)`` 命令来配置。下图为 *ST7701S* 的色彩格式配置: + +.. figure:: ../../../_static/display/screen/lcd_st7701_color_format.png + :align: center + :scale: 80% + :alt: ST7701S 的色彩格式配置 + + ST7701S 的色彩格式配置 + +从上图可以看出, *ST7701S* 支持 ``16-bit RGB565`` 、 ``18-bit RGB666`` 、 ``24-bit RGB888`` 三种色彩格式,其中 ``N-bit`` 表示接口的数据线位数,并且是通过 ``COLMOD(3Ah):VIPF[2:0]`` 和 ``COLCTRL(CDh):MDT`` 命令来进行选择。 **需注意,命令配置需要与硬件接口保持一致** ,例如 LCD 模块仅提供了 18-bit 的数据线,那么软件一定不能配置色彩格式为 ``24-bit RGB888`` ,并且在此情况下只有在数据线为 ``D[21:16],D[13:8],D[5:0]`` 时才能配置为 ``16-bit RGB565``。 + +**除此之外,色彩格式的位数并不等于接口的有效数据线位数** ,下图为 *ST77903* 的接口类型选择和色彩格式配置: + +.. figure:: ../../../_static/display/screen/lcd_st77903_interface_type.png + :align: center + :scale: 70% + :alt: ST77903 RGB 接口的类型选择 + + ST77903 RGB 接口的类型选择 + +.. figure:: ../../../_static/display/screen/lcd_st77903_color_format.png + :align: center + :scale: 100% + :alt: ST77903 的色彩格式配置 + + ST77903 的色彩格式配置 + +从上图可以看出, *ST77903* 支持 ``6-bit RGB565`` 、 ``6-bit RGB666`` 和 ``8-bit RGB888`` 三种色彩格式,而它们的位数分别为 ``16-bit`` 、 ``18-bit`` 和 ``24-bit`` 。多数 LCD 的 ``RGB`` 接口仅需一个时钟周期即可并行传输单个像素的色彩数据,而像 ST77903 这类 LCD 接口则需要多个时钟周期传输单个像素的色彩数据,所以这类接口也被称为 **串行 RGB 接口** (SRGB)。 + +.. note:: + + 虽然 ESP32-S3 仅支持 ``16-bit RGB565`` 和 ``8-bit RGB888`` 两种色彩格式,但是通过特殊的硬件连接方式可以使其驱动支持 ``18-bit RGB666`` 或 ``24-bit RGB888`` 色彩格式的 LCD ,连接方式请参考开发板 `ESP32-S3-LCD-EV-Board `_ 的 `LCD 子板 2 `_ (3.95' LCD_QMZX) 和 `LCD 子板 3 `_ 原理图。 + +.. _rgb_初始化接口设备: + +初始化接口设备 +--------------------------- + +**对于仅采用 RGB 接口的 LCD** ,因为它们不支持传输命令及参数,所以这里不需要初始化接口设备,请直接参考 :ref:`初始化 LCD 设备 `。 + +**对于采用 3-wire SPI 和 RGB 接口的 LCD** ,这里仅需创建 ``3-wire SPI`` 接口设备。由于 ESP 的 SPI 外设不支持直接传输 9-bit 数据,并且该接口仅用于传输数据量较小的命令及参数,而且对于数据传输的带宽以及时序要求不高,因此可以使用 GPIO 或者 IO 扩展芯片引脚 (如 `TCA9554 `_ ) 通过软件模拟 SPI 协议的方式来实现。下面是使用 `esp_lcd_panel_io_additions `_ 组件来创建 ``3-wire SPI`` 接口设备的代码说明: + +.. code-block:: c + + #include "esp_check.h" // 依赖的头文件 + #include "esp_lcd_panel_io.h" + #include "esp_lcd_panel_io_additions.h" + + esp_lcd_panel_io_3wire_spi_config_t io_config = { + .line_config = { + .cs_io_type = IO_TYPE_GPIO, // 设置为 `IO_TYPE_EXPANDER` 表示使用 IO 扩展芯片的引脚,否则使用 GPIO + .cs_gpio_num = EXAMPLE_LCD_IO_SPI_CS, // 连接 LCD CS 信号的 GPIO 编号 + // .cs_expander_pin = EXAMPLE_LCD_IO_SPI_CS, // 连接 LCD CS 信号的扩展 IO 芯片引脚编号 + .scl_io_type = IO_TYPE_GPIO, // 设置为 `IO_TYPE_EXPANDER` 表示使用 IO 扩展芯片的引脚,否则使用 GPIO + .scl_gpio_num = EXAMPLE_LCD_IO_SPI_SCK, // 连接 LCD SCK(SCL)信号的 GPIO 编号 + // .scl_expander_pin = EXAMPLE_LCD_IO_SPI_SCK, // 连接 LCD SCK(SCL)信号的扩展 IO 芯片引脚编号 + .sda_io_type = IO_TYPE_GPIO, // 设置为 `IO_TYPE_EXPANDER` 表示使用 IO 扩展芯片的引脚,否则使用 GPIO + .sda_gpio_num = EXAMPLE_LCD_IO_SPI_SDO, // 连接 LCD MOSI(SDO、SDA) 信号的 GPIO 编号 + // .sda_expander_pin = EXAMPLE_LCD_IO_SPI_SDO, // 连接 LCD MOSI(SDO、SDA) 信号的扩展 IO 芯片引脚编号 + .io_expander = NULL, // 若使用 IO 扩展芯片的引脚,则需要传入已经初始化好的设备句柄 + }, + .expect_clk_speed = PANEL_IO_3WIRE_SPI_CLK_MAX, // 期望的 SPI 时钟频率,由于采用软件模拟的方式,实际可能有较大误差, + // 默认设为 `PANEL_IO_3WIRE_SPI_CLK_MAX` 即可 + .spi_mode = 0, // SPI 模式(0-3),需根据 LCD 驱动 IC 的数据手册以及硬件的配置确定(如 IM[3:0]) + .lcd_cmd_bytes = 1, // 单位 LCD 命令的字节数(1-4),通常设为 `1` 即可 + .lcd_param_bytes = 1, // 单位 LCD 参数的字节数(1-4),通常设为 `1` 即可 + .flags = { + .use_dc_bit = 1, // 默认设为 `1` 即可 + .del_keep_cs_inactive = 1, // 默认设为 `1` 即可 + }, + } + esp_lcd_panel_io_handle_t io_handle = NULL; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_3wire_spi(&io_config, &io_handle)); + +通过创建接口设备可以获取数据类型为 ``esp_lcd_panel_io_handle_t`` 的句柄,然后能够使用 ``esp_lcd_panel_io_tx_param()`` 给 LCD 的驱动 IC 发送 **命令** 。 + +.. _rgb_移植驱动组件: + +移植驱动组件 +--------------------------- + +**对于仅采用 RGB 接口的 LCD** ,由于 `RGB 接口驱动 `_ 中已经通过注册回调函数的方式实现了结构体 `esp_lcd_panel_t `_ 中的各项功能,并且提供了函数 ``esp_lcd_new_rgb_panel()`` 用于创建数据类型为 ``esp_lcd_panel_handle_t`` 的 LCD 设备,使得应用程序能够使用 `LCD 通用 APIs `_ 来操作 LCD 设备。因此,这种 LCD 不需要移植驱动组件,请直接参考 :ref:`初始化 LCD 设备 `。 + +**对于采用 3-wire SPI 和 RGB 接口的 LCD** ,在上述 `RGB 接口驱动 `_ 的基础上,还需要通过 ``3-wire SPI`` 接口发送命令及参数。因此,实现这种 LCD 驱动组件的基本原理包含以下三点: + + #. 基于数据类型为 ``esp_lcd_panel_io_handle_t`` 的接口设备发送指定格式的命令及参数。 + #. 使用函数 ``esp_lcd_new_rgb_panel()`` 创建一个 LCD 设备,然后通过注册回调函数的方式 **保存和覆盖** 该设备中的 **部分** 功能。 + #. 实现一个函数用于提供数据类型为 ``esp_lcd_panel_handle_t`` 的 LCD 设备句柄,使得应用程序能够利用 `LCD 通用 APIs `_ 来操作 LCD 设备。 + +下面是 ``esp_lcd_panel_handle_t`` 各项功能的实现说明以及和 `RGB 接口驱动 `_ 还有 `LCD 通用 APIs `_ 的对应关系: + +.. list-table:: + :widths: 10 20 20 50 + :header-rows: 1 + + * - 功能 + - RGB 接口驱动 + - LCD 通用 APIs + - 实现说明 + * - reset() + - rgb_panel_reset() + - esp_lcd_panel_reset() + - 若设备连接了复位引脚,则通过该引脚进行硬件复位,否则通过命令 ``LCD_CMD_SWRESET(01h)`` 进行软件复位,最后使用 ``rgb_panel_reset()`` 复位 ``RGB`` 接口。 + * - init() + - rgb_panel_init() + - esp_lcd_panel_init() + - 若 ``3-wire SPI`` 接口没有与 ``RGB`` 接口复用引脚,则通过发送一系列的命令及参数来初始化 LCD 设备,否则需要提前在 LCD 创建时进行初始化,最后使用 ``rgb_panel_init()`` 初始化 ``RGB`` 接口。 + * - del() + - rgb_panel_del() + - esp_lcd_panel_del() + - 释放驱动占用的资源,包括申请的存储空间和使用的 IO,还要使用 ``rgb_panel_del()`` 删除 ``RGB`` 接口。 + * - draw_bitmap() + - rgb_panel_draw_bitmap() + - esp_lcd_panel_draw_bitmap() + - 无需保存和覆盖,使用 ``rgb_panel_draw_bitmap()`` 发送图像数据。 + * - mirror() + - rgb_panel_mirror() + - esp_lcd_panel_mirror() + - 根据用户配置,既可以通过命令,也可以使用 ``rgb_panel_mirror()`` 通过软件实现镜像 X 轴和 Y 轴。 + * - swap_xy() + - rgb_panel_swap_xy() + - esp_lcd_panel_mirror() + - 无需保存和覆盖,使用 ``rgb_panel_swap_xy()`` 通过软件实现交换 X 轴和 Y 轴。 + * - set_gap() + - rgb_panel_set_gap() + - esp_lcd_panel_mirror() + - 无需保存和覆盖,使用 ``rgb_panel_set_gap()`` 通过软件修改画图时的起始和终止坐标,从而实现画图的偏移。 + * - invert_color() + - rgb_panel_invert_color() + - esp_lcd_panel_mirror() + - 无需保存和覆盖,使用 ``rgb_panel_invert_color()`` 通过硬件实现像素的色彩数据按位取反(0xF0F0 -> 0x0F0F)。 + * - disp_on_off() + - rgb_panel_disp_on_off() + - esp_lcd_panel_mirror() + - 根据用户配置来实现 LCD 显示的开关。如果没有配置 ``disp_gpio_num``,则可以通过 LCD 命令 ``LCD_CMD_DISON(29h)`` 和 ``LCD_CMD_DISOFF(28h)`` 来进行控制。另外,如果配置了 ``disp_gpio_num``,则可以通过调用函数 ``rgb_panel_disp_on_off()`` 来实现控制。 + +对于大多数 RGB LCD,其驱动 IC 的命令及参数与上述实现说明中的兼容,因此可以通过以下步骤完成移植: + + #. 在 :ref:`LCD 驱动组件 ` 中选择一个型号相似的 RGB LCD 驱动组件。 + #. 通过查阅目标 LCD 驱动 IC 的数据手册,确认其与所选组件中各功能使用到的命令及参数是否一致,若不一致则需要修改相关代码。 + #. 即使 LCD 驱动 IC 的型号相同,不同制造商的屏幕也通常需要使用各自提供的初始化命令配置。因此,需要修改初始化函数 ``init()`` 中发送的命令和参数。这些初始化命令通常以特定的格式存储在一个静态数组中。此外,需要注意不要在初始化命令中包含由驱动 IC 控制的命令,例如 ``LCD_CMD_COLMOD(3Ah)``,以确保成功初始化 LCD 设备。 + #. 可使用编辑器的字符搜索和替换功能,将组件中的 LCD 驱动 IC 名称替换为目标名称,如将 ``gc9503`` 替换为 ``st7701``。 + +.. _rgb_初始化_lcd: + +初始化 LCD 设备 +--------------------------- + +**对于采用 3-wire SPI 和 RGB 接口的 LCD** ,首先通过 `RGB 接口驱动 `_ 中的 ``esp_lcd_new_rgb_panel()`` 函数创建 LCD 设备并获取数据类型为 ``esp_lcd_panel_handle_t`` 的句柄,然后使用 `LCD 通用 APIs `_ 来初始化 LCD 设备,下面是以 ESP-IDF release/v5.1 中 `rgb_panel `_ 为例的代码说明: + +.. code-block:: c + + #include "esp_check.h" // 依赖的头文件 + #include "esp_lcd_panel_ops.h" + #include "esp_lcd_panel_rgb.h" + + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_rgb_panel_config_t panel_config = { // RGB 接口的配置参数 + .data_width = EXAMPLE_LCD_DATA_WIDTH, // RGB 接口的数据线位数,如 `16-bit RGB565`: 16,`8-bit RGB888`:8 + .bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // 色彩格式的位数,可能与 RGB 接口的数据线位数不相等, + // 如 `16-bit RGB565`: 16,`8-bit RGB888`:24 + .psram_trans_align = 64, // 默认设为 `64` 即可 + .num_fbs = EXAMPLE_LCD_NUM_FB, // RGB 接口的帧缓存数,默认设为 `1`,大于 `1` 时用于实现多缓冲防撕裂 + .bounce_buffer_size_px = 10 * EXAMPLE_LCD_H_RES, // 用于提升 RGB 接口的数据传输带宽,通常设为 `10 * EXAMPLE_LCD_H_RES` + .clk_src = LCD_CLK_SRC_DEFAULT, // 默认设为 `LCD_CLK_SRC_DEFAULT` 即可 + .disp_gpio_num = EXAMPLE_PIN_NUM_DISP_EN, // 连接 LCD DISP 信号的引脚编号,可以设置为 `-1` 表示不使用 + .pclk_gpio_num = EXAMPLE_PIN_NUM_PCLK, // 连接 LCD PCLK 信号的引脚编号 + .vsync_gpio_num = EXAMPLE_PIN_NUM_VSYNC, // 连接 LCD VSYNC 信号的引脚编号 + .hsync_gpio_num = EXAMPLE_PIN_NUM_HSYNC, // 连接 LCD HSYNC 信号的引脚编号 + .de_gpio_num = EXAMPLE_PIN_NUM_DE, // 连接 LCD DE 信号的引脚编号,可以设置为 `-1` 表示不使用 + .data_gpio_nums = { // 连接 LCD D[15:0] 信号的引脚编号,有效数量由 `data_width` 指定, + // 8-bit 时设置 D[7:0] 即可 + EXAMPLE_PIN_NUM_DATA0, + EXAMPLE_PIN_NUM_DATA1, + EXAMPLE_PIN_NUM_DATA2, + EXAMPLE_PIN_NUM_DATA3, + EXAMPLE_PIN_NUM_DATA4, + EXAMPLE_PIN_NUM_DATA5, + EXAMPLE_PIN_NUM_DATA6, + EXAMPLE_PIN_NUM_DATA7, + EXAMPLE_PIN_NUM_DATA8, + EXAMPLE_PIN_NUM_DATA9, + EXAMPLE_PIN_NUM_DATA10, + EXAMPLE_PIN_NUM_DATA11, + EXAMPLE_PIN_NUM_DATA12, + EXAMPLE_PIN_NUM_DATA13, + EXAMPLE_PIN_NUM_DATA14, + EXAMPLE_PIN_NUM_DATA15, + }, + .timings = { // 以下为 RGB 时序的相关参数,需根据 LCD 驱动 IC 的数据手册以及硬件的配置确定 + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, + .h_res = EXAMPLE_LCD_H_RES, + .v_res = EXAMPLE_LCD_V_RES, + .hsync_back_porch = 40, // 在 DE 模式下,HSYNC 和 VSYNC 的相关参数可以根据期望的刷新率进行调整 + .hsync_front_porch = 20, // 在 SYNC 模式下,HSYNC 和 VSYNC 的相关参数需要和软件初始化命令中的配置保持一致 + .hsync_pulse_width = 1, + .vsync_back_porch = 8, + .vsync_front_porch = 4, + .vsync_pulse_width = 1, + .flgas = { // 由于一些 LCD 可以通过硬件引脚配置这些参数,需要确保它们与配置保持一致,但通常情况下均为 `0` + .hsync_idle_low = 0, // HSYNC 信号空闲时的电平,0:高电平,1:低电平 + .vsync_idle_low = 0, // VSYNC 信号空闲时的电平,0 表示高电平,1:低电平 + .de_idle_high = 0, // DE 信号空闲时的电平,0:高电平,1:低电平 + .pclk_active_neg = 0, // 时钟信号的有效边沿,0:上升沿有效,1:下降沿有效 + .pclk_idle_high = 0, // PCLK 信号空闲时的电平,0:高电平,1:低电平 + }, + }, + .flags.fb_in_psram = 1, // 默认设置为 `1` 即可 + }; + ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + + /* 以下函数可以根据需要调用 */ + // ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); // 通过硬件实现像素的色彩数据按位取反(0xF0F0 -> 0x0F0F) + // ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, true)); // 通过软件实现镜像 X 轴和 Y 轴 + // ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true)); // 通过软件实现交换 X 轴和 Y 轴 + // ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 0)); // 通过软件修改画图时的起始和终止坐标,从而实现画图的偏移 + // ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); // 通过 `disp_gpio_num` 引脚控制 LCD 显示的开关, + // 仅当该引脚设置且不为 `-1` 时可用,否则会报错 + +关于 ``RGB`` 接口参数配置的说明和一些特殊功能函数的使用,请参考 :ref:`说明 ` + +**对于采用 3-wire SPI 和 RGB 接口的 LCD** ,首先通过移植好的驱动组件创建 LCD 设备并获取数据类型为 ``esp_lcd_panel_handle_t`` 的句柄,然后使用 `LCD 通用 APIs `_ 来初始化 LCD 设备,下面是以 `ST7701S `_ 为例的代码说明: + +.. code-block:: c + + #include "esp_check.h" // 依赖的头文件 + #include "esp_lcd_panel_ops.h" + #include "esp_lcd_panel_rgb.h" + #include "esp_lcd_panel_vendor.h" + #include "esp_lcd_st7701.h" // 目标驱动组件的头文件 + + /** + * 用于存放 LCD 驱动 IC 的初始化命令及参数 + */ + // static const st7701_lcd_init_cmd_t lcd_init_cmds[] = { + // // cmd data data_size delay_ms + // {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x13}, 5, 0}, + // {0xEF, (uint8_t []){0x08}, 1, 0}, + // {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, + // {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, + // ... + // }; + + /* 创建 LCD 设备 */ + esp_lcd_rgb_panel_config_t rgb_config = { // RGB 接口的配置参数 + .data_width = EXAMPLE_LCD_DATA_WIDTH, // RGB 接口的数据线位数,如 `16-bit RGB565`: 16,`8-bit RGB888`:8 + .bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // 色彩格式的位数,可能与 RGB 接口的数据线位数不相等, + // 如 `16-bit RGB565`: 16,`8-bit RGB888`:24 + .psram_trans_align = 64, // 默认设为 `64` 即可 + .num_fbs = EXAMPLE_LCD_NUM_FB, // RGB 接口的帧缓存数量,默认设为 `1`,大于 `1` 时用于实现多缓冲防撕裂 + .bounce_buffer_size_px = 10 * EXAMPLE_LCD_H_RES, // 用于提升 RGB 接口的数据传输带宽,通常设为 `10 * EXAMPLE_LCD_H_RES` + .clk_src = LCD_CLK_SRC_DEFAULT, // 默认设为 `LCD_CLK_SRC_DEFAULT` 即可 + .disp_gpio_num = EXAMPLE_PIN_NUM_DISP_EN, // 连接 LCD DISP 信号的引脚编号,可以设置为 -1 表示不使用 + .pclk_gpio_num = EXAMPLE_PIN_NUM_PCLK, // 连接 LCD PCLK 信号的引脚编号 + .vsync_gpio_num = EXAMPLE_PIN_NUM_VSYNC, // 连接 LCD VSYNC 信号的引脚编号 + .hsync_gpio_num = EXAMPLE_PIN_NUM_HSYNC, // 连接 LCD HSYNC 信号的引脚编号 + .de_gpio_num = EXAMPLE_PIN_NUM_DE, // 连接 LCD DE 信号的引脚编号,可以设置为 -1 表示不使用 + .data_gpio_nums = { // 连接 LCD D[15:0] 信号的引脚编号,有效数量由 `data_width` 指定, + // 8-bit 时设置 D[7:0] 即可 + EXAMPLE_PIN_NUM_DATA0, + EXAMPLE_PIN_NUM_DATA1, + EXAMPLE_PIN_NUM_DATA2, + EXAMPLE_PIN_NUM_DATA3, + EXAMPLE_PIN_NUM_DATA4, + EXAMPLE_PIN_NUM_DATA5, + EXAMPLE_PIN_NUM_DATA6, + EXAMPLE_PIN_NUM_DATA7, + EXAMPLE_PIN_NUM_DATA8, + EXAMPLE_PIN_NUM_DATA9, + EXAMPLE_PIN_NUM_DATA10, + EXAMPLE_PIN_NUM_DATA11, + EXAMPLE_PIN_NUM_DATA12, + EXAMPLE_PIN_NUM_DATA13, + EXAMPLE_PIN_NUM_DATA14, + EXAMPLE_PIN_NUM_DATA15, + }, + .timings = { // 以下为 RGB 时序的相关参数,需根据 LCD 驱动 IC 的数据手册以及软硬件的配置确定 + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, + .h_res = EXAMPLE_LCD_H_RES, + .v_res = EXAMPLE_LCD_V_RES, + .hsync_back_porch = 40, // 在 DE 模式下,HSYNC 和 VSYNC 的相关参数可以根据期望的刷新率进行调整 + .hsync_front_porch = 20, // 在 SYNC 模式下,HSYNC 和 VSYNC 的相关参数需要和软件初始化命令中的配置保持一致 + .hsync_pulse_width = 1, + .vsync_back_porch = 8, + .vsync_front_porch = 4, + .vsync_pulse_width = 1, + .flgas = { // 由于一些 LCD 可以通过硬件引脚或者软件命令配置这些参数,需要确保它们与配置保持一致,但通常情况下均为 `0` + .hsync_idle_low = 0, // HSYNC 信号空闲时的电平,0:高电平,1:低电平 + .vsync_idle_low = 0, // VSYNC 信号空闲时的电平,0 表示高电平,1:低电平 + .de_idle_high = 0, // DE 信号空闲时的电平,0:高电平,1:低电平 + .pclk_active_neg = 0, // 时钟信号的有效边沿,0:上升沿有效,1:下降沿有效 + .pclk_idle_high = 0, // PCLK 信号空闲时的电平,0:高电平,1:低电平 + }, + }, + .flags.fb_in_psram = 1, // 默认设置为 `1` 即可 + }; + st7701_vendor_config_t vendor_config = { + .rgb_config = &rgb_config, // RGB 接口的配置参数 + // .init_cmds = lcd_init_cmds, // 用于替换驱动组件中的初始化命令及参数 + // .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(st7701_lcd_init_cmd_t), + .flags = { // LCD 驱动 IC 的配置参数 + .mirror_by_cmd = 1, // 若为 `1` 则使用 LCD 命令实现镜像功能(esp_lcd_panel_mirror()),若为 `0` 则通过软件实现 + .auto_del_panel_io = 0, // 若为 `1` 则在删除 LCD 设备时自动删除接口设备,此时应设置所有名称为 `*_by_cmd` 的参数为 `0`, + // 若为 `0` 则不删除。如果 3-wire SPI 接口的引脚与 RGB 接口的复用,那么需要设置此参数为 `1` + }, + }; + const esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = EXAMPLE_LCD_IO_RST, // 连接 LCD 复位信号的 IO 编号,可以设为 `-1` 表示不使用 + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // 像素色彩的元素顺序(RGB/BGR), + // 一般通过命令 `LCD_CMD_MADCTL(36h)` 控制 + .bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // 色彩格式的位数(RGB565:16,RGB666:18,RGB888:24), + // 一般通过命令 `LCD_CMD_COLMOD(3Ah)` 控制 + .vendor_config = &vendor_config, // RGB 接口及 LCD 驱动 IC 的配置参数 + }; + esp_lcd_panel_handle_t panel_handle = NULL; + ESP_ERROR_CHECK(esp_lcd_new_panel_st7701(io_handle, &panel_config, &panel_handle)); + + /* 初始化 LCD 设备 */ + ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + // 以下函数可以根据需要使用 + // ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); + // ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, true)); + // ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true)); + // ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 0)); + // ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); + +.. _rgb_参数配置及特殊功能函数: + +关于 ``RGB`` 接口配置参数更加详细的说明,请参考 `ESP-IDF 编程指南 `_。 + +除了 `LCD 通用 APIs `_ 之外, `RGB 接口驱动 `_ 中还提供了一些特殊功能的函数,下面是一些常用函数的使用说明: + + #. ``esp_lcd_rgb_panel_set_pclk()``:动态修改时钟频率,可以在 LCD 初始化后使用。 + #. ``esp_lcd_rgb_panel_restart()``:复位数据传输,用于在屏幕发生偏移时调用可以使其恢复正常。 + #. ``esp_lcd_rgb_panel_get_frame_buffer()``:用于获取帧缓存的地址,可用数量由配置参数 ``num_fbs`` 决定,用于多缓冲防撕裂。 + #. ``esp_lcd_rgb_panel_register_event_callbacks()``:注册多种事件的回调函数,示例代码及说明如下: + + .. code-block:: c + + static bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx) + { + /* 可以在此处进行一些操作 */ + + return false; + } + + static bool example_on_bounce_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx) + { + /* 可以在此处进行一些操作 */ + + return false; + } + + esp_lcd_rgb_panel_event_callbacks_t cbs = { + .on_vsync = example_on_vsync_event, // 刷新完一帧图像时的回调函数 + .on_bounce_frame_finish = example_on_bounce_event, // 通过 Bounce Buffer 机制传输完一帧图像时的回调函数 + }; + ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, &example_user_ctx)); + +相关文档 +--------------------- + +- `ST7701S 数据手册 `_ +- `ST77903 数据手册 `_ +- `GC9503 数据手册 `_ +- `色彩格式 `_ +- `3-wire SPI + RGB 接口 `_ diff --git a/docs/zh_CN/display/lcd/spi_lcd.rst b/docs/zh_CN/display/lcd/spi_lcd.rst new file mode 100644 index 000000000..a446ba131 --- /dev/null +++ b/docs/zh_CN/display/lcd/spi_lcd.rst @@ -0,0 +1,286 @@ +SPI LCD 详解 +=========================== + +:link_to_translation:`en:[English]` + +.. contents:: 目录 + :local: + :depth: 2 + +接口模式 +--------------------- + +不同的接口模式需要主控采用不同的 **接线** 和 **驱动** 方式,下面以 *ST7789* 为例,介绍几种比较常见的接口模式。 + +.. figure:: ../../../_static/display/screen/lcd_st7789_spi_select.png + :align: center + :scale: 80% + :alt: SPI 接口的模式选择 + + SPI 接口的模式选择 + +从上图中可以看出, *ST7789* 是通过 ``IM[3:0]`` 引脚来选择 ``Interface I/II`` 和 ``3/4-line`` 的配置,可以实现 4 种不同的接口模式。下图为 *ST7789* 的 ``SPI`` 接口的引脚描述: + +.. figure:: ../../../_static/display/screen/lcd_st7789_spi_pin.png + :align: center + :scale: 80% + :alt: SPI 接口的引脚描述 + + SPI 接口的引脚描述 + +.. _spi_interface_I/II_模式: + +Interface I/II 模式 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. figure:: ../../../_static/display/screen/lcd_st7789_spi_interface_I_II.png + :align: center + :scale: 50% + :alt: Interface I/II 模式的时序图对比(4-line) + + Interface I/II 模式的时序图对比(4-line) + +从图中可以看出, ``Interface I`` 和 ``Interface II`` 的主要区别在于是否仅用一根数据线实现数据的读取和写入(如仅用 ``MOSI``)。 + +.. list-table:: + :widths: 20 50 10 + :header-rows: 1 + + * - 模式 + - 是否仅用一根数据线实现数据的读取和写入 + - ESP 是否支持 + * - Interface I + - 是 + - 是 + * - Interface II + - 否 + - 是 + +.. _spi_3/4-line_模式: + +3/4-line 模式 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. figure:: ../../../_static/display/screen/lcd_st7789_spi_3_4-line.png + :align: center + :scale: 80% + :alt: 3/4-line 模式的时序图对比(Interface I) + + 3/4-line 模式的时序图对比(Interface I) + +从图中可以看出, ``3-line`` 和 ``4-line`` 的主要区别在于是否使用 D/C 信号线。 + +.. list-table:: + :widths: 20 50 10 + :header-rows: 1 + + * - 模式 + - 是否使用 D/C 信号线 + - ESP 是否支持 + * - 3-line + - 否 + - 否 + * - 4-line + - 是 + - 是 + +.. note:: + + #. ``3-line`` 模式有时也称为 ``3-wire`` 或 ``9-bit`` 模式。 + #. 虽然 ESP 的 SPI 外设不支持 LCD 的 ``3-line`` 模式,但是可以通过软件模拟实现,具体请参考组件 `esp_lcd_panel_io_additions `_,它通常用于实现 RGB LCD 的初始化。 + +.. _spi_初始化接口设备: + +初始化接口设备 +------------------------------ + +下面基于 ESP-IDF release/v5.1 中的 `spi_lcd_touch `_ 示例,介绍如何初始化 SPI 接口设备。 + +初始化总线 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +如果有多个设备同时使用同一 SPI 总线,那么只需要对总线初始化一次,下面是示例代码的说明: + +.. code-block:: c + + #include "driver/spi_master.h" // 依赖的头文件 + #include "esp_check.h" + + spi_bus_config_t buscfg = { + .sclk_io_num = EXAMPLE_PIN_NUM_SCLK, // 连接 LCD SCK(SCL) 信号的 IO 编号 + .mosi_io_num = EXAMPLE_PIN_NUM_MOSI, // 连接 LCD MOSI(SDO、SDA) 信号的 IO 编号 + .miso_io_num = EXAMPLE_PIN_NUM_MISO, // 连接 LCD MISO(SDI) 信号的 IO 编号,如果不需要从 LCD 读取数据,可以设为 `-1` + .quadwp_io_num = -1, // 必须设置且为 `-1` + .quadhd_io_num = -1, // 必须设置且为 `-1` + .max_transfer_sz = EXAMPLE_LCD_H_RES * 80 * sizeof(uint16_t), // 表示 SPI 单次传输允许的最大字节数上限,通常设为全屏大小即可 + }; + ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); + // 第 1 个参数表示使用的 SPI 主机 ID,和后续创建接口设备时保持一致 + // 第 3 个参数表示使用的 DMA 通道号,默认设置为 `SPI_DMA_CH_AUTO` 即可 + +下面是部分配置参数的说明: + +#. 若 LCD 驱动 IC 配置为 :ref:`Interface-I 接口模式 `,软件仅需设置 ``mosi_io_num`` 为其数据线 IO,而设置 ``miso_io_num`` 为 -1。 +#. `SPI 驱动 `_ 在传输数据前会对输入数据量的大小进行判断,若单次传输的字节数超过 ``max_transfer_sz`` 则会报错。但是, **SPI 单次 DMA 传输允许的最大字节数** 不仅取决于 ``max_transfer_sz``,而且受限于 ESP-IDF 中的 `SPI_LL_DATA_MAX_BIT_LEN `_ (不同系列 ESP 的值不同),即满足 ``最大字节数 <= MIN(max_transfer_sz, (SPI_LL_DATA_MAX_BIT_LEN / 8))`` 。由于 `esp_lcd 驱动 `_ 会提前判断输入的数据量是否超过限制,如果超过则进行 **分包处理** 后才控制 SPI 进行多次传输, **因此 max_transfer_sz 通常设为全屏大小即可** 。 + +创建接口设备 +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +基于初始化好的 SPI 总线可以创建相应的接口设备,每个接口设备对应一个 SPI master 设备,下面是示例代码的说明: + +.. code-block:: c + + #include "esp_lcd_panel_io.h" // 依赖的头文件 + + static bool example_on_color_trans_dome(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) + { + /* 色彩数据传输完成时的回调函数,可以在此处进行一些操作 */ + + return false; + } + + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_spi_config_t io_config = { + .dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC, // 连接 LCD DC(RS) 信号的 IO 编号,可以设为 `-1` 表示不使用 + .cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS, // 连接 LCD CS 信号的 IO 编号,可以设为 `-1` 表示不使用 + .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, // SPI 的时钟频率(Hz),ESP 最高支持 80M(SPI_MASTER_FREQ_80M) + // 需根据 LCD 驱动 IC 的数据手册确定其最大值 + .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, // 单位 LCD 命令的比特数,应为 8 的整数倍 + .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, // 单位 LCD 参数的比特数,应为 8 的整数倍 + .spi_mode = 0, // SPI 模式(0-3),需根据 LCD 驱动 IC 的数据手册以及硬件的配置确定(如 IM[3:0]) + .trans_queue_depth = 10, // SPI 设备传输数据的队列深度,一般设为 10 即可 + .on_color_trans_done = example_on_color_trans_dome, // 单次调用 `esp_lcd_panel_draw_bitmap()` 传输完成后的回调函数 + .user_ctx = &example_user_ctx, // 传给回调函数的用户参数 + .flags = { // 以下为 SPI 时序的相关参数,需根据 LCD 驱动 IC 的数据手册以及硬件的配置确定 + .sio_mode = 0, // 通过一根数据线(MOSI)读写数据,0: Interface I 型,1: Interface II 型 + }, + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle)); + + /* 以下函数也可用于注册色彩数据传输完成事件的回调函数 */ + // const esp_lcd_panel_io_callbacks_t cbs = { + // .on_color_trans_done = example_on_color_trans_dome, + // }; + // esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, &example_user_ctx); + +关于 ``SPI`` 接口配置参数更加详细的说明,请参考 `ESP-IDF 编程指南 `_。 + +通过创建接口设备可以获取数据类型为 ``esp_lcd_panel_io_handle_t`` 的句柄,然后能够使用以下 `接口通用 APIs `_ 给 LCD 的驱动 IC 发送 **命令** 和 **图像数据**: + + #. ``esp_lcd_panel_io_tx_param()``:用于发送单个 LCD 的命令及配套参数,其内部通过函数 ``spi_device_polling_transmit()`` 实现数据传输,使用该函数会等待数据传输完毕后才会返回。 + #. ``esp_lcd_panel_io_tx_color()``:用于发送单次 LCD 刷屏命令和图像数据。在函数内部,它通过函数 ``spi_device_polling_transmit()`` 发送命令和一些少量的参数,然后通过函数 ``spi_device_queue_trans()`` 来分包发送大量的图像数据,每个包的大小由 **SPI 单次 DMA 传输允许的最大字节数** 来限制。这个函数将图像缓存地址等相关数据压入队列,队列的深度由 ``trans_queue_depth`` 参数指定。一旦数据成功压入队列,函数就会立刻返回。因此,如果计划在后续操作中修改相同的图像缓存,则需要注册一个回调函数来判断上一次的传输是否已经完成。如果不这样做,可能会在未完成的传输上进行修改,这会导致由于数据混乱而显示出现错误。 + +.. _spi_移植驱动组件: + +移植驱动组件 +------------------------ + +移植 SPI LCD 驱动组件的基本原理包含以下三点: + + #. 基于数据类型为 ``esp_lcd_panel_io_handle_t`` 的接口设备句柄发送指定格式的命令及参数。 + #. 实现并创建一个 LCD 设备,然后通过注册回调函数的方式实现结构体 `esp_lcd_panel_t `_ 中的各项功能。 + #. 实现一个函数用于提供数据类型为 ``esp_lcd_panel_handle_t`` 的 LCD 设备句柄,使得应用程序能够利用 `LCD 通用 APIs `_ 来操作 LCD 设备。 + +下面是 ``esp_lcd_panel_handle_t`` 各项功能的实现说明以及和 `LCD 通用 APIs `_ 的对应关系: + +.. list-table:: + :widths: 10 20 70 + :header-rows: 1 + + * - 功能 + - LCD 通用 APIs + - 实现说明 + * - reset() + - esp_lcd_panel_reset() + - 若设备连接了复位引脚,则通过该引脚进行硬件复位,否则通过命令 ``LCD_CMD_SWRESET(01h)`` 进行软件复位。 + * - init() + - esp_lcd_panel_init() + - 通过发送一系列的命令及参数来初始化 LCD 设备。 + * - del() + - esp_lcd_panel_del() + - 释放驱动占用的资源,包括申请的存储空间和使用的 IO。 + * - draw_bitmap() + - esp_lcd_panel_draw_bitmap() + - 首先通过命令 ``LCD_CMD_CASET(2Ah)`` 和 ``LCD_CMD_RASET(2Bh)`` 发送图像的起始和终止坐标,然后通过命令 ``LCD_CMD_RAMWR(2Ch)`` 发送图像数据。 + * - mirror() + - esp_lcd_panel_mirror() + - 通过命令 ``LCD_CMD_MADCTL(36h)`` 设置是否镜像屏幕的 X 轴和 Y 轴。 + * - swap_xy() + - esp_lcd_panel_swap_xy() + - 通过命令 ``LCD_CMD_MADCTL(36h)`` 设置是否交换屏幕的 X 轴和 Y 轴。 + * - set_gap() + - esp_lcd_panel_set_gap() + - 通过软件修改画图时的起始和终止坐标,从而实现画图的偏移。 + * - invert_color() + - esp_lcd_panel_invert_color() + - 通过命令 ``LCD_CMD_INVON(21h)`` 和 ``LCD_CMD_INVOFF(20h)`` 实现像素的颜色数据按位取反(0xF0F0 -> 0x0F0F)。 + * - disp_on_off() + - esp_lcd_panel_disp_on_off() + - 通过命令 ``LCD_CMD_DISON(29h)`` 和 ``LCD_CMD_DISOFF(28h)`` 实现屏幕显示的开关。 + +对于大多数 SPI LCD,其驱动 IC 的命令及参数与上述实现说明中的兼容,因此可以通过以下步骤完成移植: + + #. 在 :ref:`LCD 驱动组件 ` 中选择一个型号相似的 SPI LCD 驱动组件。 + #. 通过查阅目标 LCD 驱动 IC 的数据手册,确认其与所选组件中各功能使用到的命令及参数是否一致,若不一致则需要修改相关代码。 + #. 即使 LCD 驱动 IC 的型号相同,不同制造商的屏幕也通常需要使用各自提供的初始化命令配置。因此,需要修改初始化函数 ``init()`` 中发送的命令和参数。这些初始化命令通常以特定的格式存储在一个静态数组中。此外,需要注意不要在初始化命令中包含一些特殊的命令,例如 ``LCD_CMD_COLMOD(3Ah)`` 和 ``LCD_CMD_MADCTL(36h)``,这些命令是由驱动组件进行管理和使用的。 + #. 可使用编辑器的字符搜索和替换功能,将组件中的 LCD 驱动 IC 名称替换为目标名称,如将 ``gc9a01`` 替换为 ``st77916``。 + +.. _spi_初始化_lcd: + +初始化 LCD 设备 +------------------------------ + +首先通过移植好的驱动组件创建 LCD 设备并获取数据类型为 ``esp_lcd_panel_handle_t`` 的句柄,然后使用 `LCD 通用 APIs `_ 来初始化 LCD 设备,下面是以 `GC9A01 `_ 为例的代码说明: + +.. code-block:: c + + #include "esp_lcd_panel_vendor.h" // 依赖的头文件 + #include "esp_lcd_panel_ops.h" + #include "esp_lcd_gc9a01.h" // 目标驱动组件的头文件 + + /** + * 用于存放 LCD 驱动 IC 的初始化命令及参数 + */ + // static const gc9a01_lcd_init_cmd_t lcd_init_cmds[] = { + // // {cmd, { data }, data_size, delay_ms} + // {0xfe, (uint8_t []){0x00}, 0, 0}, + // {0xef, (uint8_t []){0x00}, 0, 0}, + // {0xeb, (uint8_t []){0x14}, 1, 0}, + // ... + // }; + + /* 创建 LCD 设备 */ + esp_lcd_panel_handle_t panel_handle = NULL; + // const gc9a01_vendor_config_t vendor_config = { // 用于替换驱动组件中的初始化命令及参数 + // .init_cmds = lcd_init_cmds, + // .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), + // }; + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST, // 连接 LCD 复位信号的 IO 编号,可以设为 `-1` 表示不使用 + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // 像素色彩的元素顺序(RGB/BGR), + // 一般通过命令 `LCD_CMD_MADCTL(36h)` 控制 + .bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // 色彩格式的位数(RGB565:16,RGB666:18), + // 一般通过命令 `LCD_CMD_COLMOD(3Ah)` 控制 + // .vendor_config = &vendor_config, // 用于替换驱动组件中的初始化命令及参数 + }; + ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); + + /* 初始化 LCD 设备 */ + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + // ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); // 这些函数可以根据需要使用 + // ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, true)); + // ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true)); + // ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 0)); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); + +下面是一些关于使用函数 ``esp_lcd_panel_draw_bitmap()`` 刷新 SPI LCD 图像的说明: + + #. 传入该函数的图像缓存的字节数可以大于 ``max_transfer_sz``,此时 ``esp_lcd`` 驱动内部会根据 SPI 单次 DMA 传输允许的最大字节数进行分包处理。 + #. 由于该函数是采用 DMA 的方式来传输图像数据,也就是说该函数调用完成后数据仍在通过 DMA 进行传输,此时不能修改正在使用的缓存区域(如进行 LVGL 的渲染)。因此,需要通过总线初始化或者调用 ``esp_lcd_panel_io_register_event_callbacks()`` 注册的回调函数来判断上一次传输是否完成。 + #. 由于 SPI 驱动目前不支持直接通过 DMA 传输 PSRAM 上的数据,其内部会判断数据是否存放在 PSRAM 上,若是则会将其拷贝到 SRAM 中再进行传输。因此,推荐使用 SRAM 作为图像的缓存进行传输(如用于 LVGL 渲染的缓存),否则直接传输 PSRAM 上较大的图像数据,很可能会出现 SRAM 不足的情况。 + +相关文档 +--------------------- + +- `ST7789 数据手册 `_ diff --git a/docs/zh_CN/display/screen.rst b/docs/zh_CN/display/screen.rst deleted file mode 100644 index 02921454e..000000000 --- a/docs/zh_CN/display/screen.rst +++ /dev/null @@ -1,340 +0,0 @@ -显示屏 -=========== -:link_to_translation:`en:[English]` - -许多应用需要把信息显示给用户,因此显示屏是很重要的一个显示设备。ESP32 系列芯片为屏幕显示应用提供了丰富的外设支持,包含的接口类型有 ``I2C``、``8080``、``SPI`` 和 ``RGB``。 - -一块屏幕通常有两个主要部分:``显示基板`` 和 ``驱动 IC``。显示基板(也称显示面板)决定了显示的尺寸、分辨率、色彩等参数;驱动 IC (也称屏幕控制器)是匹配显示基板并与基板封装在一起的,它通过一定的接口对外通信并控制显示基板进行显示。 - -ESP32 系列芯片的屏幕接口 ------------------------- - -大部分屏幕控制器可以支持多种显示接口。如 `ILI9486 `_ 支持 MCU 接口(即 8080 接口)、SPI 接口、RGB 接口和 MIPI 接口。 - -ESP32 系列芯片接口支持情况如下: - -================== ====================== ==================== ==================== =========================== -SoC I2C 接口 SPI 接口 8080 接口 RGB 接口 ------------------- ---------------------- -------------------- -------------------- --------------------------- -ESP32 |supported| |supported| |supported| ------------------- ---------------------- -------------------- -------------------- --------------------------- -ESP32-S2 |supported| |supported| |supported| ------------------- ---------------------- -------------------- -------------------- --------------------------- -ESP32-S3 |supported| |supported| |supported| |supported| ------------------- ---------------------- -------------------- -------------------- --------------------------- -ESP32-C3 |supported| |supported| -================== ====================== ==================== ==================== =========================== - -.. |supported| image:: https://img.shields.io/badge/-Supported-green - -.. note:: ESP32 系列芯片的 I2C、SPI、8080 和 RGB 接口均可以通过 GPIO 交换矩阵将信号映射到任意管脚。 - -SPI 接口 -^^^^^^^^^^^^^ - -ESP32 系列芯片的 SPI 接口特点: - -- SPI 时钟频率最高可达 80MHz -- 支持 QSPI 模式 - -8080 接口 -^^^^^^^^^^^^^ - -ESP32 系列芯片的 8080 接口分别由不同的外设实现 - -=============== ======================== =========================================================== - SoC 实现 8080 接口的外设 特点 ---------------- ------------------------ ----------------------------------------------------------- - ESP32 I2S 8/16 位模式下时钟频率最高可达 20MHz ---------------- ------------------------ ----------------------------------------------------------- - ESP32-S2 I2S 8 位模式下时钟频率最高可达 40MHz,16 位模式下 20MHz ---------------- ------------------------ ----------------------------------------------------------- - ESP32-S3 LCD_CAM 8 位模式下时钟频率最高可达 40MHz,16 位模式下 20MHz -=============== ======================== =========================================================== - -RGB 接口 -^^^^^^^^^^^^^ - -ESP32-S3 芯片拥有一个 RGB 接口,支持并行 RGB565 模式和串行 RGB888 模式。RGB 接口与 8080 接口都是并行接口,一个重要区别在于 RGB 接口的屏幕一般不带显存,这就需要每一个刷新周期都对屏幕上的所有像素数据进行更新。由于 ESP32-S3 芯片内部没有足够的 RAM 用于显存,所以需要外接 PSRAM,并将显存置于 PSRAM 上。由于显存要求的带宽较大,所以为达到良好的显示效果 **需要使用 8 线 PSRAM ,并且将 PSRAM 时钟频率至少设置为 80MHz**。 - -.. note:: RGB 接口的驱动在 esp-idf 的 ``components/esp_lcd`` 组件中而不在 esp-iot-solution。例程请参考 ``esp-idf/examples/peripherals/lcd/rgb_panel`` - -屏幕控制器 -------------- - -已适配的屏幕控制器型号如下表所示: - -+------------+----------------+------------+ -| 控制器型号 | 最大分辨率 | 类型 | -+============+================+============+ -| NT35510 | 480 x 865 | Color | -+------------+----------------+------------+ -| ILI9806 | 480 x 865 | Color | -+------------+----------------+------------+ -| RM68120 | 480 x 865 | Color | -+------------+----------------+------------+ -| ILI9486 | 320 x 480 | Color | -+------------+----------------+------------+ -| ILI9488 | 320 x 480 | Color | -+------------+----------------+------------+ -| ILI9341 | 240 x 320 | Color | -+------------+----------------+------------+ -| ILI9342 | 240 x 320 | Color | -+------------+----------------+------------+ -| ST7789 | 240 x 320 | Color | -+------------+----------------+------------+ -| ST7796 | 320 x 480 | Color | -+------------+----------------+------------+ -| SSD1351 | 128 x 128 | Color | -+------------+----------------+------------+ -| SSD1306 | 128 x 64 | Mono | -+------------+----------------+------------+ -| SSD1307 | 128 x 39 | Mono | -+------------+----------------+------------+ -| SSD1322 | 480 x 128 | Gray | -+------------+----------------+------------+ -| SSD1963 | 480 x 864 | Color | -+------------+----------------+------------+ - -其中 ``SSD1963`` 可将 8080 接口转换到 RGB 接口。 - -驱动结构 ----------- - -.. figure:: ../../_static/display/screen_driver_structure.png - :align: center - :width: 500px - - 屏幕驱动结构框图 - -为了更加符合一个屏幕控制芯片拥有多个接口的实际情况,将屏幕驱动程序划分为 ``接口驱动`` 和 ``屏幕控制器驱动`` 两部分。 - -- 接口驱动:完成基本的命令和数据的读写 -- 屏幕控制器驱动:通过接口驱动来完成屏幕的显示 - -在程序设计上,一个屏幕控制器驱动可以通过调用不同的接口驱动以实现切换硬件上不同的接口。 - -屏幕的分类 ----------- -对屏幕进行分类的讨论将有助于我们对驱动的理解,这里将按照屏幕可显示的色彩来分类,而非 OLED、LCD 等屏幕的面板材料。 -一般情况下,屏幕显示的色彩决定了 BPP (Bits Per Pixel),而 BPP 的不同导致程序的处理方式有一些不同,下面将更直观地列举几种 GRAM 映射到像素点的方式: - -.. figure:: ../../_static/display/screen_driver_RGB565.png - :align: center - :width: 600px - - BPP = 16 GRAM 结构 - -.. figure:: ../../_static/display/screen_driver_mono.png - :align: center - :width: 600px - - BPP = 1 GRAM 结构 - -.. figure:: ../../_static/display/screen_driver_gray.png - :align: center - :width: 600px - - BPP = 4 GRAM 结构 - -从以上图中可以看出,映射方式大概可以分为两类: - -- BBP >= 8,通常是支持 RGB888、RGB666、RGB565 等编码的彩色屏幕。 -- BPP < 8,通常是单色的屏幕,可能是黑白的,也可能是灰阶的。 - -BPP < 8 时,一个字节映射到了多个像素,因此无法直接地控制单个像素。这时,驱动不支持 :c:func:`draw_pixel` 函数,且 :c:func:`set_window` 的参数也将受到限制。BPP >= 8 时,则可以轻松地访问单个像素。 - - -.. attention:: 对于彩色屏幕,驱动仅支持 RGB565 颜色编码。 - -接口驱动 ------------ - -一个屏幕控制器通常有多种接口,在 ESP32 上通常使用 ``8080 并口``、``SPI`` 和 ``I2C`` 这三种接口与屏幕连接,可以在调用 :c:func:`scr_interface_create` 创建接口驱动时选用其中一种接口。 - -.. note:: 使用 :c:func:`scr_interface_create` 创建不同类型的接口时需要注意传入与之对应的配置参数类型,例如 8080 接口是 :cpp:type:`i2s_lcd_config_t` 而 SPI 接口是 :cpp:type:`scr_interface_spi_config_t`。 - -为了方便在屏幕控制器驱动中统一使用这些接口,:component_file:`display/screen/screen_utility/interface_drv_def.h` 中定义了所有接口,可以使用简单的参数调用接口驱动。 - -.. note:: 大部分屏幕是大端模式,而 ESP32 是小端模式,因此可在使用的接口驱动中根据 ``swap_data`` 配置可选择进行大小端转换。**请注意:** 当使用 SPI 接口时,由于 IDF 的 SPI 驱动内部没有提供该功能,接口驱动将会对传入数据进行转换,这要求传入的数据是可写的,因此数据 **必须** 存放在 RAM 中。 - -屏幕控制器驱动 ----------------- - -该部分将根据不同的屏幕控制器分别实现显示等功能,为了方便地移植到不同 GUI 库,对屏幕的一部分通用函数用 :cpp:type:`scr_driver_t` 进行了抽象。对于一些屏幕的非通用功能,需要自行调用其特定的函数完成。 - -对于这些通用函数,由于屏幕控制器本身的功能不尽相同,并不是所有的屏幕都全部实现了,例如:对于 BPP < 8 的屏幕不支持 :c:func:`draw_pixel` 函数。调用不支持的函数将返回 :cpp:enumerator:`ESP_ERR_NOT_SUPPORTED`。 - -显示方向 -^^^^^^^^^ - -这里设置的屏幕显示方向是完全由屏幕硬件实现的,这个功能在不同的屏幕控制器上会有差异。一共有 8 种可能的显示方向,显示器可以旋转 0°、90°、180° 或 270°,也可以从顶部或底部查看,默认方向为 0° 和顶部查看。这 8 (4 × 2) 个不同的显示方向也可以表示为 3 个二进制开关的组合:X-mirroring、Y-mirroring 和 X/Y swapping。 - -下表将列出全部 8 种组合显示的方向。如果显示方向不正常,请查看下表中的配置开关使其正常工作。 - -================== ====================== ==================== =========================== -|original| 0 |mirror_y| SCR_MIRROR_Y - [SCR_DIR_LRTB] [SCR_DIR_LRBT] ------------------- ---------------------- -------------------- --------------------------- -|mirror_x| SCR_MIRROR_X |mirror_xy| SCR_MIRROR_X| - [SCR_DIR_RLTB] SCR_MIRROR_Y - [SCR_DIR_RLBT] ------------------- ---------------------- -------------------- --------------------------- -|swap_xy| SCR_SWAP_XY |swap_xy_mirror_y| SCR_SWAP_XY| - [SCR_DIR_TBLR] SCR_MIRROR_Y - [SCR_DIR_BTLR] ------------------- ---------------------- -------------------- --------------------------- -|swap_xy_mirror_x| SCR_SWAP_XY| |swap_xy_mirror_xy| SCR_SWAP_XY| - SCR_MIRROR_X SCR_MIRROR_X| - [SCR_DIR_TBRL] SCR_MIRROR_Y - [SCR_DIR_BTRL] -================== ====================== ==================== =========================== - -.. |original| image:: ../../_static/display/original.png - :height: 50px - :width: 100px - -.. |mirror_y| image:: ../../_static/display/mirror_y.png - :height: 50px - :width: 100px -.. |mirror_x| image:: ../../_static/display/mirror_x.png - :height: 50px - :width: 100px -.. |mirror_xy| image:: ../../_static/display/mirror_xy.png - :height: 50px - :width: 100px - -.. |swap_xy| image:: ../../_static/display/swap_xy.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_x| image:: ../../_static/display/swap_xy_mirror_x.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_y| image:: ../../_static/display/swap_xy_mirror_y.png - :height: 100px - :width: 50px -.. |swap_xy_mirror_xy| image:: ../../_static/display/swap_xy_mirror_xy.png - :height: 100px - :width: 50px - -对于不同屏幕控制器,屏幕显示方向的实现并不完全相同,通常分为以下的情况: - - - 对于彩色屏幕,支持 8 个方向的旋转。 - - 对于单色屏幕,如 SSD1306 等屏幕来说,只支持 :cpp:type:`scr_dir_t` 中定义的前 4 个方向,即不支持交换 XY 轴。 - -.. note:: - 显示方向还和使用的屏幕面板有关系,你可能会发现两种异常的情况: - - - 显示方向设置为 :cpp:enumerator:`SCR_DIR_LRTB`,屏幕却不是按照上表中对应的显示方向。这可能是因为屏幕面板上的走线对 X/Y 方向上进行了镜像,这时应该根据实际情况调整旋转以得到期望的显示方向。 - - 旋转了屏幕后,显示内容不见了。这可能是因为屏幕面板的分辨率小于屏幕控制器的分辨率,导致旋转后显示区域没有完全落在屏幕面板上,这时应考虑设置正确的显示区域偏移。 - -显示区域的偏移 -^^^^^^^^^^^^^^^^^^ - -在一些小尺寸的屏幕上,通常其可视区域分辨率小于所用屏幕控制器的分辨率。请参考以下示例图: - -.. image:: ../../_static/display/screen_offset.png - :align: center - :width: 350px - -图中 ``Controller window`` 是屏幕控制器的显示窗口,分辨率为 240 × 320,``Panel window`` 是屏幕面板窗口,分辨率为 135 × 240,可视的区域为屏幕面板区域。可以看出显示区域在水平方向上偏移了 52 个像素,在垂直方向上偏移了 40 个像素。 - -当屏幕逆时针旋转 90° 后,变成水平方向上偏移了 40 个像素,在垂直方向上偏移了 53 个像素,如下所示: - -.. image:: ../../_static/display/screen_offset_rotate.png - :align: center - :width: 420px - -屏幕控制器驱动会帮助你自动根据屏幕的旋转来改变偏移的值,以保持正确的显示区域。你需要做的是在 :cpp:type:`scr_controller_config_t` 中正确配置屏幕在 ``SCR_DIR_LRTB`` 方向时的偏移和屏幕面板尺寸。 - -.. note:: - - - 显示偏移仅支持 BPP >= 8 的屏幕。 - - 当屏幕控制器是可选分辨率的时候,发现偏移不对可能是因为选择的分辨率与实际不符,此时应该修改程序,如: ILI9806 可尝试修改 ``ili9806.c`` 中的 ``ILI9806_RESOLUTION_VER`` 为实际的分辨率。 - -应用示例 ------------- - -.. note:: - - 以下示例不再维护,LCD 以及 LVGL 示例请参考: `i80_controller `_、 `rgb_panel `_ 和 `spi_lcd_touch `_ - -初始化屏幕 -^^^^^^^^^^^ - -.. code:: c - - scr_driver_t g_lcd; // A screen driver - esp_err_t ret = ESP_OK; - - /** Initialize 16bit 8080 interface */ - i2s_lcd_config_t i2s_lcd_cfg = { - .data_width = 16, - .pin_data_num = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 - }, - .pin_num_cs = 45, - .pin_num_wr = 34, - .pin_num_rs = 33, - .clk_freq = 20000000, - .i2s_port = I2S_NUM_0, - .buffer_size = 32000, - .swap_data = false, - }; - scr_interface_driver_t *iface_drv; - scr_interface_create(SCREEN_IFACE_8080, &i2s_lcd_cfg, &iface_drv); - - /** Find screen driver for ILI9806 */ - ret = scr_find_driver(SCREEN_CONTROLLER_ILI9806, &g_lcd); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "screen find failed"); - return; - } - - /** Configure screen controller */ - scr_controller_config_t lcd_cfg = { - .interface_drv = iface_drv, - .pin_num_rst = -1, // The reset pin is not connected - .pin_num_bckl = -1, // The backlight pin is not connected - .rst_active_level = 0, - .bckl_active_level = 1, - .offset_hor = 0, - .offset_ver = 0, - .width = 480, - .height = 854, - .rotate = SCR_DIR_LRBT, - }; - - /** Initialize ILI9806 screen */ - g_lcd.init(&lcd_cfg); - -.. note:: - - 默认情况下只打开了 ILI9341 屏幕的驱动,如果要使用其他的驱动,需要在 ``menuconfig -> Component config -> LCD Drivers -> Select Screen Controller`` 中使能对应屏幕驱动。 - -显示图像 -^^^^^^^^^^^ - -.. code:: c - - /** Draw a red point at position (10, 20) */ - lcd.draw_pixel(10, 20, COLOR_RED); - - /** Draw a bitmap */ - lcd.draw_bitmap(0, 0, width_of_pic, height_of_pic, pic_data); - -获取屏幕信息 -^^^^^^^^^^^^^ - -.. code:: c - - scr_info_t lcd_info; - lcd.get_info(&lcd_info); - ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", lcd_info.name, lcd_info.width, lcd_info.height); - -API 参考 ------------------ - -.. include-build-file:: inc/screen_driver.inc - -.. include-build-file:: inc/scr_interface_driver.inc