大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是在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主頁、知乎主頁、微信公衆號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。