cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H5 FMC 8080 16-bit Parallel LCD freezes after several seconds (MCU running, requires power cycle)

mprz
Visitor

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.

  • For the display to show anything at all, I must perform a full power cycle (physically unplug and re-apply power). Toggling the LCD RESET pin or following the reset sequence from the datasheet does not reset the display.
  • Once reset, on the first draw or two, only about 3/4 of the display is updated then begins updating the full screen correctly. After a few seconds the display freezes, stopping on either red or white. MCU does not freeze, the display just stops updating (tested by including a LED toggle in the loop).
  • Sometimes after some time being frozen the display updates briefly changing the color a few times and then freezes again. Seems to start working a bit with movement, possibly the fact that so many wires are going from board to breadboard to board?

 

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:

  • FMC
    • Reset pin is GPIO_Output PC6
    • TE Tearing pin configured and connected, but not used.
    • Wired according to the wiring diagram from the display product specification sheet for 8080-16 bit Parallel.
    • Not using touch controller, pins are left floating. 
    • Backlight Cathode pins are grounded using 22Ω resistors.
    • Everything is wired via breadboard.

mprz_0-1766505264770.png

mprz_1-1766505788485.png

 

  • Clock Speed
    • HCLK is set to 31.25 MHz for testing (have tried multiple different clock speeds)
    • FMC clock speed is the same as HCLK, there is no FMC Clock Mux option.

 

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)

  • The init function's data and commands defined variables are pulled from other ST7789 drivers and the Newhaven spec sheet.
#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);
}

 

1 REPLY 1
AScha.3
Super User

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();
If you feel a post has answered your question, please click "Accept as Solution".