Hardware SPI not working for ILI9340/9341 TFT Display - SW SPI Does...



  • Recently wired up an Adafruit 2.2" TFT w/ ILI9340/41 compatible driver IC, and was unable to run the Adafruit GFX graphics tests successfully using hardware SPI. If I re-write the code to utilize software SPI, the graphics tests works as expected (much slower of course). I (successfully) tested the hardware SPI interface using the loopback example in the Spresense examples library. Wondering if anyone else has had this issue using the hardware SPI module and existing Arduino examples.

    I know Spresense + ILI9340/41 should work given the demos I have seen (camera rotation example, 3D rendering example) but I know those were built using the NUTTX dev environment and not Arduino. Any direction is appreciated!


  • DeveloperWorld

    @Cameron-R-MANN

    Hi, in the past I have used a ST7735 display with the standard Arduino drivers for that chip. And I remember that the drivers used specific register writes when used with original Arduino that didn't work with Spresense.

    If you have a look at:
    https://github.com/TE-KarlKomierowski/TFT/commit/ffbab7269e7ef7470f10a6f63fd077cfa46db180

    You can see that I made macros of the chip select settning/unsetting functions.

    Some designs ILI934x are very voltage sensitive, if you run them at 5V gpio voltage they don't work. So the GPIO voltage has to be 3.3v.

    It would help a lot if you could provide the code you are trying to run and also point to the tft driver you are using. And also the wiring diagram.



  • @TE-KarlKomierowski
    I appreciate the feedback...indeed I did notice the macros you added for the 7735 display. I have tried both 5V and 3.3V (the Adafruit display has a built in level shifter) to no avail. The first vertical column of pixels are the only ones active during the test, unless a screen"fill" operation is being performed (even then only 3/4 of the screen is filled). I suspect a timing issue, not complete corruption of data. When I am free this evening I will add a sample of code so it is clear what I am doing, and a table of pin assignments.

    In the meantime, so you have context of my development goal: Stream Spresense camera video "preview" to 320x240 TFT using SPI, then overlay that video stream w/real-time data such as GPS, graphics, etc...of course developing with Arduino IDE.



  • @TE-KarlKomierowski

    Wiring: Display / Spresense:

    DC -> 9
    RST -> 8
    CS -> 10
    MOSI -> 11
    MISO -> 12
    SCK -> 13

    (Display): https://www.adafruit.com/product/1480

    --> VIN @ 5V or 3.3V does not appear to change the behavior for HW or SW SPI methods.

    Code excerpt below...it is effectively the default Adafruit GFX example "graphicstest" for ILI9341, aside from the software SPI implementation:

    (source .h and .cpp): https://github.com/adafruit/Adafruit_ILI9341

    /***************************************************
      This is our GFX example for the Adafruit ILI9341 Breakout and Shield
      ----> http://www.adafruit.com/products/1651
    
      Check out the links above for our tutorials and wiring diagrams
      These displays use SPI to communicate, 4 or 5 pins are required to
      interface (RST is optional)
      Adafruit invests time and resources providing this open source code,
      please support Adafruit and open-source hardware by purchasing
      products from Adafruit!
    
      Written by Limor Fried/Ladyada for Adafruit Industries.
      MIT license, all text above must be included in any redistribution
     ****************************************************/
    
    
    #include "SPI.h"
    #include "Adafruit_GFX.h"
    #include "Adafruit_ILI9341.h"
    
    // For the Adafruit shield, these are the default.
    #define TFT_RST 8   // Didn't make a difference....
    #define TFT_DC 9
    #define TFT_CS 10
    
    // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
    //Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); // CRM: HARDWARE - NOT WORKING
    Adafruit_ILI9341 tft = Adafruit_ILI9341(10, 9, 11, 13, 8, 12); //CRM: SOFTWARE - WORKING
    // If using the breakout, change pins as desired
    //Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
    
    void setup() {
      Serial.begin(9600);
      Serial.println("ILI9341 Test!"); 
     
      tft.begin();
    
      // read diagnostics (optional but can help debug problems)
      uint8_t x = tft.readcommand8(ILI9341_RDMODE);
    

  • DeveloperWorld

    Hi @Cameron-R-MANN

    I played around with the drivers you linked to.
    And found that if you change the following line in Adafruit_SPITFT.h

    //void         initSPI(uint32_t freq = 0, uint8_t spiMode = SPI_MODE0);
    void         initSPI(uint32_t freq = 0, uint8_t spiMode = SPI_MODE3);
    

    or even better in Adafruit_ILI9341 line 189:

    initSPI(freq);
    to
    initSPI(freq, SPI_MODE3);
    

    you should get the desired result.

    Please give it a try and see if it works better.

    BR
    Karl



  • @TE-KarlKomierowski

    It works! Edited Adafruit_ILI9341.cpp to isolate the changes to ILI9341 only. Saved all files and re-ran the example successfully. Very good information going forward.

    As soon as I read "SPI_MODE....." I facepalmed myself. I debugged an issue with an ADC not too long ago and this was the issue, SPI clock polarity/phase. Even dragged out the logic analyzer on that problem, and observed the bits were shifted....phasing issue. Probably the same road I would have taken to investigate this.

    Thanks Karl! 👍