痞子衡嵌入式:在i.MXRT1170上快速點亮一款全新LCD屏的方法與步驟(MIPI DSI接口)


  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是在i.MXRT1170上快速點亮一款全新LCD屏的方法與步驟

  我們知道 LCD 屏的接口有很多:DPI-RGB、MIPI DSI、DBI/MCU(I8080)、LVDS、SPI 等等,接口不同,對應的軟件驅動也不同。RT1170 片內外設對以上接口都能很好地支持,今天我們主要聊最近比較火的 MIPI DSI 接口。

  在恩智浦官方 SDK (v2.14) 裏目前支持的 MIPI DSI 接口的 LCD 屏主要有如下四款,但客戶在實際應用中選擇的屏五花八門(生產 MIPI DSI 接口的 LCD 廠商非常多),如果我們拿到一款全新 LCD 屏,該如何快速點亮它呢?今天痞子衡教你方法:

LCD屏型號 LCD分辨率
width * height
LCD驅動IC
晶鴻電子 RK055AHD091 720x1280 瑞鼎科技 RM68200
晶鴻電子 RK055MHD091 720x1280 奇景光電 HX8394-F
晶鴻電子 RK055IQH091 540x960 瑞鼎科技 RM68191
定製屏 G1120B0MIPI 400x392 瑞鼎科技 RM67162

一、點屏準備工作

  磨刀不誤砍柴工,在開始點屏之前我們需要準備如下材料,這在後續修改和調試 LCD 屏相關代碼時非常重要。其中 LCD 屏數據手冊一般需要向屏廠獲取,有了屏數據手冊我們就能知道其相應驅動 IC,從而下載這個驅動 IC 的數據手冊。

1. LCD 屏配套的數據手冊
2. LCD 屏內置驅動 IC 的數據手冊
3. RT1170 板卡連接 LCD 屏的原理圖
4. 恩智浦 SDK_2_14_0_MIMXRT1170-EVKB
5. 能夠訪問 github

  痞子衡就以深圳柯達科電子生產的 KD050FWFIA019-C019A 屏爲例,這款 MIPI DSI 屏分辨率是 480x854,其驅動 IC 是來自奕力科技的 ILI9806E。

二、點屏標準步驟

2.1 熟悉SDK標準例程

  恩智浦 SDK 裏的 elcdif_rgb 例程是一個很好的基礎工程,我們可以基於這個工程來修改代碼做調試。工程裏我們主要關注 elcdif_support.c/h 文件,在這個文件裏,恩智浦已經把不同屏之間的差異做了抽離處理,你搜索 MIPI_PANEL_ 宏就能找到那些差異,這些差異的地方就是我們需要改動的地方。

\SDK_2_14_0_MIMXRT1170-EVKB\boards\evkbmimxrt1170\driver_examples\elcdif\rgb\cm7\iar

  這個 elcdif_rgb 例程裏沒有看到 G1120B0MIPI 身影,因爲小分辨率的圓屏不太適合這個 example,其驅動可在 RT595_SDK\boards\evkmimxrt595\vglite_examples 裏找到。

2.2 調整屏控制I/O腳(Power_en、Reset、Backlight)

  先來關注硬件上需要注意的改動,RT1170 上 MIPI DSI 這個外設不同於其它外設有很多 pinmux 選項,其就一組固定的引腳(並且是專用的),所以這組引腳我們不需要做任何代碼上的配置。

  但是 LCD 屏除了 MIPI DSI 相關信號以及電源、地之外,通常還有三個控制信號,即 Power_en(電源使能-可選)、Reset(硬復位)、Backlight(背光控制),這三個信號一般是通過普通 GPIO 來控制的。

  所以我們需要打開板卡原理圖,找到 LCD 相關連接把這三個信號所用的 GPIO 找出來,並在代碼裏如下地方做相應改動:

  elcdif_rgb 例程會在共享函數 BOARD_InitLcdPanel() 裏操作 BOARD_MIPI_PANEL_BL 宏所指向的 GPIO 來打開背光。此外 BOARD_MIPI_PANEL_RST 和 BOARD_MIPI_PANEL_POWER 宏所指向的 GPIO 操作已經被封裝在如下函數裏,這個函數被進一步封裝進 display_handle_t 裏供後續驅動靈活使用:

static void PANEL_PullResetPin(bool pullUp);
static void PANEL_PullPowerPin(bool pullUp);

2.3 創建LCD驅動IC源文件

  現在我們需要在如下目錄下,創建 ILI9806E 的驅動文件,可以先直接拷貝 hx8394 文件夾下的文件並將其改名後添加進工程,並且在 elcdif_support.c/h 裏也複製添加相應代碼保證編譯通過(後續再參考 ILI9806E 數據手冊修改代碼)。

\SDK_2_14_0_MIMXRT1170-EVKB\components\video\display

2.4 調整屏上電覆位延時(Power_en、Reset)

  有了 fsl_ili9806e.c/h 基本源文件後,現在我們需要根據 ILI9806E 數據手冊來修改代碼。首先是調整屏上電以及復位延時時間,這個延時一般既可以在 KD050FWFIA019-C019A 屏的數據手冊也可以在 ILI9806E 的數據手冊裏找到。

  有了延時數值之後,在 ILI9806E_Init() 函數裏做相應設置即可:

status_t ILI9806E_Init(display_handle_t *handle, const display_config_t *config)
{
    const ili9806e_resource_t *resource = (const ili9806e_resource_t *)(handle->resource);
    /* Only support 480 * 854 */
    if (config->resolution != FSL_VIDEO_RESOLUTION(480, 854))
    {
        return kStatus_InvalidArgument;
    }
    /* Power on. */
    resource->pullPowerPin(true);
    ILI9806E_DelayMs(1U);
    /* 根據屏數據手冊調整復位延時時間. */
    resource->pullResetPin(true);
    ILI9806E_DelayMs(10U);
    resource->pullResetPin(false);
    ILI9806E_DelayMs(10U);
    resource->pullResetPin(true);
    ILI9806E_DelayMs(120U);
    
    /* 代碼省略 */
}

2.5 調整屏顯示相關參數

  現在我們需要在 elcdif_support.h 里根據 KD050FWFIA019-C019A 屏的數據手冊修改如下定義包含:屏分辨率、六個行列掃描參數、四個信號極性(APP_POL_FLAGS)、數據位寬,這些都是屏本身的特性。

#if (USE_MIPI_PANEL == MIPI_PANEL_KD050FWFIA019)
#define APP_PANEL_HEIGHT 854
#define APP_PANEL_WIDTH  480
#define APP_HSW          4
#define APP_HFP          18
#define APP_HBP          30
#define APP_VSW          4
#define APP_VFP          20
#define APP_VBP          30
#endif
#define APP_POL_FLAGS \
    (kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnFallingClkEdge)

#define APP_DATA_BUS       24
#define APP_LCDIF_DATA_BUS kELCDIF_DataBus24Bit

  關於六個行列掃描參數(HSW/HFP/HBP/VSW/VFP/VBP)稍稍科普一下,這些信號是以行列同步信號(VSYNC/HSYNC)爲時間起點來做的延時,相當於在實際顯示的圖像寬高基礎上做了外圍擴大,從而提高圖像有效區域顯示的可靠性(實際上是等待面板做好每行數據刷新前的準備工作)。

  分辨率和行列掃描參數均設置正確了之後,別忘了根據想要的刷新率(比如 60Hz)計算得出所需的 pixel clock,在 BOARD_InitLcdifClock() 函數裏做相應設置。

void BOARD_InitLcdifClock(void)
{
    /*
     * The pixel clock is (height + VSW + VFP + VBP) * (width + HSW + HFP + HBP) * frame rate.
     * Use PLL_528 as clock source.
     * For 60Hz frame rate, the KD050FWFIA019 pixel clock should be 29MHz.
     */
    const clock_root_config_t lcdifClockConfig = {
        .clockOff = false,
        .mux      = 4, /*!< PLL_528. */
#if (USE_MIPI_PANEL == MIPI_PANEL_RK055AHD091) || (USE_MIPI_PANEL == MIPI_PANEL_RK055MHD091)
        .div = 9,
#elif (USE_MIPI_PANEL == MIPI_PANEL_RK055IQH091)
        .div = 15,
#elif (USE_MIPI_PANEL == MIPI_PANEL_KD050FWFIA019)
        // 我們需要設置 29MHz 的 pixel clock
        .div = 18,
#endif
    };
    CLOCK_SetRootClock(kCLOCK_Root_Lcdif, &lcdifClockConfig);
    mipiDsiDpiClkFreq_Hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Lcdif);
}

2.6 配置LCD驅動芯片

  現在到了最難也是最重要的環節了,KD050FWFIA019-C019A 面板主要是由 ILI9806E 芯片驅動的,ILI9806E 本身是個萬能驅動芯片,其支持的接口很多,MIPI DSI 僅是其一,而且 2.5 節裏設置的那些關於屏顯示相關參數,我們都需要設置進 ILI9806E 內部寄存器裏。

  打開 ILI9806E 數據手冊(V097版),一共 328 頁,寄存器一大堆,我們難道要看着數據手冊一個個去設置嗎?當然不是!這時候需要打開萬能的 github,搜索跟 ili9806e 相關的代碼,看看前人有沒有調試好的現成代碼。

  其實關於屏的支持,Linux 裏做得比較多,痞子衡找了個 RaspberryPI 移植的分支,裏面有 ili9806e 參數初始化表,注意這個表不一定完全適用 KD050FWFIA019-C019A(因爲用 ILI9806E 芯片驅動的面板非常多),我們需要在這個參數表基礎之上做一些調整。

https://github.com/raspberrypi/linux/blob/rpi-6.1.y/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c

  把 RaspberryPI 倉庫裏的參數表移植進我們的 fsl_ili9806e.c 文件裏後,粗粗看了一下注釋,其配置的是 480x800 的屏,極性設置相關也都和 KD050FWFIA019-C019A 有差異。

  最後我們再對照 ILI9806E 數據手冊裏的寄存器定義做一些參數上的微調,如下四個寄存器需要重點關注。這些微調做完之後,把代碼下載進板卡運行,這時候你應該能看到屏開始正常工作了。

  至此,在i.MXRT1170上快速點亮一款全新LCD屏的方法與步驟痞子衡便介紹完畢了,掌聲在哪裏~~~

歡迎訂閱

文章會同時發佈到我的 博客園主頁CSDN主頁知乎主頁微信公衆號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章