tombalabomba Posted February 12, 2019 Report Share Posted February 12, 2019 I struggle to get my ILI9225 driven display on a STM32L1 nucleo board running. Essentially. Below you can find my application code and the board file I use. main.c : #include "stm32l1xx.h" #include "stm32l1xx_nucleo.h" #include "gfx.h" #include "stm32l1xx_hal.h" #include "board_ILI9225.h" void SystemClock_Config(void); void Error_Handler(void); int main(void) { coord_t width, height; coord_t i, j; HAL_Init(); SystemClock_Config(); gfxInit(); width = gdispGetWidth(); height = gdispGetHeight(); gdispDrawBox(10, 10, width/2, height/2, Yellow); gdispFillArea(width/2, height/2, width/2-10, height/2-10, Blue); gdispDrawLine(5, 30, width-50, height-40, Red); while (TRUE) { for (i = 5, j = 0; i < width && j < height; i += 7, j += i/20) { gdispDrawPixel(i, j, White); } gfxSleepMilliseconds(500); HAL_GPIO_TogglePin(LD2_PORT, LD2_Pin); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /**Configure the main internal regulator output voltage */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12; RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } } void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } board_ILI9225.h: #ifndef _GDISP_LLD_BOARD_H #define _GDISP_LLD_BOARD_H #include "stm32l1xx_hal.h" #include "stm32l1xx_hal_spi.h" #include "gfx.h" #define LCD_PORT GPIOB #define LCD_DC_Pin GPIO_PIN_2 #define LCD_RST_Pin GPIO_PIN_11 #define LCD_SPI_SS_Pin GPIO_PIN_12 #define LCD_SPI_SCK_Pin GPIO_PIN_13 #define LCD_SPI_MOSI_Pin GPIO_PIN_15 #define LD2_PORT GPIOA #define LD2_Pin GPIO_PIN_5 SPI_HandleTypeDef hspi2; //------------------------------------------------------------------------- static GFXINLINE void init_board(GDisplay *g) { GPIO_InitTypeDef GPIO_InitStruct; (void)g; // SPI configuration __SPI2_CLK_ENABLE(); /* CLKPolarity CLKPhase MOSI changes on SCK value when inactive SPI_POLARITY_HIGH SPI_PHASE_2EDGE Falling Edge High SPI_POLARITY_LOW SPI_PHASE_2EDGE Rising Edge Low SPI_POLARITY_LOW SPI_PHASE_1EDGE Falling Edge Low SPI_POLARITY_HIGH SPI_PHASE_1EDGE Rising Edge High */ hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_1LINE; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 10; HAL_SPI_Init(&hspi2); __HAL_SPI_ENABLE(&hspi2); // GPIO configuration // Peripheral clocks __HAL_RCC_GPIOA_CLK_ENABLE(); // Green LED (PA5) GPIO_InitStruct.Pin = LD2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD2_PORT, &GPIO_InitStruct); __HAL_RCC_GPIOB_CLK_ENABLE(); //SPI GPIO_InitStruct.Pin = LCD_SPI_SCK_Pin | LCD_SPI_MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(LCD_PORT, &GPIO_InitStruct); // LCD Chip Select (PB12) GPIO_InitStruct.Pin = LCD_SPI_SS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(LCD_PORT, &GPIO_InitStruct); // LCD DC (PB10) GPIO_InitStruct.Pin = LCD_DC_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(LCD_PORT, &GPIO_InitStruct); // LCD Reset (PB11) GPIO_InitStruct.Pin = LCD_RST_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(LCD_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(LCD_PORT, LCD_RST_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LCD_PORT, LCD_SPI_SS_Pin, GPIO_PIN_SET); } //------------------------------------------------------------------------- static GFXINLINE void post_init_board(GDisplay* g) { (void) g; } //------------------------------------------------------------------------- static GFXINLINE void setpin_reset(GDisplay* g, bool_t state) { (void) g; if (state) { HAL_GPIO_WritePin(LCD_PORT, LCD_RST_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(LCD_PORT, LCD_RST_Pin, GPIO_PIN_SET); } } //------------------------------------------------------------------------- static GFXINLINE void set_backlight(GDisplay* g, uint8_t percent) { (void) g; } //------------------------------------------------------------------------- static GFXINLINE void acquire_bus(GDisplay* g) { HAL_GPIO_WritePin(LCD_PORT, LCD_SPI_SS_Pin, GPIO_PIN_RESET); (void) g; } //------------------------------------------------------------------------- static GFXINLINE void release_bus(GDisplay* g) { HAL_GPIO_WritePin(LCD_PORT, LCD_SPI_SS_Pin, GPIO_PIN_SET); (void) g; } //------------------------------------------------------------------------- static GFXINLINE void write_cmd(GDisplay* g, uint16_t index) { (void) g; uint8_t tx_data[2]; tx_data[0] = index >> 8; tx_data[1] = 0x00FF & index; HAL_GPIO_WritePin(LCD_PORT, LCD_DC_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi2, tx_data, 2, HAL_MAX_DELAY); } //------------------------------------------------------------------------- static GFXINLINE void write_data(GDisplay* g, uint16_t data) { (void) g; uint8_t tx_data[2]; tx_data[0] = data >> 8; tx_data[1] = 0x00FF & data; HAL_GPIO_WritePin(LCD_PORT, LCD_DC_Pin, GPIO_PIN_SET); HAL_SPI_Transmit(&hspi2, tx_data, 2, HAL_MAX_DELAY); } //------------------------------------------------------------------------- static GFXINLINE void setreadmode(GDisplay* g) { (void) g; } //------------------------------------------------------------------------- static GFXINLINE void setwritemode(GDisplay* g) { (void) g; } //------------------------------------------------------------------------- static GFXINLINE uint16_t read_data(GDisplay* g) { (void) g; return 0; } #endif /* _GDISP_LLD_BOARD_H */ Unfortunately, expect of backlight illumination the display does nothing. Hence, I checked the SPI communication which looks as follows (D0 = reset, D1 = chip select, D2 = DC, D3 = SCK, D4 = MOSI) scope_1.png show the digital lines triggered on the falling edge of the reset and scope_2.png shows the SPI communication triggered on the falling edge of chip select. Since the display I use looks pretty much the same like the one shown in http://www.lcdwiki.com/2.0inch_Arduino_SPI_Module_ILI9225_SKU:MAR2001 . I already checked if it's really am ILI9225 driven display and if it's functional by flashing the library https://github.com/jorgegarciadev/TFT_22_ILI9225 on an Arduino. Coclusio: The performance is not overwhelming but the display is working. That's basically good news for me since that means I only have a bug in my code. So the question is what do I wrong? Any hints are highly appreciated. Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted February 12, 2019 Report Share Posted February 12, 2019 The ILIxxxx display controllers are known to suffer from differences across series and revisions. Also, some (chinese) sources love to sell you an ILI9225 as an ILI9220 and so on. Therefore, once you confirmed that the SPI is working correctly, try to grab the initialization code (sequence) from your supplied and plug it into the init() function of the corresponding µGFX driver. Another thing you might want to do is trying to read out the display controllers version register / chip ID. This will tell you exactly what display controller you have and will also confirm that the communication is working well. Link to comment Share on other sites More sharing options...
tombalabomba Posted February 20, 2019 Author Report Share Posted February 20, 2019 (edited) Meanwhile, I ended up with a working configuration. Basically, I had to fix two problems. The first was indeed the wrong SPI configuration. In contrast to many other ILI driver the ILI9225 drivers requires CPOL = 1: hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; On the other hand there was also a problem with the chip select signal. Controlling CS in acquire_bus(GDisplay* g) and release_bus(GDisplay* g) didn't do the job and I had to control the chip select signal right before and after data transmission. Edited February 20, 2019 by tombalabomba Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted February 26, 2019 Report Share Posted February 26, 2019 Happy to hear that you got it working! The issue with the chip select sounds like the GDISP driver is not properly calling those functions. Link to comment Share on other sites More sharing options...
diode268 Posted December 18, 2019 Report Share Posted December 18, 2019 Can you explain more detail about controlling the CS??? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now