Jump to content
david1982

ILI9341 SPI stm32f103

Recommended Posts

Glad to hear that you have everything working now and also thank you for reporting back the issue with the proper solution so other people who search the forum don't have to ask the same questions :)

Very nice work!

~ Tectu

Share this post


Link to post
Share on other sites

While porting this to the STM32F4-Discovery board, I found an error/typo in the board file. Took me a while to find it :( , so I want to save you the time in case you want to do the same or use a pin from another port ...

   //Set up the pins..
palSetPadMode(SPI_PORT, CS_PAD, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);

needs to be of course:

   //Set up the pins..
palSetPadMode(CS_PORT, CS_PAD, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);

Share this post


Link to post
Share on other sites

You're doing a great job! Thank you very much!

I think we should add your board files to the /boards directory so people with a similar setup have an easy start. What do you think?

~ Tectu

Share this post


Link to post
Share on other sites

Yeah, sure, would be great! I just want to polish the board file a little bit more so it is usable for multiple targets. Now I have a version for the Nucleo, and two for the STM32F4-Discovery (one based on ChibiOS and one on Tilen Majerle's libraries (bare metal, no RTOS)), and I want to merge them in a sort of easy to understand way for users who want to use it in different configurations.

Share this post


Link to post
Share on other sites

Hi,

This is what I made of it. Feel free to optimize it :-)

This file is working for all my situations. I have one question dough. For the Nucleo board (STM32L152RE), I can use a max clock speed of 8MHz (SPI_BaudRatePrescaler_4) for SPI2. For SPI1, 16MHz (SPI_BaudRatePrescaler_2) is working fine.

Could be something wrong with the pin setup? I'm not 100% sure about the PAL_MODE_ALTERNATE(5) pin mode for the SPI pins.

For instance, with the STM32F4-Discovery board, I need to use PAL_MODE_ALTERNATE(5) for SPI2 and PAL_MODE_ALTERNATE(6) for SPI3.

Can you point me to a good document/tutorial where these pin modes are properly explained?

Thanks!

/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*
* Altered, optimized an polished by Gunter Otté
*/

#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H

#if defined(USE_STDPERIPH_DRIVER) // *** Use Tilen Majerle's libraries. This definition is usually specified by the compiler (well, for Keil it is :-))
#include "tm_stm32f4_ili9341.h"
#else // *** Use ChibiOS/RT
//**** ILI9341 on SPI. TESTED on STM32L1 AND STM32F4.

// SPI communication method
#define SPI_METHOD_IRQ 1
#define SPI_METHOD_POLLING 2
#define SPI_METHOD SPI_METHOD_POLLING

// Target selection
#define TARGET_SELECTION_NUCLEO_SPI1 1
#define TARGET_SELECTION_NUCLEO_SPI2 2
#define TARGET_SELECTION_DISCOVERY_SPI3 3
#define TARGET_SELECTION TARGET_SELECTION_NUCLEO_SPI1

#if TARGET_SELECTION == TARGET_SELECTION_NUCLEO_SPI1 // SPI_BaudRatePrescaler_2 tested OK
#define SPI_DRIVER (&SPID1)
#define SPI_PORT GPIOA
#define SCK_PAD 5 //PA5
#define MISO_PAD 6 //PA6
#define MOSI_PAD 7 //PA7

#define CS_PORT GPIOA
#define RESET_PORT GPIOA
#define DNC_PORT GPIOA
#define CS_PAD 4 // 0 = chip selected
#define RESET_PAD 1 // 0 = reset
#define DNC_PAD 0 // control=0, data=1 -- DNC or D/C
#elif TARGET_SELECTION == TARGET_SELECTION_NUCLEO_SPI2 // For some reason, SPI_BaudRatePrescaler_4 is max for SPI2
#define SPI_DRIVER (&SPID2)
#define SPI_PORT GPIOB
#define SCK_PAD 13 //PB13
#define MISO_PAD 14 //PB14
#define MOSI_PAD 15 //PB15

#define CS_PORT GPIOA
#define RESET_PORT GPIOA
#define DNC_PORT GPIOA
#define CS_PAD 4 // 0 = chip selected
#define RESET_PAD 1 // 0 = reset
#define DNC_PAD 0 // control=0, data=1 -- DNC or D/C
#elif TARGET_SELECTION == TARGET_SELECTION_DISCOVERY_SPI3 // SPI_BaudRatePrescaler_2 tested OK
// Pin & SPI setup
#define SPI_DRIVER (&SPID3)
#define SPI_PORT GPIOB
#define SCK_PAD 3 //PB3
#define MISO_PAD 4 //PB4
#define MOSI_PAD 5 //PB5

#define CS_PORT GPIOC
#define RESET_PORT GPIOD
#define DNC_PORT GPIOD
#define CS_PAD 2 // 0 = chip selected
#define RESET_PAD 12 // 0 = reset
#define DNC_PAD 13 // control=0, data=1 -- DNC or D/C
#endif

// SPI setup ajust " SPI_BaudRatePrescaler_X" to set SPI speed.
// Peripherial Clock STM32F4-Discovery SPI1:84MHz, SPI2&SPI3:42MHz
// Peripherial Clock STM32L152RE-Nucleo SPI1:32MHz
// STM32F4-Discovery STM32L152RE-Nucleo
// SPI1 SPI2/3 SPI1
#define SPI_BaudRatePrescaler_2 ((uint16_t)0x0000) // 42 MHz 21 MHZ 16 MHz
#define SPI_BaudRatePrescaler_4 ((uint16_t)0x0008) // 21 MHz 10.5 MHz 8 MHz
#define SPI_BaudRatePrescaler_8 ((uint16_t)0x0010) // 10.5 MHz 5.25 MHz 4 MHz
#define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018) // 5.25 MHz 2.626 MHz 2 MHz
#define SPI_BaudRatePrescaler_32 ((uint16_t)0x0020) // 2.626 MHz 1.3125 MHz 1 MHz
#define SPI_BaudRatePrescaler_64 ((uint16_t)0x0028) // 1.3125 MHz 656.25 KHz 500 KHz
#define SPI_BaudRatePrescaler_128 ((uint16_t)0x0030) // 656.25 KHz 328.125 KHz 250 KHz
#define SPI_BaudRatePrescaler_256 ((uint16_t)0x0038) // 328.125 KHz 164.06 KHz 125 KHz

static SPIConfig spi_cfg = {
NULL,
CS_PORT,
CS_PAD,
SPI_BaudRatePrescaler_2 //Ajust speed here. It's quite unlikely that the ILI9341 can handle >21MHz clock ...
};
#endif

#include "gfx.h"

static __inline void init_board(GDisplay *g) {
(void) g;

g->board = 0;

#if defined(USE_STDPERIPH_DRIVER)
TM_ILI9341_Init();
#else
//Set up the pins..
palSetPadMode(CS_PORT, CS_PAD, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
#if (TARGET_SELECTION == TARGET_SELECTION_NUCLEO_SPI1) || (TARGET_SELECTION == TARGET_SELECTION_NUCLEO_SPI2)
palSetPadMode(SPI_PORT, SCK_PAD, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);
palSetPadMode(SPI_PORT, MISO_PAD, PAL_MODE_ALTERNATE(5));
palSetPadMode(SPI_PORT, MOSI_PAD, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);
#elif TARGET_SELECTION == TARGET_SELECTION_DISCOVERY_SPI3
palSetPadMode(SPI_PORT, SCK_PAD, PAL_MODE_ALTERNATE(6) | PAL_STM32_OSPEED_HIGHEST);
palSetPadMode(SPI_PORT, MISO_PAD, PAL_MODE_ALTERNATE(6));
palSetPadMode(SPI_PORT, MOSI_PAD, PAL_MODE_ALTERNATE(6) | PAL_STM32_OSPEED_HIGHEST);
#endif
palSetPadMode(DNC_PORT, DNC_PAD, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palSetPadMode(RESET_PORT, RESET_PAD, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);

//Set pins.
palSetPad(CS_PORT, CS_PAD);
palSetPad(RESET_PORT, RESET_PAD);
palClearPad(DNC_PORT, DNC_PAD);

//Start SPI with our config.
spiStart(SPI_DRIVER, &spi_cfg);
spiSelectI(SPI_DRIVER); /* Slave Select assertion. */
#endif
}

static __inline void post_init_board(GDisplay *g) {
(void) g;
}

static __inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;

#if defined(USE_STDPERIPH_DRIVER)
if(state == 1){
ILI9341_RST_RESET;}
else {
ILI9341_RST_SET;
}
#else
palWritePad(RESET_PORT, RESET_PAD, !state);
#endif
}

static __inline void set_backlight(GDisplay *g, uint8_t percent) {
(void) g;
(void) percent;
}

static __inline void acquire_bus(GDisplay *g) {
(void) g;

#if defined(USE_STDPERIPH_DRIVER)
#else
spiSelectI(SPI_DRIVER);
#endif
}

static __inline void release_bus(GDisplay *g) {
(void) g;

#if defined(USE_STDPERIPH_DRIVER)
#else
spiUnselectI(SPI_DRIVER);
#endif
}

static __inline void write_index(GDisplay *g, uint8_t index) {
(void) g;

#if defined(USE_STDPERIPH_DRIVER)
TM_ILI9341_SendCommand(index);
#else
palClearPad(DNC_PORT, DNC_PAD);
#if SPI_METHOD == SPI_METHOD_IRQ
spiSend(SPI_DRIVER, 1, &index);
#elif SPI_METHOD == SPI_METHOD_POLLING
spiPolledExchange(SPI_DRIVER, index);
#endif
palSetPad(DNC_PORT, DNC_PAD);
#endif
}

static __inline void write_data(GDisplay *g, uint8_t data) {
(void) g;

#if defined(USE_STDPERIPH_DRIVER)
TM_ILI9341_SendData(data);
#else
#if SPI_METHOD == SPI_METHOD_IRQ
spiSend(SPI_DRIVER, 1, &data);
#elif SPI_METHOD == SPI_METHOD_POLLING
spiPolledExchange(SPI_DRIVER, data);
#endif
#endif
}

static __inline void setreadmode(GDisplay *g) {
(void) g;
}

static __inline void setwritemode(GDisplay *g) {
(void) g;
}

static __inline uint16_t read_data(GDisplay *g) {
(void) g;
return 0;
}

#endif /* _GDISP_LLD_BOARD_H */

Share this post


Link to post
Share on other sites

Ok, found all the info I need about the alternate GPIO functions in the data sheet of the STM32F405xx/STM32F407xx chip.

Now it makes (more) sense to me :-)

Share this post


Link to post
Share on other sites

If you are using chibios and you are having speed issues then using spiPolledExchange may help. Note that the driver as talked about above was working, just not with the expected performance.

Share this post


Link to post
Share on other sites

Yes, I'm using ChibiOS_2.6.8 with the latest uGFX. It is a little bit strange because with the ChibiOS_2.6.5 everything was ok. As I switched to 2.6.8 the touch stopped to work.

Share this post


Link to post
Share on other sites

Hi

I have problems with the controller configuration STM32F103C8t6. I need to learn how to display image in the display is ILI9341. I read the whole forum but did not understand how do I configure the display. I have no experience with stm32. I have no experience in the UGFX library. Please help me. Give ready file or manual

Share this post


Link to post
Share on other sites

Please help set up the project at this stage. I do not quite understand where the initialized functions should be and what should be in them. I use nucleo F401RE it with the same display.

Снимок.PNG

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

×