adafruit_ILI9341_STM for SPI2

madias
Sun Apr 17, 2016 7:03 pm
Hello,
cause I needed the TFT on SPI2 I rewrote the library and renamed it to Adafruit_ILI9341_STM_SPI2 so it can easily coexist with the standard lib so if you need it you can run two independent ILI9341’s simultaneous. Better example would be to use with a another device on SPI1, like NRF24 (as I did) or SD-Card. Benefit would be to use both DMA channels for SPI. Another benefit is you won’t take care of which SPI you are taking to in the sketch, every ILI9341 functions is automatically on SPI2.
Usage is simple: Just put the SPI lines of the TFT module to SPI2, the rest of the pins can be changed by software.
All examples should include the “#include <Adafruit_ILI9341_STM_SPI2.h>”, DMA tested successfully (I didn’t have to change anything “DMA” related in the code, because of the smart SPI library, hope that’s right) , so it runs out of the box.

WereCatf
Sun Apr 17, 2016 7:40 pm
That’s a rather clunky approach. Why not just add one more class-constructor to the original adafruit_ILI9341_STM that allows you to specify the SPI-bus to use? Like e.g. Adafruit_ILI9341_STM(uint8_t _SPIBUS, int8_t _CS, int8_t _DC, int8_t _RST = -1)? That’s a much cleaner approach and doesn’t require multiple copies of the library.

mrburnette
Sun Apr 17, 2016 9:48 pm
WereCatf wrote:That’s a rather clunky approach. <…>

WereCatf
Sun Apr 17, 2016 10:05 pm
mrburnette wrote:Play nice.

mrburnette
Sun Apr 17, 2016 10:10 pm
WereCatf wrote:mrburnette wrote:Play nice.

madias
Mon Apr 18, 2016 4:16 pm
Ok, while ignoring the comments above, I’ve recognized, that DMA on SPI2 isn’t working as it should. It looks like, its only doing the “normal” transfer. At the first tests, I only saw it was ok, but it’s slower than on SPI1. I had a quick look into the SPI library and it seems, like all DMA channels are active since the implementation begun. Have to check it twice, or I need a input.
Ray: The DMA implementation was done by Victor, I’ve only ported the library (as I can remember).

BTW: Setting different SPI ports is a bit blurry for me:
http://www.stm32duino.com/viewtopic.php … spi2#p3923

so I guess
SPIClass SecondSPI(2);
SecondSPI.setClockDivider(SPI_CLOCK_DIV32);


mrburnette
Mon Apr 18, 2016 4:25 pm
madias wrote:
<…>
Ray: The DMA implementation was done by Victor, I’ve only ported the library (as I can remember).

martinayotte
Mon Apr 18, 2016 4:27 pm
That make me think that we didn’t hear something from Victor since awhile …

mrburnette
Mon Apr 18, 2016 4:35 pm
martinayotte wrote:That make me think that we didn’t hear something from Victor since awhile …

WereCatf
Mon Apr 18, 2016 4:35 pm
madias wrote:Ok, while ignoring the comments above, I’ve recognized, that DMA on SPI2 isn’t working as it should. It looks like, its only doing the “normal” transfer. At the first tests, I only saw it was ok, but it’s slower than on SPI1.

racemaniac
Mon Apr 18, 2016 5:46 pm
WereCatf wrote:madias wrote:Ok, while ignoring the comments above, I’ve recognized, that DMA on SPI2 isn’t working as it should. It looks like, its only doing the “normal” transfer. At the first tests, I only saw it was ok, but it’s slower than on SPI1.

WereCatf
Mon Apr 18, 2016 5:58 pm
racemaniac wrote:WereCatf wrote:madias wrote:Ok, while ignoring the comments above, I’ve recognized, that DMA on SPI2 isn’t working as it should. It looks like, its only doing the “normal” transfer. At the first tests, I only saw it was ok, but it’s slower than on SPI1.

madias
Tue Apr 19, 2016 6:16 am
Thanks for the tip with the slower SPI2, I’ll try to lower the divider.
I have come to another problem on it, but this belongs to nearly every library with SPI:
Assume that you have two SPI devices on one port:
A touch controller (XPT2046 as example)
A ILI9341
The ILI9341 works with a low clock divider (setClockDivider(2))
The XPT2046 needs at least setClockDivider(4) (if not 8)
So in both libraries you need a setClockDivider() line before each SPI execution.
(The example above is a bad example, because I don’t use the XPT2046 SPI library, but UTouch -> http://www.rinkydinkelectronics.com/library.php?id=55 this lib runs out of the box and is far more precise than the adafruit one)

RogerClark
Tue Apr 19, 2016 9:52 am
I have issues with the nRF905 as well on SPI with DIV2, so as I have a board with both nRF905 and ILI9341 I just have to change the SPI divider before and after I make the block of calls to the nRF905 (to slow it down to DIV4)

Adding the call to change the divider in each of the ILI9341 (or the nRF905 lib) code would probably slow things down a bit.

As long as you know a device’s limitations, you can probably code more efficiently in your own code (in the sketch), rather than adding code to set the divider in each of the library calls.


madias
Tue Apr 19, 2016 10:30 am
So I think it’s a wise idea to “bundle” SPI devices with the same clock divider on a specific SPI:
Like: NRF and/or XPT2046 on SPI1 and the ILI9341, SD-Card, Winbond EEPROM’s on SPI2
For sure it would be better to use “high speed SPI devices” on SPI1, but I won’t rewrite the radiohead library (If somebody digged into the code of this lib, know what I mean…)

RogerClark
Tue Apr 19, 2016 10:38 am
Hi Matthias

I’ve avoided using RadioHead as it looks like a massive amount of code. it would probably take ages to port, and I’d only end up using 10% of it.

I found a simple nRF905 library and hacked it a lot to get it to work on the STM32 (but as its a hack I’m not adding it as a library, as the code is now rather messy)

But it works fine ;-)


madias
Tue Apr 19, 2016 12:25 pm
I also use the manicbug NRF24 library, somebody posted here times ago… but it’s also a “‘#ifdef” hell because of supprt of (too) many platforms. I’m a fan of lightweight separate libraries for each platform, I see no sense in “supporting everything” in one lib.

mrburnette
Tue Apr 19, 2016 1:03 pm
madias wrote:
<…>
I see no sense in “supporting everything” in one lib.

stm32user
Thu Jan 18, 2018 7:04 am
@madias
First of all thank you for the library.

I could not display images on the screen with the following connections.

SPI works on channel 1.
I checked the connections over and over again and the screen remains white.

#include "SPI.h"
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM_SPI2.h> // STM32 DMA Hardware-specific library

#define TFT_CS PB4
#define TFT_DC PA15
#define TFT_RST PB3

Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); // Use hardware SPI


stevestrong
Thu Jan 18, 2018 7:27 am
@stm32user
you can use the default library from the Roger’s (or my) repo, it was implemented the possibility to pass the SPI instance as input paramter to the library.
So you can define which SPI interface you would like to use, and also the frequency if different from 36MHz:
#include <Adafruit_ILI9341_STM.h> // no need to include SPI.h

SPIClass mySPI(2); // use SPI2
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

void setup()
{
...
tft.begin(mySPI); // this will set the SPI clock to 36MHz.
/* alternative:
uint32_t frequency = 18000000;
tft.begin(mySPI, frequency);
*/
...
}


stm32user
Thu Jan 18, 2018 11:19 am
@stevestrong thank you for reply.

stm32user
Thu Jan 18, 2018 11:56 am
#include "SPI.h"
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM.h> // STM32 DMA Hardware-specific library

#define TFT_CS PB4
#define TFT_DC PA15
#define TFT_RST PB3

SPIClass mySPI(2); // use SPI2
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

void Setup(){
tft.begin(mySPI);
tft.fillScreen(ILI9341_BLACK);
}


stevestrong
Thu Jan 18, 2018 12:17 pm
Try this:
#include <SPI.h>
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM.h>

#define TFT_CS PB4
#define TFT_DC PA15
#define TFT_RST PB3

SPIClass mySPI(2); // use SPI2
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

void setup()
{
Serial.begin(9600);
while ( !Serial );
delay(1000);

Serial.println("ILI9341 Test!");

tft.begin();
}
void loop()
{
tft.fillScreen(ILI9341_BLACK);
delay(1000);
tft.fillScreen(ILI9341_RED);
delay(1000);
tft.fillScreen(ILI9341_GREEN);
delay(1000);
tft.fillScreen(ILI9341_BLUE);
}


stm32user
Thu Jan 18, 2018 12:21 pm
I use StLink
this code did not work !

tft.begin(mySPI);
I also tried doing


stevestrong
Thu Jan 18, 2018 1:45 pm
It is clear, that it does not work if you use STlink and don’t define SERIAL_USB.

How old is your repository local copy?
Because PB3/PB4/PA15 are used by the debug interface, they were previously reserved for debugging, and not available as normal IO pins.

With this patch this problem has been fixed, so you should update your local copy from github.

And then try this:
#include <SPI.h>
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM.h>

#define TFT_CS PB4
#define TFT_DC PA15
#define TFT_RST PB3

SPIClass mySPI(2); // use SPI2
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

void setup()
{
tft.begin();
}
void loop()
{
tft.fillScreen(ILI9341_BLACK);
delay(1000);
tft.fillScreen(ILI9341_RED);
delay(1000);
tft.fillScreen(ILI9341_GREEN);
delay(1000);
tft.fillScreen(ILI9341_BLUE);
delay(1000);
}


stm32user
Thu Jan 18, 2018 2:13 pm
my @file wirish/stm32f1/wirish_debug.cpp

void enableDebugPorts(void) {
afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);
}


stevestrong
Mon Jan 22, 2018 9:48 am
What if you use other pins as control pins? Have you tried?

minime
Sun Jun 03, 2018 11:33 pm
stm32user

btw did you get working ?.


minime
Mon Jun 18, 2018 4:51 am
am using upto date official repo with arduino 1.85
// spi2
#define TFT_CS PB12
#define TFT_DC PB11
#define TFT_RST PB10

HardwareTimer pwmtimer(1);
const int pwmOutPin = PA8;

/*----------------ROTARY_ENCODER2 ----------------*/
// timer4 as encoder 1
#define CLK1 PB6
#define DT1 PB7
#define SW1 PB11

/*----------------ROTARY_ENCODER2 ----------------*/
// timer3 as encoder 2
#define CLK2 PA7
#define DT2 PA6
#define SW2 PB12


stevestrong
Mon Jun 18, 2018 8:24 am
You are mapping both TFT_CS and SW2 to PB12.
And TFT_DC and SW1 to PB11.

Check again which pins are you mapping for which function.

EDIT
This is working on my bluepill:
// spi2
#define TFT_CS PB12
#define TFT_DC PB11
#define TFT_RST PB10

//SPIClass SPI_2(2); // use SPI2
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

void blink(void)
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin();
while (!Serial); delay(10);
SPI.setModule(2); // use SPI2
tft.begin(SPI, 9000000); // set direct frequency value in MHz
}

void loop()
{
Serial.println(millis());
blink();

tft.fillScreen(ILI9341_BLACK);
delay(250);
tft.fillScreen(ILI9341_RED);
delay(250);
tft.fillScreen(ILI9341_GREEN);
delay(250);
tft.fillScreen(ILI9341_BLUE);
delay(250);
}


minime
Tue Jun 19, 2018 3:25 am
stevestrong

Thank you very much , it worked very well , I wish just wish the rest of the men “mostly likely as i got to know many here over 2 years thus i doubt ever they would learn what giving means ” around here just learn from your great wonderful mind. thank you again.


All Comments

  • I am working on a project where I have a Lora sx1276 on spi 1 and TFT ili9341 on spi2. with 2 i/o lines for cs.

    when I run code on one spi it works but when I initialize both none works.

    is there a way both spi can work ?

    Jason 01/11/2020 6:20 PM Reply

Leave a Reply

Your email address will not be published. Required fields are marked *