Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: SPI issues with ILI9341 T3 library and second device

  1. #1
    Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    55

    SPI issues with ILI9341 T3 library and second device

    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);
    }

  2. #2
    Senior Member
    Join Date
    Jan 2014
    Posts
    157
    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

  3. #3
    Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    55
    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

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,929
    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

  5. #5
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    Quote Originally Posted by KurtE View Post
    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.

  6. #6
    Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    55
    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

  7. #7
    Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    55
    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

  8. #8
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    Quote Originally Posted by palmerr View Post
    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)".

  9. #9
    Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    55
    TNI.

    Thanks again.

    Richard

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •