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

Thread: SPI - SPI.begin() and using multiple SPI devices

  1. #1
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    291

    SPI - SPI.begin() and using multiple SPI devices

    I'd welcome clarification on use of multiple SPI devices on Teensy.

    I am using Teensy 3.2 and 4 SPI devices, one of which employs 2 Chip Select pins for "command" vs "data" functions.
    So, 4 SPI devices, and 5 CS pins.

    • My Synth library (for VLSI's VS1053) calls SPI.begin() in the synth class constructor - setting both CS pins to OUTPUT and HI (CS = Teensy pin 26; XCS = Teensy pin 31)
    • The IMC library from SparkFun (ICM_20948) in a device "begin()" call explicitly says "// _spi->begin(); // Moved into user's sketch" (CS=Teensy pin 3)
    • The SD library, into which I pass a pin number - and the Teensy-embedded SD.h (not the optimized version) seems to use the equivalent of SD.begin() (CS =20)
    • The Adafruit_ST7789 library from AdaFruit for a TFT display (Adafruit's library uses 3 layers of SPI-initialization-related code to handle multiple display types) (CS=Teensy pin 29)

    I've tied all CS pins to 3V3 with 10k resistors (except the IMU with 2.2K to fit with an SPI level-shifting scheme)

    I am using the standard SPI pins for SCLK (13), MOSI(11) and MISO(12).
    Of note, perhaps, I use the "standard hardware SPI pin" (Teensy pin 10) for non-SPI purposes... in its TX2 role.

    Also noting: Arduino documentation says that SPI.begin() "Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low, and SS high."

    Everything works now, but I've had a number of SPI initialization challenges in the project over the last year.

    My questions:
    1. What's the best practice for calling SPI.begin: when (in what code) - various libraries (object constructor or explicit ::begin() method); or one or more "modules" in the sketch?
    2. Can I safely call SPI.begin() multiple times?
    3. If SPI begin sets the default CS pin to HIGH, could that subvert my use of TX2 in any way? (It does not yet appear to cause issues.)

    I'd also welcome any links to advice on use of multiple SPI devices on the same bus.

    Thanks!

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,699
    Typically if I know that there are multiple devices on the SPI buss,
    My setup code will do something like:

    Code:
    pinMode(CS1, OUTPUT);
    digitalWrite(CS1, HIGH);
    pinMode(CS2, OUTPUT);
    digitalWrite(CS2, HIGH);
    ...
    Before or after calling SPI.begin, but before the first call to libraries that setup SPI devices. Some of these library may convert their SPI CS pin to hardware SPI pin, although probably not ones like Adafruit_ST7789 (However ST7789_t3) may try to convert the CS pin to hardware CS. Although more likely the DC pin if possible).

    I have not had issues calling SPI.begin multiple times.

    SPI.begin() does not do anything with the hardware CS pin like pin 10. That only happens if your code does something like: SPI.setCS(10);
    Which will switch pin 10 to hardware CS mode. And in this case your code should not use digitalWrite(10, ...) to control this. Only libraries and/or code that understand SPI should do this, as you would then typically not use things like SPI.transfer, but instead you need to directly use the internal registers like on T3.x the PUSHR register to put the data onto the queue including information about which (if any) hardware CS Signals to assert during that transfer and if that hardware CS pin should remain asserted after the transfer.

  3. #3
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    291
    Thanks @KurtE!

    Can you see any problems dragging my CS pins HIGH with the resistors on the board?

    - Dave

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,699
    External PU resistors should also work fine for this as well.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,779
    10K pullup resistor should be fine.


    Quote Originally Posted by Davidelvig View Post
    except the IMU with 2.2K to fit with an SPI level-shifting scheme
    But I would be wary of an sort of resistor-based level shifting (if used on the data lines) for a system with 4 SPI devices.

  6. #6
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    291
    All SPI devices are working individually. All but SD play nicely together.
    When I add the SD card code, one of the other SPI devices get confused communications... right after SD.begin();
    With the SD.begin() call (and no actual read or write calls to the SD card), the SPI calls to the Synth chip get confused. (SPI.transfer to the Synth Chip registers result in bad register contents)

    I recall forum posts in the past related to mixed SPI use involving SD cards 9though I can't seem to find them now).
    Also, I've had a warning at the bottom of my Teensyduino info screen for ages (that did not seem to cause a problem)

    Multiple libraries were found for "SD.h"
    Used: /Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/SD
    Not used: /Applications/Teensyduino.app/Contents/Java/libraries/SD
    Is there a well-known problem with SD causing my issues?
    Can someone guide me to the solution?

    Teensy 3.2 (in this case, on my own board)
    Teensyduino (Arduino 1.8.13, Teensyduino 1.5.3)
    Mac OSX 10.14.6
    - Thanks!

  7. #7
    Member Dionysus's Avatar
    Join Date
    Apr 2020
    Location
    Chicago
    Posts
    32
    I'm sorry not to have a solution for you, but wanted to chime in to say that this problem was the bane of my existance for a couple weeks. I tried everything, and something worked. Which is great for me, but it means I can't give you a step-by-step explanation of how I fixed it! I can only say that I'm using SPI for the SD, a touchscreen, a display screen, and a flash mem chip, and for a long time it wouldn't play nicely together but now it does.

    I will definitely echo Kurt E's advice about explicitly stopping the other devices. Here's my code (basically the same as his):
    Code:
      pinMode(SDCARD_CS_PIN, OUTPUT);
      digitalWrite(SDCARD_CS_PIN, HIGH);  
      pinMode(TFT_CS, OUTPUT);                        // Make sure the screen doesn't try to access SPI while we're using it
      digitalWrite(TFT_CS, HIGH);  
      pinMode(TS_CS, OUTPUT);                         // Also make sure the touch interface doesn't mess with our SPI access
      digitalWrite(TS_CS, HIGH);  
      delay(1);
    At one point I just threw this in there every time I had an SPI call, but eventually I was able to back off. Now I only use that code in the function where I access the SD card and the Flash chip.

    I just seems really fiddly and I don't understand the logic, but I at least wanted to let you know that you aren't alone, and that I got it to work in my project. (:

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,699
    Also in cases like this would maybe help if you posted a hopefully smaller example of your code that is not working and maybe someone will see something, like maybe you need to either setup the CS pins before all of the begin/init functions or maybe external Pull Up resistors...

    And also maybe try our version of the ST7789 library. What SD Card reader. Again maybe picture heps

Posting Permissions

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