各位佬好 ! 目前在做毕业设计阶段,使用到了ST77903的这颗IC驱动,但目前根据您所发布的博客已经能够初始化出测试彩条,但一直无法进入写像素模式,所以无法进行刷屏以及后续操作,这个问题也卡了我很多天了,希望能够得到一些指导,而且由于刚开始接触使用ESP32,对PSRAM的操作不熟悉,无法将数组定义到psram,内部ram又不足以存储一帧图像,这里同样求指导 ,所以我缩减了一下数组大小,尝试先刷一部分但还是不行。
以下是我使用的平台:
ESP32S3-FH4R2 ESPIDF-v4.4.4
以下是时序图
//宏
#define LCD_BPP (24)
#define LCD_X_SIZE (400) /* available x pixel size */
#define LCD_Y_SIZE (100) /* available y pixle size */
#define LCD_PBYTE ((LCD_BPP + 7) / 8) /* bytes in pixel unit */
#define LCD_HBYTE (LCD_X_SIZE * LCD_PBYTE) /* bytes in horizontal line */
#define LCD_VSW (1U)
#define LCD_HFP (8U)
#define LCD_HBP (8U)
#define LCD_TE_OFT (25U)
#define FRAME_BLANKING_TIME (10U)
#define FRAME_MEM_SIZE (LCD_HBYTE * LCD_Y_SIZE)
#define FRAME_MEM_BASE 0x3D000000
#define SRAM_AXI_SIZE 10
//#if (FRAME_MEM_SIZE > SRAM_AXI_SIZE)
// #error "lcdqspi frame cache size is not enough!"
//#endif
//初始化列表
static const init_line_t init_table[] = {
{0xf0, 1, {0xc3}},
{0xf0, 1, {0x96}},
{0xf0, 1, {0xa5}},
{0xe9, 1, {0x20}},
{0xe7, 4, {0x80, 0x77, 0x1f, 0xcc}},
{0xc1, 4, {0x77, 0x07, 0xc2, 0x07}},
{0xc2, 4, {0x77, 0x07, 0xc2, 0x07}},
{0xc3, 4, {0x22, 0x02, 0x22, 0x04}},
{0xc4, 4, {0x22, 0x02, 0x22, 0x04}},
{0xc5, 1, {0x71}},
{0xe0, 14, {0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f}},
{0xe1, 14, {0x87, 0x09, 0x0c, 0x06, 0x05, 0x03, 0x29, 0x32, 0x49, 0x0f, 0x1b, 0x17, 0x2a, 0x2f}},
{0xe5, 14, {0xb2, 0xf5, 0xbd, 0x24, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}},
{0xe6, 14, {0xb2, 0xf5, 0xbd, 0x24, 0x22, 0x25, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}},
{0xec, 2, {0x40, 0x03}},
{0x36, 1, {0x0c}},
{0x3a, 1, {0x07}},//RGB显示格式初始化 101:565 / 110 :666 / 111:888
{0xb2, 1, {0x00}},
{0xb3, 1, {0x01}},
{0xb4, 1, {0x00}},
{0xb5, 4, {0x00, 0x08, 0x00, 0x08}},
{0xb6, 2, {0xc7, 0x31}},
{0xa5, 9, {0x00, 0x00, 0x00, 0x00, 0x20, 0x15, 0x2a, 0x8a, 0x02}},
{0xa6, 9, {0x00, 0x00, 0x00, 0x00, 0x20, 0x15, 0x2a, 0x8a, 0x02}},
{0xba, 7, {0x0a, 0x5a, 0x23, 0x10, 0x25, 0x02, 0x00}},
{0xbb, 8, {0x00, 0x30, 0x00, 0x29, 0x88, 0x87, 0x18, 0x00}},
{0xbc, 8, {0x00, 0x30, 0x00, 0x29, 0x88, 0x87, 0x18, 0x00}},
{0xbd, 11, {0xa1, 0xb2, 0x2b, 0x1a, 0x56, 0x43, 0x34, 0x65, 0xff, 0xff, 0x0f}},
{0x35, 1, {0x00}},
{0x21, 1, {0x00}},
{0x11, 1, {0x00}},
{0xff, 1, {120}},
{0x29, 1, {0x00}}, // DISPON-0X29 /DISPOFF-0X28
{0xff, 1, {120}},
#ifdef BIST_MODE
{0xb0, 1, {0xa5}},
{0xcc, 9, {0x40, 0x00, 0x3f, 0x00, 0x14, 0x14, 0x20, 0x20, 0x03}},
#endif
};
//初始化函数
void lcd_qspi_bus_init(void)
{
esp_err_t ret;
spi_bus_config_t busConfig = {
.sclk_io_num = LCD_QSPI_CLK,
// .mosi_io_num = LCD_QSPI_100,
// .miso_io_num = LCD_QSPI_101,
// .quadwp_io_num = LCD_QSPI_102,
// .quadhd_io_num = LCD_QSPI_103,
.data0_io_num = LCD_QSPI_100,
.data1_io_num = LCD_QSPI_101,
.data2_io_num = LCD_QSPI_102,
.data3_io_num = LCD_QSPI_103,
.max_transfer_sz = 4092,
//.intr_flags = ,
.flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_QUAD,
};
ret = spi_bus_initialize(LCD_SPI_HOST, &busConfig,SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
spi_device_interface_config_t ifConfig = {
.clock_speed_hz = SPI_MASTER_FREQ_8M,
.spics_io_num = LCD_SPI_CS,
.mode = 3,
.queue_size = 7,
.address_bits = 8,
.command_bits = 24,
.flags = SPI_DEVICE_HALFDUPLEX,
};
ret = spi_bus_add_device(LCD_SPI_HOST, &ifConfig, &lcd_bus_handle);
ESP_ERROR_CHECK(ret);
ESP_LOGI("spi_bus_initialize","OK");
}
/* lcd transmit, write command, write display data */
static void lcd_transmit(uint32_t cmd, uint32_t len, uint8_t *dat)
{
esp_err_t ret;
spi_transaction_ext_t tr_ext_Config = {
.command_bits = 8,
.address_bits = 24,
.dummy_bits = 0,
.base.addr = cmd << 8,
.base.cmd = 0XDE,
.base.length= 8 * len,
.base.tx_buffer = dat,
.base.rx_buffer = NULL,
.base.flags = SPI_TRANS_VARIABLE_CMD| SPI_TRANS_VARIABLE_ADDR,
};
ret = spi_device_polling_transmit(lcd_bus_handle, &tr_ext_Config.base);
if (ret != ESP_OK)ESP_LOGW("lcd_transmit","ERROR 0x%x",cmd);
}
//写像素
static void lcd_transmit_pixel(uint32_t cmd, uint32_t len, uint8_t *dat)
{
spi_transaction_ext_t tr_ext_Config = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.base.addr = 0,
.base.cmd = 0,
.base.length= 8 * len,
.base.tx_buffer = dat,
.base.rx_buffer = NULL,
.base.flags = ( SPI_TRANS_MODE_QIO),
};
spi_device_polling_transmit(lcd_bus_handle, &tr_ext_Config.base);
}
//发送到lcd的函数
void lcdqspi_thread_entry(void)
{
uint32_t i = 0;
/* vs(0x61) packet */
for (i = 0; i < LCD_VSW; i++)
{
lcd_transmit(0x61, 1, 0x00);
//delay_us_timr(50);
usleep(40);
}
/* hbp(0x60) packet */
for (i = 0; i < LCD_HBP; i++)
{
lcd_transmit(0x60, 1, 0x00);
//delay_us_timr(50);
usleep(40);
}
/* transmit display cache data to lcd line by line */
for (i = 0; i < LCD_Y_SIZE; i++)
{
lcd_transmit(0x60, 1, 0x00);
//lcd_transmit_pixel(0x00, LCD_HBYTE, color_buf);
lcd_transmit_pixel(0x00, LCD_HBYTE, &frame_cache[i][0]);
}
/* hfp(0x60) packet */
for (i = 0; i < LCD_HFP; i++)
{
lcd_transmit(0x60, 1, 0x00);
delay_us_timr(40);
}
/* transmit is complet, can update frame cache in blanking time */
delay_ms(FRAME_BLANKING_TIME);
}
函数调用关系
以下答案基于ChatGPT与GISer Liu编写:
你好,根据你提供的代码和说明,我能看到你正在使用 ESP32S3 平台,使用 ST77903 驱动控制液晶显示。你已经成功初始化了液晶,并能够显示测试彩条。然而,你遇到了问题,无法进入像素写入模式,以刷屏和显示图像。此外,你还遇到了内存不足的问题,导致你无法存储一帧完整的图像到内存中。我将根据你提供的信息提供一些可能有用的建议。
1.首先,我注意到你定义了LCD_X_SIZE和LCD_Y_SIZE宏,它们分别表示屏幕的宽度和高度。你也定义了LCD_BPP宏,表示每个像素的位深度。在这里,你将位深度设置为 24,这意味着你的每个像素将占用 24 位或 3 字节。此外,你定义了LCD_PBYTE宏,表示每个像素的字节数,以及LCD_HBYTE宏,表示每行的字节数。
2.在写入像素数据之前,你需要确保 ST77903 进入了写入模式。在你提供的初始化列表中,我无法找到设置写入模式的命令。通常,这需要发送一些特定的命令序列,如清除屏幕或写入像素数据命令。因此,我建议你仔细阅读 ST77903 数据手册中关于写入模式的章节,并确保你的初始化列表包括正确的命令序列,以将 ST77903 切换到写入模式。
3.关于内存问题,ESP32S3 平台提供了内置的 SRAM 和外部 PSRAM。你可以通过ps_malloc()和ps_calloc()等函数在 PSRAM 中分配内存。请注意,如果你要在 PSRAM 中分配内存,你需要在sdkconfig.h文件中将CONFIG_ESP32S3_PSRAM_USE_ENABLE宏设置为 1。在使用ps_malloc()或ps_calloc()分配内存之前,你需要调用psramFound()函数检查 PSRAM 是否存在。如果 PSRAM 存在,该函数将返回 true。如果不存在,则需要在硬件上进行修复或更换。如果你的液晶分辨率非常高,导致内存不足,你可能需要考虑使用内存映射文件或流数据,而不是将整个图像加载到内存中。
希望这些建议能够帮助你解决问题。如果你仍然遇到问题,或者需要更多帮助,请告诉我。
你已经成功初始化了ST77903,但是无法进入写像素模式,可能是时序不正确导致的
PSRAM的内存可以通过内存池分配。
在配置里先开启PSRAM,选择PSRAM类型,你可以把PSRAM加入到通用的内存池进行统一分配,后面用malloc分配即可,也可以通过专用的内存池来进行分配。