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

Thread: Noisy, unintelligible SPI signals using T3SPI

  1. #1
    Junior Member
    Join Date
    Jul 2015
    Posts
    13

    Noisy, unintelligible SPI signals using T3SPI

    I'm trying to use Teensy 3.0's both as a master and a slave in an SPI setup. However, trying to use the example sketches provided with the library, I haven't been successful at getting the Teensy to send out any signal recognizable by SPI. After fixing a small compile-time error in the example (changing CTAR0 to CTAR_0 in two places), the signals look like this:

    Click image for larger version. 

Name:	t3spi.jpg 
Views:	129 
Size:	169.1 KB 
ID:	4737

    (Pictured above is a single transmission. This happens every 2 seconds--as instructed by the example code--before all pins go HIGH or LOW for the remainder of the 2 seconds.)

    As you can see, none of the pins do what they are supposed to: clock is not periodic, ENABLE doesn't go low. This is not a problem with the Teensy, because I have run Nick Gammon's SPI example master code and seen this (on the same Teensy):

    Click image for larger version. 

Name:	Gammon_master_example success.jpg 
Views:	134 
Size:	76.7 KB 
ID:	4738

    I started with Arduino 1.6.5 and Teensyduino 1.24, but suspected that my software version might be the problem. Now I'm running Arduino 1.0.6 and Teensyduino 1.20. I am using a Teensy 3.0 (black) and the default output pins.

    Does anyone have experience in t3spi that could help me with this?

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,239
    Quote Originally Posted by trent View Post
    I'm trying to use Teensy 3.0's both as a master and a slave in an SPI setup. However, trying to use the example sketches provided with the library, I haven't been successful at getting the Teensy to send out any signal recognizable by SPI. After fixing a small compile-time error in the example (changing CTAR0 to CTAR_0 in two places), the signals look like this:

    Click image for larger version. 

Name:	t3spi.jpg 
Views:	129 
Size:	169.1 KB 
ID:	4737

    (Pictured above is a single transmission. This happens every 2 seconds--as instructed by the example code--before all pins go HIGH or LOW for the remainder of the 2 seconds.)

    As you can see, none of the pins do what they are supposed to: clock is not periodic, ENABLE doesn't go low. This is not a problem with the Teensy, because I have run Nick Gammon's SPI example master code and seen this (on the same Teensy):

    Click image for larger version. 

Name:	Gammon_master_example success.jpg 
Views:	134 
Size:	76.7 KB 
ID:	4738

    I started with Arduino 1.6.5 and Teensyduino 1.24, but suspected that my software version might be the problem. Now I'm running Arduino 1.0.6 and Teensyduino 1.20. I am using a Teensy 3.0 (black) and the default output pins.

    Does anyone have experience in t3spi that could help me with this?
    What speed are you using ?
    How long is the connection ?

  3. #3
    Junior Member
    Join Date
    Jul 2015
    Posts
    13
    Rookie mistake in not checking my speed. It was at 24 MHz.

    Now I've got it set to SPI_CLOCK_DIV8, and I can read it on my network analyzer. However, my CS0 pin (which I assume is pin 10) is not going low when the transmission starts. Thoughts?

    Click image for larger version. 

Name:	enable not enabling.jpg 
Views:	91 
Size:	144.2 KB 
ID:	4739

    Appended note: I can make sense of the noise now.

    And here's my code (the bold represents the changes I made to the code):


    #include <t3spi.h>

    //Initialize T3SPI class as SPI_MASTER
    T3SPI SPI_MASTER;

    //The number of integers per data packet
    #define dataLength 256

    //Initialize the arrays for outgoing data
    //volatile uint8_t data[dataLength] = {};
    volatile uint16_t data[dataLength] = {};


    void setup(){

    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);
    pinMode(CS0, OUTPUT);

    Serial.begin(115200);

    //Begin SPI in MASTER (SCK pin, MOSI pin, MISO pin, CS pin, Active State)
    SPI_MASTER.begin_MASTER(SCK, MOSI, MISO, CS0, CS_ActiveLOW);

    //Set the CTAR (CTARn, Frame Size, SPI Mode, Shift Mode, Clock Divider)
    //SPI_MASTER.setCTAR(CTAR1,8,SPI_MODE0,LSB_FIRST,SPI _CLOCK_DIV4);
    SPI_MASTER.setCTAR(CTAR_0,16,SPI_MODE0,LSB_FIRST,SPI_CLOCK_DIV32);

    //Populate data array
    for (int i=0; i<dataLength; i++){
    data[i]=i;}

    //Wait for Slave
    delay(5000);
    }
    Last edited by trent; 07-23-2015 at 07:36 PM. Reason: add note

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,357
    Quote Originally Posted by trent View Post
    However, my CS0 pin (which I assume is pin 10) is not going low when the transmission starts. Thoughts?
    Presumably you want the SPI port to control pin 10?

    Each pin has a mux. By default, the pins are configured on mux channel zero, which causes the pin to be disabled. If you want the pin to be controlled by GPIO, its mux needs to be configured for channel 1. The pinMode() function does that for you.

    If you want the pin to be controlled by SPI, its mux needs to be configured for channel 2. The mux settings for all pins are documented in a big table in chapter 10 of the reference manual, on page 209.

    The header file core_pins.h defines convenient names for each mux config register. For pin 10, use CORE_PIN10_CONFIG.

    https://github.com/PaulStoffregen/co...re_pins.h#L373

  5. #5
    Junior Member
    Join Date
    Jul 2015
    Posts
    13
    Quote Originally Posted by PaulStoffregen View Post
    Presumably you want the SPI port to control pin 10?
    If you want the pin to be controlled by SPI, its mux needs to be configured for channel 2. The mux settings for all pins are documented in a big table in chapter 10 of the reference manual, on page 209.

    The header file core_pins.h defines convenient names for each mux config register. For pin 10, use CORE_PIN10_CONFIG.

    https://github.com/PaulStoffregen/co...re_pins.h#L373
    So if I want pin 10 to be controlled by SPI, I do something like

    CORE_PIN10_CONFIG = 3;

    in setup?

  6. #6
    Senior Member
    Join Date
    Dec 2013
    Location
    Brasilia, Brazil
    Posts
    166
    You may want to take a look at SPFIFO.h: https://github.com/PaulStoffregen/co...nsy3/SPIFIFO.h

    Code:
    CORE_PIN10_CONFIG = PORT_PCR_MUX(2);
    
    Or even t3spi's enablePins method:
    Code:
    void T3SPI::enablePins(uint8_t sck, uint8_t mosi, uint8_t miso, uint8_t cs, bool activeState){
    	if (sck == 0x0D){
    		CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);}	//Set Pin13 Output & SCK
    	if (sck == 0x0E){
    		CORE_PIN13_CONFIG = PORT_PCR_MUX(1);
    		CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);}	//Set Pin14 Output & SCK
    	if (mosi == 0x0B){
    		CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);}	//Set Pin11 Output & MOSI
    	if (mosi ==  0x07){
    		CORE_PIN7_CONFIG  = PORT_PCR_DSE | PORT_PCR_MUX(2);}	//Set Pin7  Output & MOSI
    	if (miso == 0x0C){
    		CORE_PIN12_CONFIG = PORT_PCR_MUX(2);}					//Set Pin12 Input & MISO
    	if (miso ==  0x08){
    		CORE_PIN8_CONFIG  = PORT_PCR_MUX(2);}					//Set Pin8  Input & MISO
    	enableCS(cs, activeState);
    }
    Last edited by jbliesener; 07-24-2015 at 02:26 AM.

  7. #7
    Junior Member
    Join Date
    Jul 2015
    Posts
    13
    Got it working. Btmcmahan's T3SPI example worked well without having to designate these pin modes. Turns out the problems were more down-to-earth (literally): grounding issues with my network analyzer and needing the master to run MISO to MOSI and MOSI to MISO. Thanks for all the help!

  8. #8
    Glad to hear it. But I know there are some problems with the Master/Slave lib, specifically the ctar0 (ctar_0) issue. But also, I've experience issues with the data on the slave end not matching up with the master.

    For example:
    The master sends out 1, 2, 3, 4 in 4 separate SPI transactions.
    The slave reads 0, 1, 2, 3.

    For some reason, and I can't figure out why, the slave seems to boot with a value already inside the spi register. I can't seem to prevent this, but I have been able to do a Syncing process to get the data aligned.

  9. #9
    I've been working on SPI slave stuff using btmcmahan's library and as far as I can tell the only way that it's possible to get the slave FIFO in sync with the external master is if you actually toggle the _SS pin. I had it pulled low since it's the only thing on my bus but I've been unable to find any combination of register manipulation that will clear out whatever leftover junk you happen to have in there before valid frames started.

  10. #10
    That's interesting. When are you toggling the SS pin? Just once during the setup () to clear the junk? Or do you have to toggle it with every transfer?

  11. #11
    I actually have what's basically an end of frame signal, so I'm just using that for _SS right now but when I get the chance I'll try controlling it from another pin on the slave device and just doing it once at the initial sync (I only figured out this was an issue last night). Even if that appears to fix it I'd be very tempted to do it every transfer as it appears to empty the shift register and there's no easy way to tell if anything has gone wrong with your frames unless you control the protocol and can do some sort of CRC.

  12. #12
    Well it definitely sounds promising. Let us know what you find out, this issue has been plaguing me for months.

  13. #13
    If I manually hold _SS high until SPI is started up I seem to get clean frames until I deliberately mess with the signal to throw it off, however I wouldn't want to count on that in cases where a valid _SS is easy. Keep in mind also that I'm not doing any transfers back to the Master, I'm strictly reading in the data, so having _SS working might not fix the transmit side.

    Here's the current version of my hybrid code (embedded in a little project specific junk), but it's pretty similar to the slave portions of your library.

    Code:
    #include "DMAChannel.h"
    
    // Display size
    #define FRAME_COUNT 4
    #define ROW_COUNT 32
    #define COL_COUNT 128
    #define dataLength  COL_COUNT / 16
    
    // Dot data
    uint16_t data[dataLength];
    volatile uint8_t dataPointer;
    uint16_t frames[FRAME_COUNT][ROW_COUNT][dataLength];
    volatile uint8_t frame = 0;
    volatile uint8_t row = 0;
    volatile bool gotFrame = false;
    
    // Input pins
    const int COL_LATCH = 3;
    const int ROW_DATA = 2;
    const int ROW_CLK = 4;
    
    // Output pins
    const int SS_TEST = 1;
    
    // DMA channel
    DMAChannel* spi0RxDMA;
    
    void setup() {
      pinMode(ROW_DATA, INPUT_PULLUP);
      pinMode(ROW_CLK, INPUT);
      pinMode(COL_LATCH, INPUT_PULLUP);
      pinMode(SS_TEST, OUTPUT);
      
      Serial.begin(115200);
    
      // Configure pins for use by SPI0
      CORE_PIN10_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_PE | PORT_PCR_PS;
      CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
      CORE_PIN12_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_PE;
      CORE_PIN13_CONFIG = PORT_PCR_MUX(2);
      
      // Enable clock to SPI0
      SIM_SCGC6 |= SIM_SCGC6_SPI0;
      SPI0_MCR = SPI_MCR_HALT | SPI_MCR_MDIS | SPI_MCR_PCSIS(1<<0);
      
      SPI0_CTAR0_SLAVE = SPI_CTAR_FMSZ(15); // 16 bit frames, on rising edge
      
      // Enable FIFO Drain Request Interrupt
      /*
      SPI0_RSER = SPI_RSER_RFDF_RE;
      NVIC_ENABLE_IRQ(IRQ_SPI0);
      */
      
      // Enable FIFO Drain Request DMA
      SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS;
      spi0RxDMA = new DMAChannel();
      spi0RxDMA->source((volatile uint16_t&) SPI0_POPR);
      spi0RxDMA->destinationBuffer(data, dataLength * sizeof(uint16_t));
      spi0RxDMA->disableOnCompletion(); 
      spi0RxDMA->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX);
     
      //Enable Row Data Interrupt
      attachInterrupt(digitalPinToInterrupt(ROW_CLK), row_clk_isr, FALLING);
      
      //Enable Dot Latch Interrupt
      attachInterrupt(digitalPinToInterrupt(COL_LATCH), col_latch_isr, RISING);
    
      // Wait for frame alignment
      do {
       SPI0_MCR |= SPI_MCR_CLR_RXF;
       digitalWriteFast(SS_TEST, HIGH);
      } while (digitalReadFast(ROW_CLK) || !digitalReadFast(COL_LATCH));
      digitalWriteFast(SS_TEST, LOW);
    
      // Turn on the SPI
      SPI0_MCR &= ~SPI_MCR_HALT & ~SPI_MCR_MDIS;
    }
    
    int counter = 0;
    
    void loop() {
    
     if (gotFrame) {
      uint8_t currentFrame = frame;
      uint8_t currentRow = row;
      
      gotFrame = false;
      
      memcpy(frames[currentFrame][currentRow], data, sizeof(data));
        
      // REMOVED DEBUG CODE DUMPING FRAME TO USB
      }
    
    }
    
    
    //Interrupt Service Routine to handle incoming data
    /*
    void spi0_isr(void) {
      while (SPI0_SR & 0xF0) {
        data[dataPointer++] = SPI0_POPR;
      }
      
      SPI0_SR |= SPI_SR_RFDF;
    }
    
    void col_latch_isr(void) {
      if (dataPointer < 8) {
        while (SPI0_SR & 0xF0) {
          data[dataPointer++] = SPI0_POPR;
        }
        SPI0_SR |= SPI_SR_RFDF;
      }
      
      dataPointer = 0;
      
      frame++;
      gotFrame = true;
    }
    */
    
    // DMA to handle incoming data
    void col_latch_isr(void) {
     spi0RxDMA->disable();
     spi0RxDMA->clearComplete();
     spi0RxDMA->enable();
      
      frame++;
      gotFrame = true;
    }
    
    void row_clk_isr(void) {
      if (digitalReadFast(ROW_DATA) == HIGH) {
        row = 0;
      }
      else {
        row++;
      }
    
      frame = 0;
    }

Posting Permissions

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