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

Thread: SPI basic transactions

  1. #1

    SPI basic transactions

    To better understand the logic of SPI devices I have some questions that may also be helpful to others with the same confusion.
    Also my device does not have a written library.

    This link is to the teensy spi information:
    https://www.pjrc.com/teensy/td_libs_SPI.html

    From reading this over I want to understand whats going on, on the basic usage

    SPI.begin() ## This starts the SPI

    SPI.beginTransaction(SPISettings(clockspeed, MSBFIRST, SPI_MODE0)) ## This sets SPI settings

    digitalWrite(SSpin, LOW) ## This Sets the Chipselect pin LOW or HIGH depending on the device to start that particular device communication

    SPI.transfer(data) ## This sends data to What?

    SPI.endTransaction() ## this terminates the SPI


    My device has Register Banks, and Addresses.

    would I code this

    SPI.transfer(BANK)

    then I could read through the registers with

    SPI.transfer(register)

    If i have 3 registers , How would I read a particular register?

    a = SPI.transfer(register)

    thanks for the help

  2. #2
    Moderator Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,346
    It would be really good to know which SPI you use, and if a datasheet is available.. if you want help
    SPI is only about DATA - it does not know about banks or registers. This is device-specific.

  3. #3
    OK what i'm kinda dealing with is a datasheet that cannot be released.
    So i'm trying to figure this out.
    With analog devices ofcourse you see its value on the pin
    How would you explain the stream , does it have to be parsed? what signals do we look for ?

    not sure if thats the right thinking.

    As in this function from the spi page

    int digitalPotWrite(int address, int value) {
    // take the SS pin low to select the chip:
    digitalWrite(slaveSelectPin,LOW);
    // send in the address and value via SPI:
    SPI.transfer(address);
    SPI.transfer(value);
    // take the SS pin high to de-select the chip:
    digitalWrite(slaveSelectPin,HIGH);
    }

    this selects an address then writes a value
    how would I
    select an address and read a value ?

  4. #4
    Moderator Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,346


    https://www.pjrc.com/teensy/td_libs_SPI.html


    value = transfer(0x00); <- the 0x00 is ok in most cases, but not all. it depends on your maximum secret device.

  5. #5
    "value = transfer(0x00); <- the 0x00 is ok in most cases, but not all. that depends on your device."

    So this would be the value read?

    and if i had to change addresses lets say its
    01
    02
    03

    would that function run completley through? would each number have an initial value placeholder?
    and i would pull up or down the SS between reads of different addresses?
    Or would it stream in then after reading a bunch, then I pull SS up or down?

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,709
    Quote Originally Posted by ben10teensy View Post
    SPI.beginTransaction(SPISettings(clockspeed, MSBFIRST, SPI_MODE0)) ## This sets SPI settings
    Yes, it establishes the settings. It also prevents other libraries (which use interrupts) from accessing the SPI, until you do SPI.endTransaction(). That's a non-issue if you don't have any other libs accessing SPI, but it's an important safety feature which you get automatically by using this function. It's good practice to complete your communication and call SPI.endTransaction() as soon as possible, then actually do something with whatever data you communicated.

    SPI.transfer(data) ## This sends data to What?
    The "data" byte is transmitted to the MOSI (or DOUT) pin while 8 clocks pulses are generated on the SCK pin. Whatever signal happens to be on the MISO (or DIN) pin is captured as well, though you don't have to use it if you don't care.

    This is how SPI works. Data output and input always happen together. Most SPI chips expect you to send them commands and do not send you anything useful during those clocks, so you would just ignore the return value when sending if those cases. Many chips that give you data ignore whatever you send, so when receiving it's common to send 0 or 255.

    There are a huge number of SPI chips, all with their own expectations about which bytes you send and receive.

    Almost all (but there are a few exceptions) SPI chips need you to drive their chip select (or SS) signal low before any data transfer, and then bring it high when you're done. While this is the norm, there are some chips which need extra clock pulses after the chip select is high, where data is usually ignored or expected to be a specific value during those extra clocks.

    It's up to you to use the right combination of digitalWrite and SPI.transfer to communication with whatever chip you're using.

    When it comes to communication with humans, we're much more flexible than SPI chips. But still, some ways work better than others. When you leave out details, like even the part number of the chip you're using, you cut off opportunity for people to better help you. Likewise for posting the actual code you've written. Instead, only a rather generic message like this can be written. If I or others happen to know of any specific issues with the chip you're using, or there's some subtle but important issue with your code, or some related thing has been misunderstood, you lose the chance to get help with the questions you didn't know to ask....

  7. #7
    Moderator KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,070
    As Frank mentioned, SPI is simply a mechanism to transfer data.
    That is all that is really defined is, when you do something like: x = SPI.transfer(y);

    Since you are using the SPI library it is assumed you are the SPI master. So it will drive the clock signal at the specified clock speed, in the correct order (MSB or LSB) and with a value of 1 either being High or LOW and maybe when the data is valid (leading or trailing edge) (depending on mode). The Master (teensy) will stream out the bits of Y on the MOSI (or SDO) pin and it will stream in data on the MISO(also known as SDI), and will return the data into the Y register.

    With SPI there may be multiple slave devices and the way they know the data is for them and/or expected from them is their Chip Select pin is asserted.

    That is more or less all the system knows.

    So then each device may setup it's on structure on what these data bytes mean...

    Some devices may expect a command from the host, which will produce N bytes of data to return. Some do this by special values, or timing. Others do it by having another data pin, which is used to tell the device if the byte sent to it should be interpreted as a command or as data. Example of this is the ILI9341 display.

    So you need to understand your actual device in order to know how to do things like set the bank and read a register.

  8. #8
    Thats a very good explanation , my apologies for the lack of information, I do understand you are all trying to help with my limited knowledge and lack of code.
    I have a non-disclosure-agreement so I do not want to get in any trouble, and I'm currently talking with different programmers on how much this could cost to get going.
    I just wanted to get the ball rolling. but I really appreciate you all always answering our sometimes dumb questions

  9. #9
    So even if Y was sent through the from the Master
    I will read the value from Y after the first send .. In theory?

  10. #10
    Quote Originally Posted by ben10teensy View Post
    So even if Y was sent through the from the Master
    I will read the value from Y after the first send .. In theory?
    I only touched SPI once - in this code : github.com/PaulStoffregen/XPT2046_Touchscreen

    This tells the SPI Touch to send the X,Y and pressure data values needed. Not sure if it will help you - but with comments it was enough for me to understand Paul's code and do some mods to it when I added the interrupt enabled processing.

    The command goes out - whenever data goes out data comes in - but it is behind on the incoming data. This is where knowing your device commands and response details are critical. Knowing what commands and how much data and in what format it is returned in what order.

  11. #11
    Thanks I will look at it now

  12. #12
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    205
    High-jacking, but perhaps useful for ben10teensy as well:
    The Teensy page at https://www.pjrc.com/teensy/td_libs_SPI.html includes the paragraph:
    Slave Select Signal

    Any digital pin can be used for a SS (slave select) signal. The SPI library does not control the SS signals, because devices differ on when this is used, whether it is held low for multiple transfers or for each individual transfer, and so on. Control SS with digitalWrite().
    However, the SS pin must either be configured as an output, or if it is an input, it must remain low during the SPI transfer. Unconfigured pins default to input, and a pin with no signal can easily "float" to random voltages due to electrical noise. Always configure the SS pin as an output, or make sure it remains low.

    Most SPI devices are designed to work together with others, where SCK, MISO, and MOSI are shared. Each chip needs a separate SS signal. Only the selected chip will communicate. The others ignore SCK and MOSI, and avoid driving MISO when they are not selected.
    My current add-on board design uses pin 10 for another function - yet I want to use Teensy 3.6's SD card slot.

    Can I reassign the Slave Select pin for SPI with the SD card on Teensy 3.6?
    Can I then use pin 10 for something else? (it's a "ready for data" signal used by another SPI device)

    (If I need to change pin usage, I'll do that now before soldering on the just-arrived OshPark boards.)

  13. #13
    Moderator KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,070
    For the most part with normal apps using standard SPI (which is using SPI as the master) library you can use any digital pin as a chip select pin.
    You simply need to set the pin to be digital and typically set it high when not in use and low when your SPI output is supposed to go to the device.

    However there are a few libraries, like the ili9341_t3 library that uses some of the more advanced SPI functionality of the KinetisK boards (T3.x). With this library you need to use 1 or 2 of the hardware CS pins... The above mentioned library currently requires 2 CS pins, whereas my ili9341_t3n library can use 2, but also works with just 1 for the DC pin...

    Why these boards have a hardware SPI queue that allows you to queue a few items to be output and the queue entries have the ability to control hardware CS pins... Can explain more if needed, but again for most programs using the SPI library you are free to use other pins...

  14. #14
    Quote Originally Posted by Davidelvig View Post
    ...
    Can I reassign the Slave Select pin for SPI with the SD card on Teensy 3.6?
    Yes, The SPI pins running the T_3.6 SD card are unique hardware pins - it does not run from the standard SPI pins.

  15. #15
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    205
    Thanks. What's the PIN number for the SD card's Chip Select? or is it even exposed as a pin on the Teensy?

  16. #16
    Moderator KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,070
    If you are using the SD port on the Teensy 3.5 or 3.6 it does not use SPI, it has it's own hardware support, which is hopefully faster.

    If you look at any of the example programs you should see things like this in the comments:

    Code:
    // change this to match your SD shield or module;
    // Arduino Ethernet shield: pin 4
    // Adafruit SD shields and modules: pin 10
    // Sparkfun SD shield: pin 8
    // Teensy audio board: pin 10
    // Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
    // Wiz820+SD board: pin 4
    // Teensy 2.0: pin 0
    // Teensy++ 2.0: pin 20
    So to use it in your program for SD use the BUILTIN_SDCARD

    However if you are asking can I use the underlying IO pins for other things, the answer is yes - If you build an adapter to get to the IO pins. Which are IO pins 58-63. And many of these pins have other functions which can be used (alternate pins) for things like Serial1 or Serial5 or SPI1

    But again if use are using this for the SDCARD the underlying system is using the SDHC interface (pins in Mode 4) and not SPI (Mode 2)...

  17. #17
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    205
    I think I get it.
    I ran this line of code
    Code:
      Serial.printf("BUILTIN_SDCARD = %d\n", BUILTIN_SDCARD);
    to see that BUILTIN_SDCARD = 254 (and not 10).

    Cool. My board design will work!

    The "Mode X" designation you speak of is new to me. Does this relate to SPI_MODE0 - SPI_MODE3 at
    Code:
    https://www.arduino.cc/en/Reference/SPI
    , or to the 4 color-coded pin labels on the Teensy 3.6 reference card?

    Either way, thanks @KurtE.
    I think I'm in good shape!

  18. #18
    If you look in the SPI code the #==254 is probably a flag to use the alternate access Mode - on the unique pins noted above, wholly unique and different from any of the other SPI buses

  19. #19
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    205
    That's good news and clever design.
    Thanks

    And the "Modes?"

  20. #20
    Search and you can find :: wiki/Serial_Peripheral_Interface_Bus#Mode_numbers

    And indeed - processor specific code that bypasses standard SPI init:
    Code:
      uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin) {
        #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
        if (chipSelectPin == BUILTIN_SDCARD) {
          chipSelectPin_ = BUILTIN_SDCARD;
          uint8_t ret = KinetisSDHC_InitCard();
          type_ = KinetisSDHC_GetCardType();
          return (ret == 0) ? true : false;
        }
        #endif
        return SD_init(sckRateID, chipSelectPin);
      }

  21. #21
    Moderator Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,346
    SD on the T3.5 / T3.6 uses the pins PORTE_PCR0 .. PORTE_PCR5

  22. #22
    Moderator KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,070
    Quote Originally Posted by Davidelvig View Post
    That's good news and clever design.
    Thanks

    And the "Modes?"
    Sorry, I did not mean to confuse things. If you are asking about what I meant by Pins in different Modes... Almost every IO pin is setup on processor to be able to do different things, depending on how the Pin is configured... Sometimes mentioned as Mode sometimes mentiond as Alternate... When we first started testing on the T3.6 in the beta, I and several others made tables and the like to show this. Example from
    my Excel spreadsheet

    Code:
    On-board SD card (dedicated 4-bit SDIO)										
    ----------------		
    				ALT0		ALT1		ALT2		ALT3		ALT4		ALT5		ALT6		ALT7
    58	PTE0	ADC1_SE4a	ADC1_SE4a	PTE0		SPI1_PCS1	UART1_TX	SDHC1_D1	TRACE_CLKOUT	I2C1_SDA	RTC_CLKOUT
    59	PTE1	ADC1_SE5a	ADC1_SE5a	PTE1/LLWU_P0	SPI1_SOUT	UART1_RX	SDHC0_D0	TRACE_D3	I2C1_SCL	SPI1_SIN
    60	PTE2	PTE2/LLWU_P1	ADC1_SE6a	PTE2/LLWU_P1	SPI1_SCK	UART1_CTS_b	SDHC0_DCLK	TRACE_D2		
    61	PTE3	ADC1_SE7a	ADC1_SE7a	PTE3		SPI1_SIN	UART1_RTS_b	SDHC0_CMD	TRACE_D1			SPI1_SOUT
    62	PTE4	DISABLED			PTE4/LLWU_P2	SPI1_PCS0	UART3_TX	SDHC0_D3	TRACE_D0		
    63	PTE5	DISABLED			PTE5		SPI1_PCS2	UART3_RX	SDHC0_D2			FTM3_CH0
    Sorry pretty quick cut/paste from my excel document, so not all of the columns may align properly:
    But in this ALT0(Mode) typically implies Analog, ALT1 - Digital, ALT2 - SPI, ALT3 - Serial, ALT4 - SDHC, 5-?, 6 - I2C, 7 - Depends (alternate SPI in couple cases here)

    But again sorry, this digressed from your main topic. My main point was when you use on on board SDCard you are not using SPI (ALT 2), but instead SDHC (ALT 4)

  23. #23
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    205
    Got it.
    In one sense, I just want it to work.
    (But in the back of my mind, it's cool to see how this stuff works)

Posting Permissions

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