動(dòng)ST7789P3屏幕:SPI接口初始化命令全解析)
這次我們來看一塊非常常見、但經(jīng)常把人卡在“白屏”或“花屏”上的屏ST7789P3。這類驅(qū)動(dòng) IC 大量出現(xiàn)在 1.86 寸 IPS LCD 模組上尤其是 ESP32-S3 開發(fā)板的配套屏幕里。很多朋友把 SPI 線接好代碼也編譯通過了結(jié)果屏幕要么全白、要么顏色發(fā)紫、要么上下顛倒最終問題基本都出在初始化命令序列上。這篇文章不繞彎子直接講清楚兩件事ST7789P3 通過 SPI 接口時(shí)哪些命令是必發(fā)的這些命令到底在干什么在 ESP-IDF 框架下怎么用 C 語言和 FreeRTOS 把這套流程跑起來并提供一個(gè)便于排查的思路。如果你正在做 ESP32-S3 嵌入式 AI 物聯(lián)網(wǎng)項(xiàng)目后續(xù)打算把模型推理結(jié)果、傳感器數(shù)據(jù)、調(diào)試日志顯示在 1.86 寸屏上那建議把這篇收藏。SPI 驅(qū)動(dòng) ST7789P3 的命令規(guī)范是芯片級(jí)通用的不只是 ESP32-S3 能用STM32、樹莓派 Pico、Arduino 接同一塊屏?xí)r命令序列也是一套。1. 核心能力速覽先把 ST7789P3 ESP32-S3 這套組合的關(guān)鍵信息列出來方便判斷這個(gè)方案是否適合你。能力項(xiàng)說明驅(qū)動(dòng)芯片ST7789P3ST7789 系列衍生型號(hào)命令與 ST7789V 高度兼容接口方式4 線 SPISCLK / MOSI / CS / DC另有 RES 復(fù)位和 BLK 背光常見分辨率240x320、240x280具體以模組規(guī)格書為準(zhǔn)像素格式RGB565、RGB666最常用 RGB565驅(qū)動(dòng)框架ESP-IDF v5.x 的 esp_lcd 組件或手寫 SPI Master FreeRTOS核心命令數(shù)量基礎(chǔ)必發(fā)約 10 條廠商調(diào)優(yōu)命令按規(guī)格書補(bǔ)充支持平臺(tái)ESP32-S3 / ESP32 / STM32 等任意 SPI 主機(jī)API 服務(wù)本文不涉及 HTTP/網(wǎng)絡(luò) API但 SPI 驅(qū)動(dòng)本身支持批量事務(wù)批量刷新支持按矩形窗口刷新、分塊刷新、雙緩沖預(yù)留適用場(chǎng)景桌面看板、AI 推理結(jié)果展示、傳感器數(shù)據(jù)可視化、無線調(diào)試器本地顯示這塊屏的核心價(jià)值不是性能有多強(qiáng)而是“小巧 接口簡(jiǎn)單 資料多”。ESP32-S3 的 SPI 外設(shè)跑到 20MHz 或 40MHz 驅(qū)動(dòng) 240x320 的 RGB565 屏幕足夠日常顯示。關(guān)鍵是要把命令順序發(fā)對(duì)否則性能再好也是白屏。2. 適用場(chǎng)景與使用邊界ST7789P3 適合誰先說結(jié)論適合需要一塊小型彩色屏但不想引入太復(fù)雜硬件設(shè)計(jì)的項(xiàng)目。典型場(chǎng)景有這幾類ESP32-S3 嵌入式 AI 物聯(lián)網(wǎng)項(xiàng)目顯示識(shí)別結(jié)果、模型置信度、推理耗時(shí)、傳感器曲線比串口日志直觀得多。無線 AI 調(diào)試器通過 WiFi 接收上位機(jī)或另一塊開發(fā)板發(fā)來的調(diào)試數(shù)據(jù)實(shí)時(shí)在屏幕上顯示狀態(tài)。桌面小工具時(shí)鐘、天氣、歌詞顯示、系統(tǒng)監(jiān)控面板。學(xué)習(xí) ST7789 命令時(shí)序和 ESP-IDF SPI 驅(qū)動(dòng)原理的實(shí)驗(yàn)板。需要注意使用邊界ST7789P3 不是大屏1.86 寸顯示信息量有限不要指望它做復(fù)雜的數(shù)據(jù)可視化。屏幕刷新需要占用 SPI 總線如果 SPI 總線上還掛了 SD 卡、Flash 等其他設(shè)備要注意總線占用和沖突。實(shí)時(shí)性要求很高的動(dòng)畫場(chǎng)景需要考慮一幀刷新耗時(shí)。20MHz 下 240x320 全屏 RGB565 的理論傳輸時(shí)間約 61ms實(shí)際幀率會(huì)低于理論值。涉及圖像顯示時(shí)注意素材版權(quán)。顯示人物照片、品牌 Logo、受版權(quán)保護(hù)的圖片要確認(rèn)授權(quán)。本地開發(fā)和測(cè)試場(chǎng)景盡量使用自繪或無版權(quán)素材。另外如果你的項(xiàng)目要接入 WiFi、BLE 或 AI 推理屏幕驅(qū)動(dòng)只是其中一個(gè)模塊。建議把顯示任務(wù)和業(yè)務(wù)任務(wù)用 FreeRTOS 解耦避免屏幕刷屏卡住主流程。3. SPI 接口與接線準(zhǔn)備先看硬件連接。ST7789P3 模組通常引出 7 到 9 個(gè)引腳其中與 SPI 相關(guān)的核心引腳如下。信號(hào)方向作用接線說明SCLK / SCK輸入SPI 時(shí)鐘接 ESP32-S3 SPI 時(shí)鐘腳MOSI / SDA輸入SPI 數(shù)據(jù)接 ESP32-S3 MOSI屏幕只寫不讀時(shí) MISO 可不接CS輸入片選低電平有效DC輸入命令/數(shù)據(jù)選擇低電平發(fā)命令高電平發(fā)數(shù)據(jù)RES / RST輸入硬件復(fù)位低電平復(fù)位需外部拉高或由 MCU 控制BLK / LEDA輸入背光控制接 GPIO 高電平點(diǎn)亮或接 PWM 調(diào)光接線時(shí)注意三個(gè)點(diǎn)第一DC 腳不能省。ST7789P3 的 SPI 是“命令/數(shù)據(jù)共線”靠 DC 電平區(qū)分傳輸類型。某些模組設(shè)計(jì)成 3 線 SPI也就是把命令和數(shù)據(jù)通過 9 bit SPI 封裝區(qū)分那種情況不需要 DC 腳但本文以最常見的 4 線 SPI 為例。第二CS 可以用硬件片選。ESP-IDF 的 SPI 主機(jī)支持硬件 CS給spi_device_interface_config_t配置spics_io_num即可不需要手動(dòng)拉 CS。但 DC 必須由 GPIO 手動(dòng)控制因?yàn)樗诿看蝹鬏斍耙獏^(qū)分命令和數(shù)據(jù)。第三背光腳必須處理。很多模組默認(rèn)背光亮但有些模組需要外部拉高。如果代碼全部初始化正確但屏幕是黑的先檢查 BLK 是否處于有效電平。下面是一組通用接線參考實(shí)際引腳按你自己的開發(fā)板調(diào)整#define PIN_SCLK GPIO_NUM_12 #define PIN_MOSI GPIO_NUM_11 #define PIN_DC GPIO_NUM_10 #define PIN_CS GPIO_NUM_9 #define PIN_RST GPIO_NUM_8 #define PIN_BL GPIO_NUM_7這組引腳不是標(biāo)準(zhǔn)答案只是常見參考。實(shí)戰(zhàn)派一類的 ESP32-S3 開發(fā)板屏幕引腳一般會(huì)印在 PCB 上或者查原理圖確認(rèn)。4. ST7789P3 常用命令拆解這是本文的重頭戲。ST7789P3 和 ST7789V 一樣是一顆 MIPI DCS 兼容的顯示驅(qū)動(dòng) IC。命令本身不復(fù)雜但順序錯(cuò)了就會(huì)白屏或花屏。下面按初始化流程逐個(gè)拆。4.1 軟件復(fù)位 SWRESET0x01開機(jī)后建議先發(fā)軟件復(fù)位。雖然硬件 RES 引腳也能復(fù)位但軟件復(fù)位更保險(xiǎn)尤其在代碼啟動(dòng)時(shí)序不穩(wěn)定的情況下。發(fā)送方式CMD(0x01);復(fù)位后需要延時(shí)。一般延時(shí) 120ms 是比較穩(wěn)妥的做法。緊跟著應(yīng)發(fā)送退出睡眠命令。4.2 退出睡眠 SLPOUT0x11ST7789P3 上電后默認(rèn)處于睡眠模式此時(shí)屏幕不顯示內(nèi)容。SLPOUT是初始化中最重要的命令之一如果漏掉屏幕就會(huì)一直黑著。CMD(0x11); // SLPOUT vTaskDelay(pdMS_TO_TICKS(120));這個(gè)命令之后必須給足夠延時(shí)。數(shù)據(jù)手冊(cè)通常要求 120ms 左右工程上直接延時(shí) 120ms 即可。延時(shí)不夠容易導(dǎo)致后續(xù)命令沒被正確執(zhí)行表現(xiàn)就是偶爾白屏或顯示異常。4.3 像素格式 COLMOD0x3AST7789P3 支持多種顏色深度。最常用的是 RGB565也就是 16 位色色彩信息壓縮到每像素 2 字節(jié)。CMD(0x3A); lcd_write_data(0x55); // RGB565參數(shù)說明參數(shù)值含義0x5516 位 / 像素RGB565最常用0x6618 位 / 像素RGB666顏色更準(zhǔn)但傳輸量更大0x7724 位 / 像素傳輸量最大不推薦在 ESP32 上使用ESP32-S3 的 SPI 外設(shè)可以直接送 16 位像素流。如果選了 18 位單個(gè)像素需要 3 字節(jié)刷新速度和幀緩沖占用都會(huì)增加。一般項(xiàng)目用 0x55 足夠。4.4 內(nèi)存訪問控制 MADCTL0x36MADCTL 是另一個(gè)容易翻車的命令。它控制顯示方向、RGB/BGR 順序、行列鏡像。CMD(0x36); lcd_write_data(0x00);MADCTL 的 8 個(gè) bit 含義如下Bit符號(hào)作用7MY行方向翻轉(zhuǎn)6MX列方向翻轉(zhuǎn)5MV行列交換旋轉(zhuǎn) 90 度4ML垂直刷新方向3BGR1 為 BGR0 為 RGB2MH水平刷新方向1-0-保留實(shí)際使用時(shí)常見的幾個(gè)值0x00豎屏RGB 順序通常配合 240x320 面板。0x60即 MX MV常用于橫屏配合 320x240 使用。0xA0即 MY MV另一種橫屏方向。0xC0即 MX MY相當(dāng)于原始方向旋轉(zhuǎn) 180 度。0x08在 0x00 基礎(chǔ)上換成 BGR 順序。屏幕顯示方向沒有絕對(duì)正確因?yàn)槟=M綁定到開發(fā)板時(shí)排線方向可能不同。調(diào)試時(shí)先把 MADCTL 設(shè)為 0x00畫一個(gè)矩形如果上下顛倒就加 MY左右顛倒就加 MX橫豎顛倒就加 MV。顏色不對(duì)就切換 bit3。4.5 反色控制 INVON / INVOFF0x21 / 0x20ST7789P3 的內(nèi)存數(shù)據(jù)和實(shí)際顯示顏色之間有一個(gè)可選的反色開關(guān)。同一個(gè)命令序列在不同模組上顯示效果可能正好相反有的模組需要INVON有的需要INVOFF。CMD(0x21); // INVON如果顏色發(fā)傻試試 0x20判斷方法很簡(jiǎn)單先按 0x21 發(fā)如果顯示白色背景但看起來是黑色、或者顏色明顯異常就把命令改成 0x20。ST7789 系列屏幕常見的“紅色變藍(lán)色”“白色變黑色”一半原因是 BGR 位錯(cuò)了另一半就是反色命令反了。4.6 列地址設(shè)置 CASET0x2ACASET 用于設(shè)置刷屏區(qū)域的列范圍。發(fā)送 4 字節(jié)參數(shù)依次是 X 起始高字節(jié)、X 起始低字節(jié)、X 結(jié)束高字節(jié)、X 結(jié)束低字節(jié)。以 240x320 全屏為例CMD(0x2A); uint8_t caset[] {0x00, 0x00, 0x00, 0xEF}; // X: 0 到 239 lcd_write_data_bytes(caset, 4);4.7 行地址設(shè)置 RASET0x2BRASET 和 CASET 類似設(shè)置行范圍。同樣是 4 字節(jié)參數(shù)。CMD(0x2B); uint8_t raset[] {0x00, 0x00, 0x01, 0x3F}; // Y: 0 到 319 lcd_write_data_bytes(raset, 4);有的模組在上電后并不從 0 開始顯示而是在左上角存在偏移比如某些 1.86 寸屏幕需要把起始地址偏置 20 或 40 像素。遇到“全屏內(nèi)容錯(cuò)位、畫面整體向右下方偏移”的情況需要根據(jù)模組規(guī)格書在 CASET/RASET 基礎(chǔ)上加偏移量。4.8 寫顯存 RAMWR0x2C地址窗口設(shè)好后發(fā)送RAMWR接下來所有 SPI 數(shù)據(jù)都會(huì)被寫入 GRAM。寫入順序從地址窗口左上角開始按行從左到右、從上到下連續(xù)寫入。CMD(0x2C);之后設(shè)置 DC 為高電平連續(xù)發(fā)送 RGB565 像素?cái)?shù)據(jù)即可。數(shù)據(jù)字節(jié)序通常是高字節(jié)在前也就是顏色0xF800先發(fā)0xF8再發(fā)0x00。如果顏色看起來每個(gè)像素都被拆成兩半大概率是字節(jié)序問題。4.9 讀顯存 RAMRD0x2ERAMRD讀取 GRAM 內(nèi)容一般用于屏幕截圖或回讀校驗(yàn)。但很多模組沒有把 MISO 接到 MCU 上這種模組就用不了讀命令。如果 SPI 總線只接了 MOSI直接跳過這條命令。4.10 正常顯示模式 NORON0x13初始化時(shí)發(fā)送NORON讓屏幕進(jìn)入正常顯示模式。這個(gè)命令一般放在睡眠退出之后、顯示開啟之前。CMD(0x13);有些初始化序列還會(huì)在0x13之前發(fā)送0x12PON 部分顯示模式或者0x14反色部分模式但工程上常規(guī)流程不需要。4.11 顯示開啟 DISPON0x29最后一條必發(fā)命令是DISPON。發(fā)送后屏幕真正開始顯示內(nèi)容。CMD(0x29); vTaskDelay(pdMS_TO_TICKS(20));4.12 撕裂效果控制 TE0x350x35開啟撕裂效果信號(hào)。如果使用 GPIO 監(jiān)視 TE 引腳可以在刷新前等待垂直同步避免畫面撕裂。沒有 TE 引腳時(shí)跳過即可。4.13 廠商調(diào)優(yōu)命令ST7789P3 的數(shù)據(jù)手冊(cè)里還有一組廠商命令比如電源控制、柵極控制、Gamma 校正等命令功能0xB2Porch 控制0xB7柵極控制0xBBVCOM 設(shè)置0xC0LCM 控制0xC2VDV 與 VRH 命令相等設(shè)置0xC3VRH 設(shè)置0xC4VDV 設(shè)置0xC6幀率控制0xD0電源控制 10xE0 / 0xE1正負(fù) Gamma 校正這組命令的值通常由模組廠出廠時(shí)確定。很多開源屏幕驅(qū)動(dòng)會(huì)直接內(nèi)置一組 ST7789V 的通用值但不同模組之間存在差異盲目照抄可能對(duì)比度偏低或偏色。最穩(wěn)妥的做法是找你的模組規(guī)格書把電源和 Gamma 部分按 PDF 里的推薦值填進(jìn)去。如果只是做基礎(chǔ)顯示前 11 條命令已經(jīng)足夠點(diǎn)亮屏幕。5. ESP32-S3 本地部署環(huán)境準(zhǔn)備接下來說代碼側(cè)。推薦使用 ESP-IDF v5.x 版本原因很簡(jiǎn)單v5.x 內(nèi)置esp_lcd組件ST7789 面板驅(qū)動(dòng)開箱即用不需要手寫復(fù)雜命令序列。安裝和初始化 ESP-IDF 的基本流程如下# 選擇你要使用的 IDF 分支例如 v5.2 git clone -b v5.2 --recursive https://github.com/espressif/esp-idf.git # 進(jìn)入 IDF 目錄運(yùn)行安裝腳本Linux / macOS ./install.sh esp32s3 # 導(dǎo)出環(huán)境變量 source export.shWindows 用戶可以直接使用 Espressif 官方提供的 IDF Tools 安裝器圖形界面選擇 ESP32-S3 工具鏈。創(chuàng)建工程后先設(shè)置目標(biāo)芯片idf.py set-target esp32s3編譯和燒錄