2025-12-23 10:17 AM - edited 2025-12-23 10:50 AM
I am trying to configure an 8080 16-bit parallel LCD using FMC on an STM32H5563 development board, but it is inconsistent and unstable. I am getting a logic analyzer and will be able to provide screenshots of the signals in a bit.
Tutorials I have referenced:
Issue:
My test code initializes the display and then alternates filling the entire screen between red and white.
Not sure how to debug this further or what to try next. I had this same display working pretty well via SPI on a different H5 micro and board using mostly the same driver code.
Hardware used:
Configuration:
Main
ST7789_Init();
while (1)
{
DISPLAY_FillScreen(WHITE);
HAL_Delay(10);
DISPLAY_FillScreen(RED);
}
Display Driver (code snippets to include what is necessary, merged together .c/.h)
#define FMC_BANK1_REG (uint32_t) 0x60000000
#define FMC_BANK1_DATA (uint32_t) 0x60080000
uint16_t DISPLAY_WIDTH = 320;
uint16_t DISPLAY_HEIGHT = 240;
#define MADCTL_MX 0x40 // Column address order
#define MADCTL_MV 0x20 // Row/column exchange
#define MADCTL_COLORDER 0x00 // Color order (0x08=BGR, 0x00=RGB)
#define ROTATION_90 (MADCTL_MX | MADCTL_MV | MADCTL_COLORDER) // 90° Landscape
#define DISPLAY_RST_GPIO_Port GPIOC
#define DISPLAY_RST_Pin GPIO_PIN_6
#define DISPLAY_RST_Clr() HAL_GPIO_WritePin(DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, GPIO_PIN_RESET)
#define DISPLAY_RST_Set() HAL_GPIO_WritePin(DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, GPIO_PIN_SET)
void WriteSmallData(uint8_t data) {
*(volatile uint16_t *) (FMC_BANK1_DATA) = (data);
}
void WriteCommand(uint16_t cmd) {
*(volatile uint16_t *) (FMC_BANK1_REG) = (cmd);
}
void WriteData16(const uint16_t *buff, size_t pixel_count) {
volatile uint16_t *dst = (volatile uint16_t *)FMC_BANK1_DATA;
for (size_t i = 0; i < pixel_count; i++) {
*dst = buff[i];
}
}
void WriteData16(const uint16_t *buff, size_t pixel_count) {
volatile uint16_t *dst = (volatile uint16_t *)FMC_BANK1_DATA;
for (size_t i = 0; i < pixel_count; i++) {
*dst = buff[i];
}
}
void ST7789_Init(void) {
// Hardware reset
DISPLAY_RST_Clr();
HAL_Delay(250);
DISPLAY_RST_Set();
HAL_Delay(250);
// Exit sleep mode first
WriteCommand(CMD_DISPOFF);
WriteCommand(CMD_SLPOUT);
HAL_Delay(10);
// MADCTL: memory data access control & rotation
WriteCommand(CMD_MADCTL);
WriteSmallData(ROTATION_90);
// Color mode
WriteCommand(CMD_COLMOD);
WriteSmallData(COLMOD_16BIT);
// Porch control
WriteCommand(CMD_PORCTRL);
uint8_t porch[] = { PORCH_FP, PORCH_BP, PORCH_SHF, PORCH_FPA, PORCH_BPA };
WriteData16(porch, sizeof(porch));
// Gate control
WriteCommand(CMD_GCTRL);
WriteSmallData(GCTRL_DEFAULT);
// VCOM setting
WriteCommand(CMD_VCOMS);
WriteSmallData(VCOMS_DEFAULT);
// LCM control
WriteCommand(CMD_LCMCTRL);
WriteSmallData(LCMCTRL_DEFAULT);
// VDV/VRH enable
WriteCommand(CMD_VDVVRHEN);
WriteSmallData(VDVVRHEN_DEFAULT);
WriteSmallData(0xFF);
// VRH set
WriteCommand(CMD_VRHS);
// Exit sleep mode
WriteCommand(CMD_SLPOUT);
// VDV set
WriteCommand(CMD_VDVS);
WriteSmallData(VDVS_DEFAULT);
// Frame rate control
WriteCommand(CMD_FRCTRL2);
WriteSmallData(FRCTRL2_60HZ);
// Power control
WriteCommand(CMD_PWCTRL1);
WriteSmallData(PWCTRL1_PARAM1);
WriteSmallData(PWCTRL1_PARAM2);
// Gamma corrections
WriteCommand(CMD_GMCTRP1);
uint8_t ST7789_gamma_pos[] = { 0xD0, 0x00, 0x05, 0x0E, 0x15, 0x0D, 0x37, 0x43, 0x47, 0x09, 0x15, 0x12, 0x16, 0x19 };
WriteData16(ST7789_gamma_pos, sizeof(ST7789_gamma_pos));
WriteCommand(CMD_GMCTRN1);
uint8_t ST7789_gamma_neg[] = { 0xD0, 0x00, 0x05, 0x0D, 0x0C, 0x06, 0x2D, 0x44, 0x40, 0x0E, 0x1C, 0x18, 0x16, 0x19 };
WriteData16(ST7789_gamma_neg, sizeof(ST7789_gamma_neg));
// Address set
WriteCommand(CMD_CASET);
uint8_t caset[] = { X_START_H, X_START_L, X_END_H, X_END_L };
WriteData16(caset, sizeof(caset));
WriteCommand(CMD_RASET);
uint8_t raset[] = { Y_START_H, Y_START_L, Y_END_H, Y_END_L };
WriteData16(raset, sizeof(raset));
HAL_Delay(2);
// Display inversion ON
WriteCommand(CMD_INVON);
// Display ON
WriteCommand(CMD_DISPON);
HAL_Delay(2);
}
void DISPLAY_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
DISPLAY_SetAddressWindow(x, y, x + w - 1, y + h - 1);
static uint16_t chunk_buf[MAX_BUF_SIZE];
size_t buf_len = w * HOR_LEN;
for (size_t i = 0; i < buf_len; i++) {
chunk_buf[i] = color;
}
for (uint16_t row = 0; row < h; row += HOR_LEN) {
uint16_t rows_to_send = (row + HOR_LEN <= h) ? HOR_LEN : (h - row);
size_t pixels_to_send = w * rows_to_send;
WriteData16(chunk_buf, pixels_to_send);
}
}
void DISPLAY_FillScreen(uint16_t color) {
DISPLAY_FillRectangle(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, color);
}
2025-12-23 11:03 AM
Why not using the SPI interface , needs only few pins. (I use it...) Display working fine here. :)
+
reset -> no effect -- cannot be.
+
31MHz with free air wires...no. Reduce speed.
+
ST7789 needs some time after reset , to work; so wait...see :
HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, GPIO_PIN_SET); // lcd_reset off;
HAL_Delay(150);
ST7789_Init();