16-bit parallel - ILI9325C Display and STM32F401RET6
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-09 3:36 AM - edited ‎2025-04-09 3:38 AM
Hello,
I am trying to connect an ILI9325C display to an STM32F401RET6 microcontroller Yes this is related to my previous post. After writing the code correctly and connecting the display, it doesn't respond and only has the backlight on (from the power supply). I think my code is correct I compare it to the documentation of my display. Any advice appreciate it.
Display: https://www.waveshare.com/wiki/3.2inch_320x240_Touch_LCD_(C)
My code LCD.C for 16bit-Parrarel
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_spi.h"
#include "lcd.h"
SPI_HandleTypeDef hspi1; // SPI do dotyku
// Ustawienie danych na pinach D0–D15
void LCD_SetDataPins(uint16_t data)
{
// Maska: PB0–PB10, PB12–PB15 (bez PB11 = D11, bo ten jest na PA11)
uint16_t mask = 0b1111011111111111; // 0xF7FF
// Najpierw wyczyść i ustaw dane na GPIOB
GPIOB->ODR = (GPIOB->ODR & ~mask) | (data & mask);
// Osobno ustaw PA11 (D11)
if (data & (1 << 11)) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
}
}
// Wysłanie komendy do LCD
void LCD_WriteCommand(uint16_t cmd) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); // RS = 0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS = 0
LCD_SetDataPins(cmd);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR = 0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR = 1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS = 1
}
// Wysłanie danych do LCD
void LCD_WriteData(uint16_t data) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); // RS = 1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS = 0
LCD_SetDataPins(data);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR = 0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR = 1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS = 1
}
// Inicjalizacja wyświetlacza LCD
void LCD_Init(void) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); // RST = 0
HAL_Delay(50);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); // RST = 1
HAL_Delay(10);
LCD_WriteCommand(0x01); // Soft Reset
HAL_Delay(10);
LCD_WriteCommand(0x28); // Display OFF
HAL_Delay(10);
LCD_WriteCommand(0xCF); // Power control
LCD_WriteData(0x00);
LCD_WriteData(0xC1);
LCD_WriteData(0x30);
}
// Inicjalizacja SPI1 (dla dotyku)
void SPI_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi1);
}
// Odczyt danych z kontrolera dotyku
uint16_t Touch_ReadData(uint8_t cmd) {
uint16_t result = 0;
uint8_t recv[2] = {0};
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // TP_CS = 0
HAL_SPI_Transmit(&hspi1, &cmd, 1, 1000);
HAL_SPI_Receive(&hspi1, recv, 2, 1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); // TP_CS = 1
result = ((recv[0] << | recv[1]) >> 4;
return result;
}
// Wypełnianie całego ekranu kolorem
void LCD_FillScreen(uint16_t color) {
uint32_t i;
LCD_WriteCommand(0x2A); // Column address set
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0xEF); // 240 columns
LCD_WriteCommand(0x2B); // Page address set
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x01);
LCD_WriteData(0x3F); // 320 rows
LCD_WriteCommand(0x2C); // Memory write
for (i = 0; i < 320 * 240; i++) {
LCD_WriteData(color >> 8); // High byte
LCD_WriteData(color & 0xFF); // Low byte
}
}
3. And my pin connection:
display -- stm
5v-in -- 5v
gnd -- gnd
d0 -- pb0
d1 -- pb1
d2 -- pb2
d3 -- pb3
d4 -- pb4
d5 -- pb5
d6 -- pb6
d7 -- pb7
d8 -- pb8
d9 -- pb9
d10 -- pb10
d11 -- pa11
d12 -- pb12
d13 -- pb13
d14 -- pb14
d15 -- pb15
lcd-cs -- pc0
rs -- pc1
wr -- pc2
rd -- vdd
rst -- pc3
bl-vcc -- 3v
gnd -- gnd
bl-ctrl -- pa5
tp-irq -- pa9
tp-cs -- pa8
tp-sck -- pc10
tp-sdi -- pc12
tp-sdo -- pc11
Thank you in advance!
Solved! Go to Solution.
- Labels:
-
Hardware components
-
Others
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-10 5:32 AM
I have made it. Yes that was code issue.
I have wrote code I think that the previous one what I wrote was for ILI9341 what has diffrent commands, but after a long time of debuging and looking for mistakes I have done it and the display is correctly initializating and showing colors.
Here is my code maybe someone will need it,
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_spi.h"
#include "lcd.h"
extern SPI_HandleTypeDef hspi3;
// Ustawienie danych na pinach D0–D15
void LCD_SetDataPins(uint16_t data) {
uint16_t mask = 0b1111011111111111; // PB0–PB10, PB12–PB15
GPIOB->ODR = (GPIOB->ODR & ~mask) | (data & mask);
// PA11 = D11
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, (data & (1 << 11)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
// Wysyłanie komend i danych
void LCD_WriteCommand(uint16_t cmd) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); // RS=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS=0
LCD_SetDataPins(cmd);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS=1
}
void LCD_WriteData(uint16_t data) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); // RS=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS=0
LCD_SetDataPins(data);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS=1
}
// Ustawienie kursora (GRAM address)
void LCD_SetCursor(uint16_t x, uint16_t y) {
LCD_WriteCommand(0x20);
LCD_WriteData(x); // kolumna
LCD_WriteCommand(0x21);
LCD_WriteData(y); // wiersz
LCD_WriteCommand(0x22); // RAM write
}
// Wpis danych do pamięci GRAM (jeden piksel)
void LCD_WriteRAM(uint16_t color) {
LCD_WriteData(color);
}
// Reset i inicjalizacja
void LCD_Init(void) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); // RST = 0
HAL_Delay(150);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); // RST = 1
HAL_Delay(150);
// Inicjalizacja ILI9325 — wybrane rejestry (skrót wersji)
LCD_WriteCommand(0x00E5); LCD_WriteData(0x78F0);
LCD_WriteCommand(0x0001); LCD_WriteData(0x0100);
LCD_WriteCommand(0x0002); LCD_WriteData(0x0700);
LCD_WriteCommand(0x0003); LCD_WriteData(0x1030); // BGR=1, Scan direction
LCD_WriteCommand(0x0004); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0008); LCD_WriteData(0x0202);
LCD_WriteCommand(0x0009); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000A); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000C); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000D); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000F); LCD_WriteData(0x0000);
// Power On
LCD_WriteCommand(0x0010); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0011); LCD_WriteData(0x0007);
LCD_WriteCommand(0x0012); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0013); LCD_WriteData(0x0000);
HAL_Delay(200);
LCD_WriteCommand(0x0010); LCD_WriteData(0x17B0);
LCD_WriteCommand(0x0011); LCD_WriteData(0x0037);
HAL_Delay(50);
LCD_WriteCommand(0x0012); LCD_WriteData(0x0138);
HAL_Delay(50);
LCD_WriteCommand(0x0013); LCD_WriteData(0x1700);
LCD_WriteCommand(0x0029); LCD_WriteData(0x000D);
HAL_Delay(50);
// Gamma
LCD_WriteCommand(0x0030); LCD_WriteData(0x0001);
LCD_WriteCommand(0x0031); LCD_WriteData(0x0606);
LCD_WriteCommand(0x0032); LCD_WriteData(0x0003);
LCD_WriteCommand(0x0035); LCD_WriteData(0x0206);
LCD_WriteCommand(0x0036); LCD_WriteData(0x0008);
LCD_WriteCommand(0x0037); LCD_WriteData(0x0504);
LCD_WriteCommand(0x0038); LCD_WriteData(0x0007);
LCD_WriteCommand(0x0039); LCD_WriteData(0x0000);
LCD_WriteCommand(0x003C); LCD_WriteData(0x0007);
LCD_WriteCommand(0x003D); LCD_WriteData(0x0000);
// Window
LCD_WriteCommand(0x0050); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0051); LCD_WriteData(0x00EF);
LCD_WriteCommand(0x0052); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0053); LCD_WriteData(0x013F);
LCD_WriteCommand(0x0060); LCD_WriteData(0xA700);
LCD_WriteCommand(0x0061); LCD_WriteData(0x0001);
LCD_WriteCommand(0x006A); LCD_WriteData(0x0000);
// Display ON
LCD_WriteCommand(0x0007); LCD_WriteData(0x0133);
HAL_Delay(50);
}
// Wypełnienie całego ekranu kolorem
void LCD_FillScreen(uint16_t color) {
LCD_SetCursor(0, 0);
uint32_t i;
for (i = 0; i < 320 * 240; i++) {
LCD_WriteRAM(color);
}
}
Thanks to @Ozone @Andrew Neil for advices and trying to help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-09 3:47 AM - edited ‎2025-04-09 3:49 AM
@kiwiosek2007 wrote:Yes this is related to my previous post.
You mean this:
@kiwiosek2007 wrote:I think my code is correct I compare it to the documentation of my display.
What about when you look at the actual interface lines; eg, with a logic analyser?
A complex system designed from scratch never works and cannot be patched up to make it work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-09 4:10 AM
Yes and I have changed the spi to the 16bit-parrarel.
I don't have right now the analyzer. When I'll get back I'll test it, but also my anaylzer don't have so much channels to get all pins to checked.
When i was in debug my display doesn't response the connection in neither way. I thought that is problem with my code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-09 4:24 AM
@kiwiosek2007 wrote:my anaylzer don't have so much channels to get all pins to checked.
At least start by looking at a selection of lines - the control lines and as many data lines as you can.
@kiwiosek2007 wrote:I thought that is problem with my code.
A logic analyser will be the easiest way to see what your code is actually doing.
Knowing what it's actually doing, you can then compare that to what it should be doing.
That should lead you to the part(s) of your code that are not working correctly.
It may, of course, show that you (also) have hardware problem(s)...
A complex system designed from scratch never works and cannot be patched up to make it work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-09 6:52 AM - edited ‎2025-04-09 6:53 AM
What you at least should do is to check all connections statically for correctness.
By that I mean e.g. with an ohmmeter. All the data connections and especially the control signals.
For a logic analyzer, you don't need to spend a fortune. I'm using the sigrok tool (under Linux), which supports the rather cheap 8-channel Salae Logic clones you get for a few bucks.
Her a link to the software, which AFAIK also supports Windows : https://sigrok.org/wiki/Main_Page
And I think it's understood you need the ILI9325C datasheet, to check for a proper signal sequence, timing and levels.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-10 5:32 AM
I have made it. Yes that was code issue.
I have wrote code I think that the previous one what I wrote was for ILI9341 what has diffrent commands, but after a long time of debuging and looking for mistakes I have done it and the display is correctly initializating and showing colors.
Here is my code maybe someone will need it,
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_spi.h"
#include "lcd.h"
extern SPI_HandleTypeDef hspi3;
// Ustawienie danych na pinach D0–D15
void LCD_SetDataPins(uint16_t data) {
uint16_t mask = 0b1111011111111111; // PB0–PB10, PB12–PB15
GPIOB->ODR = (GPIOB->ODR & ~mask) | (data & mask);
// PA11 = D11
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, (data & (1 << 11)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
// Wysyłanie komend i danych
void LCD_WriteCommand(uint16_t cmd) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); // RS=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS=0
LCD_SetDataPins(cmd);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS=1
}
void LCD_WriteData(uint16_t data) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); // RS=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // CS=0
LCD_SetDataPins(data);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // WR=0
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // WR=1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // CS=1
}
// Ustawienie kursora (GRAM address)
void LCD_SetCursor(uint16_t x, uint16_t y) {
LCD_WriteCommand(0x20);
LCD_WriteData(x); // kolumna
LCD_WriteCommand(0x21);
LCD_WriteData(y); // wiersz
LCD_WriteCommand(0x22); // RAM write
}
// Wpis danych do pamięci GRAM (jeden piksel)
void LCD_WriteRAM(uint16_t color) {
LCD_WriteData(color);
}
// Reset i inicjalizacja
void LCD_Init(void) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); // RST = 0
HAL_Delay(150);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); // RST = 1
HAL_Delay(150);
// Inicjalizacja ILI9325 — wybrane rejestry (skrót wersji)
LCD_WriteCommand(0x00E5); LCD_WriteData(0x78F0);
LCD_WriteCommand(0x0001); LCD_WriteData(0x0100);
LCD_WriteCommand(0x0002); LCD_WriteData(0x0700);
LCD_WriteCommand(0x0003); LCD_WriteData(0x1030); // BGR=1, Scan direction
LCD_WriteCommand(0x0004); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0008); LCD_WriteData(0x0202);
LCD_WriteCommand(0x0009); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000A); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000C); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000D); LCD_WriteData(0x0000);
LCD_WriteCommand(0x000F); LCD_WriteData(0x0000);
// Power On
LCD_WriteCommand(0x0010); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0011); LCD_WriteData(0x0007);
LCD_WriteCommand(0x0012); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0013); LCD_WriteData(0x0000);
HAL_Delay(200);
LCD_WriteCommand(0x0010); LCD_WriteData(0x17B0);
LCD_WriteCommand(0x0011); LCD_WriteData(0x0037);
HAL_Delay(50);
LCD_WriteCommand(0x0012); LCD_WriteData(0x0138);
HAL_Delay(50);
LCD_WriteCommand(0x0013); LCD_WriteData(0x1700);
LCD_WriteCommand(0x0029); LCD_WriteData(0x000D);
HAL_Delay(50);
// Gamma
LCD_WriteCommand(0x0030); LCD_WriteData(0x0001);
LCD_WriteCommand(0x0031); LCD_WriteData(0x0606);
LCD_WriteCommand(0x0032); LCD_WriteData(0x0003);
LCD_WriteCommand(0x0035); LCD_WriteData(0x0206);
LCD_WriteCommand(0x0036); LCD_WriteData(0x0008);
LCD_WriteCommand(0x0037); LCD_WriteData(0x0504);
LCD_WriteCommand(0x0038); LCD_WriteData(0x0007);
LCD_WriteCommand(0x0039); LCD_WriteData(0x0000);
LCD_WriteCommand(0x003C); LCD_WriteData(0x0007);
LCD_WriteCommand(0x003D); LCD_WriteData(0x0000);
// Window
LCD_WriteCommand(0x0050); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0051); LCD_WriteData(0x00EF);
LCD_WriteCommand(0x0052); LCD_WriteData(0x0000);
LCD_WriteCommand(0x0053); LCD_WriteData(0x013F);
LCD_WriteCommand(0x0060); LCD_WriteData(0xA700);
LCD_WriteCommand(0x0061); LCD_WriteData(0x0001);
LCD_WriteCommand(0x006A); LCD_WriteData(0x0000);
// Display ON
LCD_WriteCommand(0x0007); LCD_WriteData(0x0133);
HAL_Delay(50);
}
// Wypełnienie całego ekranu kolorem
void LCD_FillScreen(uint16_t color) {
LCD_SetCursor(0, 0);
uint32_t i;
for (i = 0; i < 320 * 240; i++) {
LCD_WriteRAM(color);
}
}
Thanks to @Ozone @Andrew Neil for advices and trying to help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-04-10 6:41 AM
I had done the same thing about 10 years ago, although for another MCU.
And also without scope or logic analyser.
A bit of persistence and a proper incremental approach are helpful...
