SPI issues with ILI9341 T3 library and second device

Status
Not open for further replies.

palmerr

Well-known member
Hi,

I'm building something with two SPI devices on a Teensy 3.1 - an ILI9341 SPI display, which works fine on its own with either Paul S' T3 library or the standard Adafruit one.

As soon as I add a second SPI device, the display freezes. The Teensy is still up and running as Serial.print() is working after the SPI stops.

BTW the second SPI device (PGA2311 audio gain cell) isn't fitted at this stage, so its code effectively does nothing other than wiggle the outputs.

Here's a simple version of the Teensyduino code.

I'd be grateful for insights into where I have strayed from the approved SPI path.

Richard

#include <SPI.h>
#include "ILI9341_t3.h"
#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 8

// Shared SPI pins - with PGA2311 Gain Cell
#define TFT_MOSI 11
#define TFT_SCLK 13
#define TFT_MISO 12

// TFT hardware SPI
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

// gain cell shares SPI - so everything but CS is the same.
#define GC_CS 7
#define GC_MUTE 3

setup(){
pinMode(SPI_SS, OUTPUT); digitalWrite(SPI_SS, HIGH);​

tft.begin();
tft.fillScreen(ILI9341_BLACK);
...​

gcBegin();
}

SPISettings SPIsettingsGC(30000000, MSBFIRST, SPI_MODE1);

void gcBegin(void){
// assume SPI core pins are already set (MISO, MOSI, SCK)
// add CS pin
pinMode(GC_CS, OUTPUT);
digitalWrite(GC_CS, HIGH);

// toggle MUTE low for > 2ms to reset gain cell
if (GC_MUTE < 255) {​
pinMode(GC_MUTE, OUTPUT);
digitalWrite(GC_MUTE, HIGH); // Make sure a reset isn't already underway
delay(100);
digitalWrite(GC_MUTE, LOW);
delay(20);
digitalWrite(GC_MUTE, HIGH);
delay(150); // stabilise after MUTE​
}​
}
void gcSetVal(uint8_t gain_r, uint8_t gain_l){
SPI.beginTransaction(SPISettings(SPIsettingsGC));​
digitalWrite(GC_CS, LOW);​
SPI.transfer(gain_r);
SPI.transfer(gain_l);​
digitalWrite(GC_CS, HIGH);​
SPI.endTransaction();​
}
loop(){
tft.setCursor(10,90);
tft.print("Display");

gcSetVal(30, 40);​
}
 
I also had a problem with a second SPI device (SD) and the ILI9341 T3 library.

I did not have very long wires (maybe 10" as I recall).

I reorganized and shortened my wires and the problems went away.

Don't know if this will help you.

Richard
 
Richard

Thanks for the tip.

I unplugged the new SPI device entirely and it made no difference - the code works fine until I try to send data to the new device in gcSetVal().

The logic analyser shows that the MOSI & SCLK both stop at this point, rather than just degrading.

BTW, I'm using an embeddedcoolness Teensy RFX breakout board for the prototyping. It has no logic, so I doubt that it's introducing any errors as the second SPI device is used.

It leads me back to broken code, rather than bus loading.

Richard
 
If it were me, I might try playing around with this line: SPI.beginTransaction(SPISettings(SPIsettingsGC));

Just looks wrong to me... Could just be me

Example in the ILI9341 library I see: SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

I know Begin Transaction is defined as: inline static void beginTransaction(SPISettings settings)
Not sure if there is a constructor that takes an instance as well...

I know you have: SPISettings SPIsettingsGC(30000000, MSBFIRST, SPI_MODE1);
So have you tried doing the call like:SPI.beginTransaction(SPISettings(30000000, MSBFIRST, SPI_MODE1))

If that does not work, wonder about mixing Mode 0 and 1? Or 30mhz.

Again I may be completely off
 
If it were me, I might try playing around with this line: SPI.beginTransaction(SPISettings(SPIsettingsGC));

Just looks wrong to me... Could just be me

Example in the ILI9341 library I see: SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

I know Begin Transaction is defined as: inline static void beginTransaction(SPISettings settings)
Not sure if there is a constructor that takes an instance as well...
C++ gives you an auto-generated copy constructor that simply copies all data members. So SPISettings(SPIsettingsGC) is not wrong.
 
Thanks Kurt,

The 30MHz / MODE1 settings were left over from trying Paul S' optimised ILI9341 library.

Unfortunately neither converting to 8MHz / MODE0 in either the constructor mode
SPISettings SPIsettingsGC(8000000, MSBFIRST, SPI_MODE0);​
or inserting the parameters directly in the beginTransaction code
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));​
was effective. (Yes, I did try all the combinations!).

Given that simplest is best, I'll stay with the simplest version from now on - 8MHz / MODE0 and put the values directly into beginTransaction.

_________
HOWEVER,

Suspecting something problematic with the SS pin, I changed the constructor for the TFT to the short form:
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

Now things seem to be working: The SPI isn't stalling and I'm getting sensible looking (logic analyser) output on the second SPI. Whether the gain cell will like MODE0 / 8MHz remains to be seen!

Thanks again for setting me on the right path.

Richard
 
Thanks tni,

I was just removing all the possible places I could have introduced errors - bad parameters for that constructor was one of them.

I will confidently go back to the SPISettings(SPIsettingsGC) format.

BTW, I call SPI.transfer via gcSetVal() from within the ADC0 interrupt routine and I had forgotten to register the ADC0 interrupt with SPI. That was what was actually causing the routine to bomb.

Thanks, all, for your help. I have tidied up several areas of not-so-good code as a result.

Richard
 
I will confidently go back to the SPISettings(SPIsettingsGC) format.
There is no reason to use "SPI.beginTransaction(SPISettings(SPIsettingsGC))". You are only creating an unnecessary temporary copy of the SPISettings object (which the compiler may or may not optimize away). You can just use "SPI.beginTransaction(SPIsettingsGC)".
 
Status
Not open for further replies.
Back
Top