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

Thread: TRouble getting SPI to function with Teensyduino

  1. #1
    Junior Member
    Join Date
    Nov 2012
    Posts
    4

    TRouble getting SPI to function with Teensyduino

    Hello

    This may eb a very basic question, but it has really puzzled me in the last couple of hours not being able to get SPI to work.

    I am running teensyduino beta 7 from yesterday on MBP from last year.

    I am running this sketch:

    Code:
    #include <SPI.h>
    #define CS 10  // Digital 10
    byte sample = 0;
    
    void setup() {
      SPI.begin();
      pinMode(CS, OUTPUT);
    }
    
    void loop() {
      sample = random(255);
      digitalWrite(CS, LOW);
      SPI.transfer(sample);
      digitalWrite(CS, HIGH);
      delay(10);
    }
    and I can see from the Teensy 3.0 pin-sheet that came with the board that SPI should be:

    CS0 = 10 (as I have defined above)
    DOUT = 11
    SCK = 13

    When I measure pin 10 I get a buzz from the HIGH/LOW in the above code, but measuring on any other pin (except power pins) gives me no output/reaction.

    To me the above code should at least spit something out on pin 11 and 13 if I am reading the pin-sheet correctly.

    Is anybody able to see what I am doing wrong?

    Best Regards,

    Jakob

  2. #2
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    706

    try explicitly setting the SPI clock divider

    I confirm your example does not work for me either. It looks like Beta 7 has a missing default SPI clock setting. The below code does work for me.

    Code:
    #include <SPI.h>
    #define CS 10  // Digital 10
    byte sample = 0;
    
    void setup() {
      SPI.begin();
      // SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
      // SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
      SPI.setClockDivider(SPI_CLOCK_DIV16);  // T3_Beta7 requires this, no default? Set SPI clock to 1 MHz
      pinMode(CS, OUTPUT);
    }
    
    void loop() {
      sample = random(255);
      digitalWrite(CS, LOW);
      SPI.transfer(sample);
      digitalWrite(CS, HIGH);
      delay(10);
    }
    Last edited by JBeale; 11-09-2012 at 06:05 AM.

  3. #3
    Junior Member
    Join Date
    Nov 2012
    Posts
    4
    It worked!!!! Thank you so much
    No it's on to figuring out how those interrupts works, and we got synth...

    Jakob

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,450
    FYI: I wired up a DS3234 (SPI) RTC to my T3 using the same pins as with the Nano:
    Pin 13 SCK
    Pin 12 MISO
    Pin 11 MOSI
    Pin 10 SS
    I didn't need to override any defaults (*), just a vanilla SPI.begin() and it works fine (and the I2C DS3231 works fine too).

    (*) Correction: Actually I did use this after SPI.begin():
    Code:
      SPI.setBitOrder(MSBFIRST); 
      SPI.setDataMode(SPI_MODE1);
    Pete
    Last edited by el_supremo; 11-09-2012 at 04:25 PM.

  5. #5
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    It looks like Beta 7 has a missing default SPI clock setting
    Was this problem fixed in Beta8?

  6. #6
    Senior Member sumotoy's Avatar
    Join Date
    Nov 2012
    Location
    Venezia, Italia
    Posts
    421
    seems no, still needed for mcp23s08,mcp23xxx that works at 1mhz

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,664
    I'm working on this bug today. It'll be fixed in beta 9.

    The AVR emulation was setting a default speed... something I've been looking at for the last hour. It turns out the problem was in the SPI library. After it configures the SPI port, pinMode() is called to configure the MOSI (DOUT) and SCK pins. On Teensy 3.0, the pins alternate functions for pins are explicitly set, not an automatic takeover of the pin like on AVR. So those pinMode calls in SPI.cpp were setting these 2 pins back to normal I/O mode.

    Doing any additional configuration to the port by writing the SPE (enable bit) causes the AVR emulation code to configure the pins correctly again. That's why setting the speed makes it work. It wasn't the speed setting at all, but rather the pins being reconfigured away from SPI inside the SPI library.

    Beta 9 will have a fixed SPI library.

  8. #8
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    Further inspect these SPI clock settings. Are these correct?

    //SPI speed @ CPU Clock Teensy 3 @ 24 MHz @ 48 Mhz @ 96 MHz - (overclock)
    //SPI.setClockDivider(SPI_CLOCK_DIV2); // ~1.738 MHz 3.039 MHz 3.275 MHz
    //SPI.setClockDivider(SPI_CLOCK_DIV4); // ~1.211 MHz 2.202 MHz 2.351 MHz <-- Default Teensy 3 SPI ?
    //SPI.setClockDivider(SPI_CLOCK_DIV8); // ~754 KHz 1.420 MHz 1.516 MHz
    //SPI.setClockDivider(SPI_CLOCK_DIV16); // ~446 KHz 860 KHz 886 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV32); // ~238 KHz 466 KHz 476 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV64); // ~127 KHz 251 KHz 253 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV128); // ~ 65 KHz 129 KHz 130 KHz

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,664
    The AVR emulation code tries to give you the same speed as an AVR running at 16 MHz when Teensy 3.0 is at 48 or 96 MHz. It gives you half that speed at 24 MHz.

    So SPI_CLOCK_DIV4 should give 4 MHz when Teensy 3.0 is at 48 or 96 MHz. Like AVR, this is the default speed.

  10. #10
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    So SPI_CLOCK_DIV4 should give 4 MHz when Teensy 3.0 is at 48 or 96 MHz. Like AVR, this is the default speed.
    My Wavetek measured these values ?//SPI.setClockDivider(SPI_CLOCK_DIV4); // ~1.211 MHz 2.202 MHz 2.351 MHz <-- Default Teensy 3 SPI ?
    There is no 4 Mhz?

    Here is my loop code to measure the Teensy 3 SPI clock:

    void loop() {
    delay(10000); // wait tens seconds for T3
    Serial.println("Start SPI Test");
    // start the SPI library:
    SPI.begin();
    //SPI speed @ CPU Clock Teensy 3 @ 24 MHz @ 48 Mhz @ 96 MHz - (overclock)
    //SPI.setClockDivider(SPI_CLOCK_DIV2); // ~1.738 MHz 3.039 MHz 3.275 MHz
    SPI.setClockDivider(SPI_CLOCK_DIV4); // ~1.211 MHz 2.202 MHz 2.351 MHz <-- Default Teensy 3 SPI ?
    //SPI.setClockDivider(SPI_CLOCK_DIV8); // ~754 KHz 1.420 MHz 1.516 MHz
    //SPI.setClockDivider(SPI_CLOCK_DIV16); // ~446 KHz 860 KHz 886 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV32); // ~238 KHz 466 KHz 476 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV64); // ~127 KHz 251 KHz 253 KHz
    //SPI.setClockDivider(SPI_CLOCK_DIV128); // ~ 65 KHz 129 KHz 130 KHz

    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE3);
    start:
    digitalWrite(cs, LOW);
    SPI.transfer(-1);
    SPI.transfer(0);
    digitalWrite(cs, HIGH);
    goto start;
    }
    Last edited by t3andy; 12-04-2012 at 05:02 PM.

  11. #11
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,664
    Quote Originally Posted by t3andy View Post
    My Wavetek measured these values ?//SPI.setClockDivider(SPI_CLOCK_DIV4); // ~1.211 MHz 2.202 MHz 2.351 MHz <-- Default Teensy 3 SPI ?
    There is no 4 Mhz?
    If you connect a frequency counter that measures by counting the number of pulses over a period of time, you'll get less than 4 MHz, because of software overhead between each SPI transfer.

    Here's the the SS and SCK waveforms while running this code:

    Code:
      digitalWrite(CS, LOW);
      SPI.transfer(sample);
      SPI.transfer(sample);
      SPI.transfer(sample);
      digitalWrite(CS, HIGH);
    Click image for larger version. 

Name:	NewFile0.png 
Views:	285 
Size:	3.6 KB 
ID:	77

    Notice the dead times between each byte? A frequency counter that measures the number of pulses over 1 second or 0.1 seconds will count fewer than 4 million (if the software keeps repeating SPI.transfer) because of these idle times.

    If you use the 'scope to view the waveform, it's easy to see the SCK frequency really is 4 MHz (2.5 divisions at 100 ns per division).

    Click image for larger version. 

Name:	NewFile1.png 
Views:	265 
Size:	3.7 KB 
ID:	78

    The idles times between transfers also happen on AVR. With the Arduino SPI library, which was designed around AVR's simple SPI port, these idle times are unavoidable.

    Bill Greiman has published a version of his SdFat library that uses Teensy 3.0's SPI port in native mode (not AVR emulation). There is a small hardware FIFO which allows Bill's code to do SPI transfers with no idle time. If you want to achieve the full 4 Mbit/sec (or 24 Mbit/sec... the fastest speed the native hardware supports), I'd recommend using Bill's code.

Tags for this Thread

Posting Permissions

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