《ESP32-S3使用指南—IDF版 V1.6》第三十三章 RGB顯示屏實(shí)驗(yàn)
第三十三章 RGB顯示屏實(shí)驗(yàn)
1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子DNESP32S3開(kāi)發(fā)板
2)章節(jié)摘自【正點(diǎn)原子】ESP32-S3使用指南—IDF版 V1.6
3)購(gòu)買(mǎi)鏈接:https://detail.tmall.com/item.htm?&id=768499342659
4)全套實(shí)驗(yàn)源碼+手冊(cè)+視頻下載地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html
5)正點(diǎn)原子官方B站:https://space.bilibili.com/394620890
6)正點(diǎn)原子DNESP32S3開(kāi)發(fā)板技術(shù)交流群:132780729


ESP32-S3的LCD_CAM控制器由獨(dú)立的LCD模塊和Camera模塊組成。LCD模塊主要用于發(fā)送并行視頻數(shù)據(jù)信號(hào),支持多種接口時(shí)序,如RGB、MOTO6800和I8080。而Camera模塊則用于接收并行視頻數(shù)據(jù)信號(hào),支持DVP 8-/16-bit模式。在本章節(jié)中,我們將首先介紹正點(diǎn)原子的RGBLCD顯示屏的參數(shù)和功能參數(shù),然后詳細(xì)介紹LCD_CAM控制器的LCD模塊,該模塊用于驅(qū)動(dòng)RGBLCD接口。
本章分為如下幾個(gè)小節(jié):
33.1 RGBLCD和LCD模塊接口簡(jiǎn)介
33.2 硬件設(shè)計(jì)
33.3 程序設(shè)計(jì)
33.4 下載驗(yàn)證
33.1 RGBLCD和LCD模塊接口簡(jiǎn)介
33.1.1 RGBLCD簡(jiǎn)介
RGBLCD是基于一組特定的同步信號(hào),該同步信號(hào)指示在哪里開(kāi)始和停止幀。幀緩沖區(qū)分配在ESP側(cè)。因?yàn)樵谶@種情況下我們不需要安裝任何IO接口驅(qū)動(dòng)程序,所以這使得驅(qū)動(dòng)程序的安裝步驟極大簡(jiǎn)化了。接下來(lái)我們就簡(jiǎn)單介紹一些RGBLCD的驅(qū)動(dòng)。
1,RGBLCD的信號(hào)線
RGBLCD的信號(hào)線如表33.1.1.1所示:

表33.1.1.1 RGBLCD信號(hào)線
一般的RGB屏都有如表33.1.1.1所示的信號(hào)線,有24根顏色數(shù)據(jù)線(RGB各8根,即RGB888格式),這樣可以表示最多1600W色,DE、VS、HS和DCLK,用于控制數(shù)據(jù)傳輸。
2,RGBLCD的驅(qū)動(dòng)模式
RGB屏一般有2種驅(qū)動(dòng)模式:DE模式和HV模式。DE模式使用DE信號(hào)來(lái)確定有效數(shù)據(jù)(DE為高/低時(shí),數(shù)據(jù)有效),而HV模式,則需要行同步和場(chǎng)同步,來(lái)表示掃描的行和列。
DE模式和HV模式的行掃描時(shí)序圖(以800*480的LCD面板為例),如圖33.1.1.1所示:

圖33.1.1.1 DE/HV模式行掃描時(shí)序圖
從圖中可以看出,DE和HV模式,時(shí)序基本一樣,DEN模式需要提供DE信號(hào)(DEN),而HV模式,則無(wú)需DE信號(hào)。圖中的HSD即HS信號(hào),用于行同步,注意:在DE模式下面,是可以不用HS信號(hào)的,即不接HS信號(hào),液晶照樣可以正常工作。
圖中的thpw為水平同步有效信號(hào)脈寬,用于表示一行數(shù)據(jù)的開(kāi)始;thb為水平后廊,表示從水平有效信號(hào)開(kāi)始,到有效數(shù)據(jù)輸出之間的像素時(shí)鐘個(gè)數(shù);thfp為水平前廊,表示一行數(shù)據(jù)結(jié)束后,到下一個(gè)水平同步信號(hào)開(kāi)始之前的像素時(shí)鐘個(gè)數(shù)。
圖33.1.1.1僅是一行數(shù)據(jù)的掃描,輸出800個(gè)像素點(diǎn)數(shù)據(jù),而液晶面板總共有480行,這就還需要一個(gè)垂直掃描時(shí)序圖,如圖33.1.1.2所示:

圖33.1.1.2 垂直掃描時(shí)序圖
圖中的VSD就是垂直同步信號(hào),HSD就是水平同步信號(hào),DE為數(shù)據(jù)使能信號(hào)。如圖可知,一個(gè)垂直掃描,剛好就是480個(gè)有效的DE脈沖信號(hào),每一個(gè)DE時(shí)鐘周期,掃描一行,總共掃描480行,完成一幀數(shù)據(jù)的顯示。這就是800480的LCD面板掃描時(shí)序,其他分辨率的LCD面板,時(shí)序類(lèi)似。
圖中的tvpw為垂直同步有效信號(hào)脈寬,用于表示一幀數(shù)據(jù)的開(kāi)始;tvb為垂直后廊,表示垂直同步信號(hào)以后的無(wú)效行數(shù),tvfp為垂直前廊,表示一幀數(shù)據(jù)輸出結(jié)束后,到下一個(gè)垂直同步信號(hào)開(kāi)始之前的無(wú)效行數(shù);這幾個(gè)時(shí)間同樣在配置LTDC的時(shí)候,需要進(jìn)行設(shè)置。
3,正點(diǎn)原子 RGBLCD模塊
正點(diǎn)原子目前提供大家五款 RGBLCD 模塊:ATK-4342(4.3寸,480272)、ATK-4384(4.3寸,800480) ATK-7084(7寸,800480)、 ATK-7016(7 寸,1024600)和ATK-1018(10.1 寸,1280800),這里我們以 ATK-7084 為例,給大家介紹。該模塊的接口原理圖如圖 33.1.1.3 所示:

圖33.1.1.3 RGBLCD模塊對(duì)外接口原理圖
圖中 J3就是對(duì)外接口,是一個(gè)40PIN 的 FPC 座( 0.5mm 間距),通過(guò) FPC 線,可以連接到ESP32-S3 開(kāi)發(fā)板的RGB接口上面,從而實(shí)現(xiàn)和ESP32-S3的連接。該接口十分完善,采用 RGB888 格式,并支持 DE&HV 模式,還支持觸摸屏(電阻/電容)和背光控制。右側(cè)的幾個(gè)電阻,并不是都焊接的,而是可以用戶自己選擇。默認(rèn)情況, R1 和 R6 焊接,設(shè)置 LCD_LR和 LCD_UD,控制 LCD 的掃描方向,是從左到右,從上到下(橫屏看)。而 LCD_R7/G7/B7則用來(lái)設(shè)置 LCD 的 ID,由于 RGBLCD 沒(méi)有讀寫(xiě)寄存器,也就沒(méi)有所謂的 ID,這里我們通過(guò)在模塊上面,控制 R7/G7/B7 的上/下拉,來(lái)自定義 LCD 模塊的 ID,幫助 MCU 判斷當(dāng)前 LCD 面板的分辨率和相關(guān)參數(shù),以提高程序兼容性。這幾個(gè)位的設(shè)置關(guān)系如表33.1.1.2 所示:

表33.1.1.2正點(diǎn)原子 RGBLCD模塊ID對(duì)應(yīng)關(guān)系
這樣我們?cè)诔绦蚶锩妫x取 LCD_R7/G7/B7,得到 M0:M2 的值,從而判斷 RGBLCD 模塊的型號(hào),并執(zhí)行不同的配置,即可實(shí)現(xiàn)不同 LCD模塊的兼容。
更詳細(xì)的RGB屏相關(guān)內(nèi)容,可以參考正點(diǎn)原子提供的《ATK-MD0430R模塊用戶手冊(cè)_V1.0》和《ATK-MD0430R模塊使用說(shuō)明_V1.0》,在這兩個(gè)手冊(cè)中,已經(jīng)詳細(xì)說(shuō)明了RGB的工作原理及相關(guān)參數(shù)信息。
33.1.2 LCD模塊接口簡(jiǎn)介
本小節(jié)主要介紹LCD_CAM控制器的LCD模塊,至于CAMERA模塊講解,作者會(huì)在攝像頭章節(jié)中涉及,下面我們來(lái)看一下LCD模塊的結(jié)構(gòu)框架。

圖33.1.2.1 LCD_CAM控制器結(jié)構(gòu)框架
這個(gè)系統(tǒng)的LCD模塊(即上圖的下方部分)包括以下模塊:一個(gè)獨(dú)立的發(fā)送控制單元(LCD_Ctrl),用于控制LCD的發(fā)送;一個(gè)發(fā)送異步FIFO(Async Tx FIFO),用于與外部設(shè)備交互,發(fā)送數(shù)據(jù);一個(gè)LCD_ClockGenerator時(shí)鐘生成模塊,用于生成對(duì)應(yīng)模塊的時(shí)鐘;以及一個(gè)格式轉(zhuǎn)換模塊,即RGB/YCbCr Converter,用于各種格式的視頻數(shù)據(jù)互相轉(zhuǎn)換。這些模塊協(xié)同工作,確保系統(tǒng)能夠高效、穩(wěn)定地處理和傳輸并行視頻數(shù)據(jù)信號(hào)。
需要讀者注意的是:LCD_CAM的所有信號(hào)均需要經(jīng)過(guò)GPIO交換矩陣映射到芯片管腳。更多信息請(qǐng)參考章節(jié)6 IO MUX和GPIO 交換矩陣(GPIO, IO MUX)。
1,LCD模塊信號(hào)描述
LCD模塊信號(hào)對(duì)應(yīng)了上圖右下角的幾個(gè)信號(hào),它們的具體作用如下所示。

表33.1.2.1 LCD模塊信號(hào)描述
在啟動(dòng)LCD模塊時(shí),信號(hào)的位寬是一個(gè)關(guān)鍵參數(shù)。根據(jù)所接入的LCD的位寬,N的值會(huì)有所不同。如果使用RGBLCD接口連接,并且位寬為16位,則N的值為15。相反,如果接入的LCD使用8位的位寬,則N的值為7。因此,根據(jù)LCD的位寬,可以確定N的具體值。
2,LCD時(shí)鐘選擇
從上圖可以清晰地看到,LCD模塊的時(shí)鐘由三個(gè)不同的時(shí)鐘源提供,它們分別是XTAL_CLK、PLL_D2_CLK和PLL_F160M_CLK。LCD模塊的時(shí)鐘源選擇模式是由寄存器LCD_CAM_LCD_CLOCK_REG中的LCD_CAM_LCD_CLK_SEL位決定的。最后,LCD_Clock Generator時(shí)鐘生成模塊負(fù)責(zé)生成LCD模塊所需的時(shí)鐘,即上圖中的LCD_CLK。
下圖是LCD時(shí)鐘選擇與計(jì)算框圖。

圖33.1.2.2 LCD時(shí)鐘選擇與計(jì)算框圖
LCD_CLK 的頻率 fLCD_CLK 與分頻器時(shí)鐘源頻率 fLCD_CLK_S 間的關(guān)系如下:

其中,2<=N<=256,N對(duì)應(yīng)為L(zhǎng)CD_CAM_LCD_CLOCK_REG寄存器中LCD_CAM_LCD_CLKM_DIV_NUM的值。LCD模塊的像素時(shí)鐘PCLK為L(zhǎng)CD_PCLK信號(hào),由LCD_CLK分頻獲得。計(jì)算公式如下:

其中,MO由寄存器LCD_CAM_LCD_CLK_EQU_SYSCLK和LCD_CAM_LCD_CLKCNT_N決定。最終我們得到了LCD_PCLK時(shí)鐘,該時(shí)鐘經(jīng)過(guò)分頻得到了像素時(shí)鐘 LCD_PCLK。
如果讀者想了解更多的LCD模塊知識(shí),可參考《esp32-s3_technical_reference_manual_cn.pdf》技術(shù)手冊(cè)29章節(jié)內(nèi)容。
33.2 硬件設(shè)計(jì)
33.2.1 例程功能
本章實(shí)驗(yàn)功能簡(jiǎn)介:本實(shí)驗(yàn)利用ESP32-S3開(kāi)發(fā)板的RGB接口來(lái)驅(qū)動(dòng)RGB屏,RGBLCD模塊的接口在核心板上,通過(guò)40P的FPC排線連接RGBLCD模塊,實(shí)現(xiàn)RGBLCD模塊的驅(qū)動(dòng)和顯示,下載成功后,按下復(fù)位之后,就可以看到RGBLCD模塊不停的顯示一些信息并不斷切換底色。同時(shí),屏幕上會(huì)顯示LCD的ID。需要注意的是:DNESP32S3開(kāi)發(fā)板的RGB例程僅支持4.3寸的RGB顯示屏。
33.2.2 硬件資源
- LED燈
LED-IO1 - XL9555
IIC_SDA-IO41
IIC_SCL-IO42 - RGBLCD
LCD_BL-IO1_3(XL9555)
LCD_DE-IO4
LCD_VSYNC-NC
LCD_HSYNC-NC
LCD_PCLK-IO5
LCD_R3-IO45
LCD_R4-IO48
LCD_R5-IO47
LCD_R6-IO21
LCD_R7-IO14
LCD_G2-IO10
LCD_G3-IO9
LCD_G4-IO46
LCD_G5-IO3
LCD_G6-IO8
LCD_G7-IO18
LCD_B3-IO17
LCD_B4-IO16
LCD_B5-IO15
LCD_B6-IO7
LCD_B7-IO6
33.2.3 原理圖
RGB接口與ESP32-S3的連接關(guān)系,如下圖所示:

圖33.2.3.1 RGB接口與ESP32-S3的連接電路圖
33.3 程序設(shè)計(jì)
33.3.1 程序流程圖
程序流程圖能幫助我們更好的理解一個(gè)工程的功能和實(shí)現(xiàn)的過(guò)程,對(duì)學(xué)習(xí)和設(shè)計(jì)工程有很好的主導(dǎo)作用。下面看看本實(shí)驗(yàn)的程序流程圖:

圖33.3.1.1 RGB實(shí)驗(yàn)程序流程圖
33.3.2 RGB-LCD函數(shù)解析
ESP-IDF提供了一套API來(lái)配置RGB。要使用此功能,需要導(dǎo)入必要的頭文件:
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_rgb.h"
接下來(lái),作者將介紹一些常用的ESP32-S3中的RGB函數(shù),這些函數(shù)的描述及其作用如下:
1,創(chuàng)建RGB對(duì)象
該函數(shù)通過(guò)配置結(jié)構(gòu)體參數(shù)的方式將參數(shù)以指針的方式傳進(jìn),該函數(shù)原型如下所示:
esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t
*rgb_panel_config,
esp_lcd_panel_handle_t *ret_panel);
該函數(shù)的形參描述如下表所示:

表33.3.2.1 esp_lcd_new_rgb_panel()函數(shù)形參描述
該函數(shù)的返回值描述,如下表所示:

表33.3.2.2 函數(shù)esp_lcd_new_rgb_panel ()返回值描述
該函數(shù)使用esp_lcd_rgb_panel_config_t類(lèi)型的結(jié)構(gòu)體變量傳入,該結(jié)構(gòu)體的定義如下:

表33.3.2.3 esp_lcd_rgb_panel_config_t結(jié)構(gòu)體參數(shù)值描述
完成上述結(jié)構(gòu)體參數(shù)配置之后,可以將結(jié)構(gòu)傳遞給 esp_lcd_new_rgb_panel() 函數(shù),用以實(shí)例化RGB。
2,復(fù)位RGB屏幕
在創(chuàng)建RGB屏幕對(duì)象后需要進(jìn)行RGB屏幕復(fù)位,該函數(shù)原型如下所示:
esp_err_tesp_lcd_panel_reset(esp_lcd_panel_handle_t panel);
該函數(shù)的形參描述如下表所示:

表33.3.2.4 esp_lcd_panel_reset ()函數(shù)形參描述
該函數(shù)的返回值描述,如下表所示:

表33.3.2.5 函數(shù)esp_lcd_panel_reset ()返回值描述
3,初始化RGB屏幕
通過(guò)上兩個(gè)步驟的配置,可以對(duì)屏幕進(jìn)行初始化了,該函數(shù)原型如下所示:
esp_err_tesp_lcd_panel_init(esp_lcd_panel_handle_t panel);
該函數(shù)的形參描述如下表所示:

表33.3.2.6 esp_lcd_panel_init ()函數(shù)形參描述
該函數(shù)的返回值描述,如下表所示:

表33.3.2.7 函數(shù)esp_lcd_panel_init ()返回值描述
33.3.3 RGB-LCD驅(qū)動(dòng)解析
在IDF版的23_rgb例程中,作者23_rgb\components\BSP路徑下新增了一個(gè)RGB文件夾,分別用于存放ltdc.c、ltdc.h以及l(fā)tdcfont.h這三個(gè)文件。其中,ltdc.h和ltdc.h文件負(fù)責(zé)聲明RGB相關(guān)的函數(shù)和變量并存放了LTDC 字庫(kù),而ltdc.c文件則實(shí)現(xiàn)了RGB的驅(qū)動(dòng)代碼。下面,我們將詳細(xì)解析這三個(gè)文件的實(shí)現(xiàn)內(nèi)容。
1,ltdc.h文件
該文件下定義了屏幕需要用到的一些重要參數(shù),比如引腳定義,RGB顏色的十六進(jìn)制值以及屏幕橫向縱向的方向參數(shù)等。
/* RGB_BL */
#define LCD_BL(x) do { x ? \
xl9555_pin_write(LCD_BL_IO, 1): \
xl9555_pin_write(LCD_BL_IO, 0); \
} while(0)
/* RGBLCD引腳 */
#define GPIO_LCD_DE (GPIO_NUM_4)
#define GPIO_LCD_VSYNC (GPIO_NUM_NC)
#define GPIO_LCD_HSYNC (GPIO_NUM_NC)
#define GPIO_LCD_PCLK (GPIO_NUM_5)
#define GPIO_LCD_R3 (GPIO_NUM_45)
#define GPIO_LCD_R4 (GPIO_NUM_48)
#define GPIO_LCD_R5 (GPIO_NUM_47)
#define GPIO_LCD_R6 (GPIO_NUM_21)
#define GPIO_LCD_R7 (GPIO_NUM_14)
#define GPIO_LCD_G2 (GPIO_NUM_10)
#define GPIO_LCD_G3 (GPIO_NUM_9)
#define GPIO_LCD_G4 (GPIO_NUM_46)
#define GPIO_LCD_G5 (GPIO_NUM_3)
#define GPIO_LCD_G6 (GPIO_NUM_8)
#define GPIO_LCD_G7 (GPIO_NUM_18)
#define GPIO_LCD_B3 (GPIO_NUM_17)
#define GPIO_LCD_B4 (GPIO_NUM_16)
#define GPIO_LCD_B5 (GPIO_NUM_15)
#define GPIO_LCD_B6 (GPIO_NUM_7)
#define GPIO_LCD_B7 (GPIO_NUM_6)
/* 常用畫(huà)筆顏色 */
#define WHITE 0xFFFF /* 白色 */
#define BLACK 0x0000 /* 黑色 */
#define RED 0xF800 /* 紅色 */
#define GREEN 0x07E0 /* 綠色 */
#define BLUE 0x001F /* 藍(lán)色 */
#define MAGENTA 0xF81F /* 品紅色/紫紅色 = BLUE +RED */
#define YELLOW 0xFFE0 /* 黃色 = GREEN +RED */
#define CYAN 0x07FF /* 青色 = GREEN +BLUE */
/* LCD LTDC重要參數(shù)集 */
typedef struct
{
/* LTDC面板的寬度,固定參數(shù),不隨顯示方向改變,如果為0,說(shuō)明沒(méi)有任何RGB屏接入 */
uint32_t pwidth;
uint32_t pheight; /* LTDC面板的高度,固定參數(shù),不隨顯示方向改變 */
uint16_t hsw; /* 水平同步寬度 */
uint16_t vsw; /* 垂直同步寬度 */
uint16_t hbp; /* 水平后廊 */
uint16_t vbp; /* 垂直后廊 */
uint16_t hfp; /* 水平前廊 */
uint16_t vfp; /* 垂直前廊 */
uint8_t activelayer; /* 當(dāng)前層編號(hào):0/1 */
uint8_t dir; /* 0,豎屏;1,橫屏; */
uint16_t id; /* LTDC ID */
uint32_t pclk_hz; /* 設(shè)置像素時(shí)鐘 */
uint16_t width; /* LTDC寬度 */
uint16_t height; /* LTDC高度 */
} _ltdc_dev;
/* LTDC參數(shù) */
extern _ltdc_dev ltdcdev; /* 管理LTDC重要參數(shù) */
extern esp_lcd_panel_handle_t panel_handle;
2,ltdc.c文件
該文件下便是實(shí)現(xiàn)RGB屏幕的驅(qū)動(dòng)函數(shù)了。由于代碼過(guò)長(zhǎng),筆者僅整理出部分代碼粘貼至此,詳細(xì)內(nèi)容請(qǐng)各位讀者進(jìn)入工程界面進(jìn)行理解與學(xué)習(xí)。
static const char *TAG = "ltdc";
esp_lcd_panel_handle_t panel_handle = NULL; /* RGBLCD句柄 */
/* 定義portMUX_TYPE類(lèi)型的自旋鎖變量,用于臨界區(qū)保護(hù) */
static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED;
uint32_t g_back_color = 0xFFFF; /* 背景色 */
/* 管理LTDC重要參數(shù) */
_ltdc_dev ltdcdev;
/**
*@brief LTDC讀取面板ID
*@note 利用LCD RGB線的最高位(R7,G7,B7)來(lái)識(shí)別面板ID
* PG6 = R7(M0); PI2 = G7(M1); PI7 = B7(M2);
* M2:M1:M0
* 0 :0 :0 4.3 寸480*272 RGB屏,ID = 0X4342
* 1 :0 :0 4.3 寸800*480 RGB屏,ID = 0X4384
*@param 無(wú)
*@retval 0, 非法;
* 其他, LCD ID
*/
uint16_t ltdc_panelid_read(void)
{
uint8_t idx = 0;
gpio_config_t gpio_init_struct = {0};
gpio_init_struct.intr_type = GPIO_INTR_DISABLE; /* 失能引腳中斷 */
gpio_init_struct.mode = GPIO_MODE_INPUT; /* 輸入輸出模式 */
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; /* 使能上拉 */
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; /* 失能下拉 */
gpio_init_struct.pin_bit_mask = 1ull << GPIO_LCD_B7;
gpio_config(&gpio_init_struct); /* 配置GPIO */
gpio_init_struct.pin_bit_mask = 1ull << GPIO_LCD_R7 || 1ull << GPIO_LCD_G7;
gpio_config(&gpio_init_struct); /* 配置GPIO */
idx = (uint8_t)gpio_get_level(GPIO_LCD_R7); /* 讀取M0 */
idx|= (uint8_t)gpio_get_level(GPIO_LCD_G7) << 1; /* 讀取M1 */
idx|= (uint8_t)gpio_get_level(GPIO_LCD_B7) << 2; /* 讀取M2 */
switch (idx)
{
case 0 :
return 0X4342; /* 4.3寸屏, 480*272分辨率 */
case 4 :
return 0X4384; /* 4.3寸屏, 800*480分辨率 */
default :
return 0;
}
}
/**
*@brief 初始化ltdc
*@param 無(wú)
*@retval 無(wú)
*/
void ltdc_init(void)
{
panel_handle = NULL;
ltdcdev.id = ltdc_panelid_read(); /* 讀取LCD面板ID */
if (ltdcdev.id == 0X4342) /* 4.3寸屏, 480*272 RGB屏 */
{
ltdcdev.pwidth = 480; /* 面板寬度,單位:像素 */
ltdcdev.pheight = 272; /* 面板高度,單位:像素 */
ltdcdev.hsw = 1; /* 水平同步寬度 */
ltdcdev.vsw = 1; /* 垂直同步寬度 */
ltdcdev.hbp = 40; /* 水平后廊 */
ltdcdev.vbp = 8; /* 垂直后廊 */
ltdcdev.hfp = 5; /* 水平前廊 */
ltdcdev.vfp = 8; /* 垂直前廊 */
ltdcdev.pclk_hz = 9 * 1000 * 1000; /* 設(shè)置像素時(shí)鐘 9Mhz */
}
else if (ltdcdev.id == 0X4384)
{
ltdcdev.pwidth = 800; /* 面板寬度,單位:像素 */
ltdcdev.pheight = 480; /* 面板高度,單位:像素 */
ltdcdev.hbp = 88; /* 水平后廊 */
ltdcdev.hfp = 40; /* 水平前廊 */
ltdcdev.hsw = 48; /* 水平同步寬度 */
ltdcdev.vbp = 32; /* 垂直后廊 */
ltdcdev.vfp = 13; /* 垂直前廊 */
ltdcdev.vsw = 3; /* 垂直同步寬度 */
ltdcdev.pclk_hz = 18 * 1000 * 1000; /* 設(shè)置像素時(shí)鐘 18Mhz */
}
/* 配置RGB參數(shù) */
esp_lcd_rgb_panel_config_t panel_config = { /* RGBLCD配置結(jié)構(gòu)體 */
.data_width = 16, /* 數(shù)據(jù)寬度為16位 */
.psram_trans_align= 64, /* 在PSRAM中分配的緩沖區(qū)的對(duì)齊 */
.clk_src =LCD_CLK_SRC_PLL160M, /* RGBLCD外設(shè)時(shí)鐘源 */
.disp_gpio_num= GPIO_NUM_NC, /* 用于顯示控制信號(hào),不使用設(shè)為-1 */
.pclk_gpio_num=GPIO_LCD_PCLK, /* PCLK信號(hào)引腳 */
.hsync_gpio_num= GPIO_NUM_NC, /* HSYNC信號(hào)引腳,DE模式可不使用 */
.vsync_gpio_num= GPIO_NUM_NC, /* VSYNC信號(hào)引腳,DE模式可不使用 */
.de_gpio_num = GPIO_LCD_DE, /* DE信號(hào)引腳 */
.data_gpio_nums= { /* 數(shù)據(jù)線引腳 */
GPIO_LCD_B3, GPIO_LCD_B4, GPIO_LCD_B5, GPIO_LCD_B6, GPIO_LCD_B7,
GPIO_LCD_G2, GPIO_LCD_G3, GPIO_LCD_G4, GPIO_LCD_G5, GPIO_LCD_G6, GPIO_LCD_G7,
GPIO_LCD_R3, GPIO_LCD_R4, GPIO_LCD_R5, GPIO_LCD_R6, GPIO_LCD_R7,
},
.timings = { /* RGBLCD時(shí)序參數(shù) */
.pclk_hz = ltdcdev.pclk_hz, /* 像素時(shí)鐘頻率 */
.h_res = ltdcdev.pwidth, /* 水平分辨率,即一行中的像素?cái)?shù) */
.v_res = ltdcdev.pheight, /* 垂直分辨率,即幀中的行數(shù) */
/* 水平后廊,hsync和行活動(dòng)數(shù)據(jù)開(kāi)始之間的PCLK數(shù) */
.hsync_back_porch= ltdcdev.hbp,
/* 水平前廊,活動(dòng)數(shù)據(jù)結(jié)束和下一個(gè)hsync之間的PCLK數(shù) */
.hsync_front_porch= ltdcdev.hfp,
.hsync_pulse_width= ltdcdev.vsw, /* 垂直同步寬度,單位:行數(shù) */
/* 垂直后廊,vsync和幀開(kāi)始之間的無(wú)效行數(shù) */
.vsync_back_porch= ltdcdev.vbp,
/* 垂直前廊,幀結(jié)束和下一個(gè)vsync之間的無(wú)效行數(shù) */
.vsync_front_porch= ltdcdev.vfp,
.vsync_pulse_width= ltdcdev.hsw, /* 水平同步寬度,單位:PCLK周期 */
.flags.pclk_active_neg = true, /* RGB數(shù)據(jù)在下降沿計(jì)時(shí) */
},
.flags.fb_in_psram = true, /* 在PSRAM中分配幀緩沖區(qū) */
/* 解決寫(xiě)spiflash時(shí),抖動(dòng)問(wèn)題 */
.bounce_buffer_size_px= (ltdcdev.id == 0X4384) ? 480 * 10 : 272 * 10,
};
/* 創(chuàng)建RGB對(duì)象 */
esp_lcd_new_rgb_panel(&panel_config, &panel_handle);
/* 復(fù)位RGB屏 */
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
/* 初始化RGB */
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
/* 設(shè)置橫屏 */
ltdc_display_dir(1);
/* 清除屏幕為顏色 */
ltdc_clear(WHITE);
/* 打開(kāi)背光 */
LCD_BL(1);
}
/**
*@brief 清除屏幕
*@param color:清除的顏色
*@retval 無(wú)
*/
void ltdc_clear(uint16_t color)
{
uint16_t *buffer = heap_caps_malloc(ltdcdev.width * sizeof(uint16_t), MALLOC_CAP_INTERNAL |
MALLOC_CAP_8BIT);
if (NULL == buffer)
{
ESP_LOGE(TAG, "Memory for bitmap is not enough");
}
else
{
for (uint16_t i = 0; i < ltdcdev.width; i++)
{
buffer = color;
}
for (uint16_t y = 0; y < ltdcdev.height; y++)
{/*使用taskENTER_CRITICAL()和taskEXIT_CRITICAL()保護(hù)畫(huà)點(diǎn)過(guò)程,禁止任務(wù)調(diào)度*/
taskENTER_CRITICAL(&my_spinlock); /* 屏蔽中斷 */
esp_lcd_panel_draw_bitmap(panel_handle,
0,
y,
ltdcdev.width,
y + 1,
buffer);
taskEXIT_CRITICAL(&my_spinlock); /* 重新使能中斷 */
}
heap_caps_free(buffer);
}
}
33.3.4 CMakeLists.txt文件
打開(kāi)本實(shí)驗(yàn)BSP下的CMakeLists.txt文件,其內(nèi)容如下所示:
set(src_dirs
IIC
LED
XL9555
RGBLCD)
set(include_dirs
IIC
LED
XL9555
RGBLCD)
set(requires
driver
esp_lcd
esp_common
log)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
上述的紅色標(biāo)注部分驅(qū)動(dòng)需要由開(kāi)發(fā)者自行添加,以確保RGB屏幕驅(qū)動(dòng)能夠順利集成到構(gòu)建系統(tǒng)中。這一步驟是必不可少的,它確保了RGB驅(qū)動(dòng)的正確性和可用性,為后續(xù)的開(kāi)發(fā)工作提供了堅(jiān)實(shí)的基礎(chǔ)。
33.3.5 實(shí)驗(yàn)應(yīng)用代碼
打開(kāi)main/main.c文件,該文件定義了工程入口函數(shù),名為app_main。該函數(shù)代碼如下。
i2c_obj_t i2c0_master;
/**
*@brief 程序入口
*@param 無(wú)
*@retval 無(wú)
*/
void app_main(void)
{
uint8_t x = 0;
uint8_t lcd_id[12];
esp_err_t ret;
ret=nvs_flash_init(); /* 初始化NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret =nvs_flash_init();
}
led_init(); /* 初始化LED */
i2c0_master = iic_init(I2C_NUM_0); /* 初始化IIC0 */
xl9555_init(i2c0_master); /* IO擴(kuò)展芯片初始化 */
ltdc_init(); /* RGB屏初始化 */
sprintf((char *)lcd_id, "LCDID:%04X", ltdcdev.id);/*將ID打印到lcd_id數(shù)組*/
while (1)
{
switch (x)
{
case 0:
ltdc_clear(WHITE);
break;
case 1:
ltdc_clear(BLACK);
break;
case 2:
ltdc_clear(BLUE);
break;
case 3:
ltdc_clear(RED);
break;
case 4:
ltdc_clear(MAGENTA);
break;
case 5:
ltdc_clear(GREEN);
break;
case 6:
ltdc_clear(CYAN);
break;
case 7:
ltdc_clear(YELLOW);
break;
}
ltdc_show_string(10, 40, 240, 32, 32, "ESP32S3", RED);
ltdc_show_string(10, 80, 240, 24, 24, "LTDCTEST", RED);
ltdc_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
ltdc_show_string(10, 130, 240, 16, 16, (char *)lcd_id, RED);/* LCD ID */
x++;
if (x == 8)
{
x = 0;
}
vTaskDelay(1000);
}
}
main函數(shù)功能主要是顯示一些固定的字符,字體大小包括3216、2412、168和126四種,同時(shí)顯示RGB-LCD驅(qū)動(dòng)IC的型號(hào),然后不停的切換背景顏色,每1s切換一次。其中我們用到一個(gè)sprintf的函數(shù),該函數(shù)用法同printf,只是sprintf把打印內(nèi)容輸出到指定的內(nèi)存區(qū)間上,最終在死循環(huán)中通過(guò)ltdc_show_strinig函數(shù)進(jìn)行屏幕顯示,sprintf的詳細(xì)用法,請(qǐng)百度學(xué)習(xí)。
33.4 下載驗(yàn)證
在初始化完RGB-LCD屏幕后,便在RGB-LCD上顯示一些本實(shí)驗(yàn)的相關(guān)信息,隨后便每間隔1000毫秒就更換一次RGB-LCD屏幕顯示的背景色。

浙公網(wǎng)安備 33010602011771號(hào)