Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 4 FirstFirst 1 2 3 4 LastLast
Results 51 to 75 of 93

Thread: SPISlave_T4

  1. #51
    Junior Member
    Join Date
    May 2022
    Posts
    4
    Has anyone had any luck using a master and slave from the same device? i.e. preferably using a teens4.1 SPI as master and SPI1 as slave? or vice versa?
    I had it working with two teensy4.1 talking to each other over SPI but struggling to get it working on the same unit.
    In this instance I am using SPI1 as the Master but as soon as uncomment
    // mySPI.onReceive(myFunc);
    // mySPI.begin();
    It stops printing out the data being sent by the master

    Code:
    #include "SPISlave_T4.h"
    #include <SPI.h>
    #define CS_SLAVE 0
    #define CS_MASTER 10
    #define DISP_CHANNEL_1 32
    #define DISP_RETURN 19
    #define SPI_MASTER SPI1
    #define DATA 2
    
    SPISlave_T4<&SPI, SPI_16_BITS> mySPI;
    
    void myFunc()
    {
      Serial.println("START: ");
      uint8_t arr[] = {3, 2, 8, 3, 10, 11, 33, 13, 14};
      uint8_t i = 0;
      while (mySPI.active())
      {
        if (mySPI.available())
        {
          if (i++ > sizeof(arr))
            i = 0;
          mySPI.pushr(arr[i]);
          Serial.print("VALUE: ");
          Serial.println(mySPI.popr());
        }
      }
      Serial.println("END");
    }
    
    void setup()
    {
      // Serial
      Serial.begin(115200); // Begin Serial
    
      // Master SPI
      pinMode(CS_MASTER, OUTPUT);                                              // Set Master Chip Select as Output
      digitalWrite(CS_MASTER, HIGH);                                           // Set Master Chip Select High
      SPI_MASTER.begin();                                                      // Begin Master SPI
      SPI_MASTER.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // Begin Master SPI Transaction
    
      // Display Pins
      pinMode(DISP_RETURN, OUTPUT);
      pinMode(DISP_CHANNEL_1, OUTPUT);
      digitalWrite(DISP_RETURN, HIGH);
      digitalWrite(DISP_CHANNEL_1, HIGH);
    
      while (!Serial)
        ;
      // mySPI.onReceive(myFunc);
      // mySPI.begin();
    }
    
    void loop()
    {
      digitalWrite(CS_MASTER, LOW);
      for (uint16_t i = 0; i < 50; i++)
        Serial.println(SPI_MASTER.transfer16(i));
      digitalWrite(CS_MASTER, HIGH);
      delay(1000);
    }

  2. #52
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    same device? well i would imagine the interrupt being held open with active locked, the loop wouldnt be able to send anything until that's done, i never tested it as a loopback but thats where you would start, by breaking up the function to release back to the loop so it can refire as needed, obviously you'll need to handle a persistant buffer to keep track of the data while the gpio is asserted

  3. #53
    Junior Member
    Join Date
    Feb 2019
    Posts
    11

    onRecieve callback confusion

    Hello, I have some problems or some confusion how to read the bytes with the callback. I want to do 4 bytes so I first set up 32 bit configuration but now I have changed it to 8 bit and of course send this in 4 bytes. The data is not coming out in order. Based on comments and questions I have seen elsewhere in this forum I feel my experience is similar to what others have experience but I also have to admit I don't perfectly understand what the pushr function does.

    In this test I have set a pin high at the beginning and low at the end of the function I attached to onReceive and as you can see it is only raising after 3 bytes have been clocked. This is what I thought was happening but...

    Click image for larger version. 

Name:	TEK00014 - Copy.PNG 
Views:	10 
Size:	69.3 KB 
ID:	28711


    Further review shows there appears to be a pattern of 4 in which 3 assertions of the CS line (4 bytes each time) do not trigger the callback. The code for the Teensy4.1 should make it clear where the pin is being raised (green trace)

    Click image for larger version. 

Name:	tek00013(copy).png 
Views:	6 
Size:	62.7 KB 
ID:	28710

    Teensy LC - as SPI master NO problems with this function, just here as a reference
    Code:
    #include <Arduino.h>
    #include "SPI.h"
    
    constexpr int32_t READ_INTERVAL_MS   = 5;
    constexpr int32_t REPORT_INTERVAL_MS = 500;
    
    constexpr int32_t cs_pin        = 10;
    constexpr int32_t spi_clock_pin = 14;
    
    SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);
    
    elapsedMillis report;
    elapsedMillis read_spi_slave;
    
    /*
    X       11 MOSI confirmed, idles high, is transitioning on the trailing edge of the clock (falling edge)
    X       12 MISO PROBLEM: this data is from the other board - the teensy 4.1 SPI SLAVE
    X       10 CS confirmed active low a bit under 200us total span (4 bytes and 200000 clock speed)
    X       14 CLK  (requires manual change to different pin) idle low, active high  about 8us extra time between each byte
    */
    
    
    void setup() {
        Serial.begin(115200);
        pinMode(cs_pin, OUTPUT);
        digitalWrite(cs_pin, HIGH);
        SPI.setSCK(spi_clock_pin);
        SPI.begin();
        pinMode(LED_BUILTIN, OUTPUT);
        digitalWrite(LED_BUILTIN, HIGH);
    }
    
    
    void loop() {
        //
        static int32_t toggle         = 0;
        static int32_t result         = 0;
        static int32_t test_indicator = 0;
        int8_t adc_values[4];
    
        if (read_spi_slave > READ_INTERVAL_MS) {
            read_spi_slave = 1;
    
            SPI.beginTransaction(settingsA);
            digitalWrite(cs_pin, LOW);
            // reading only, so data sent does not matter what these are
            adc_values[0] = SPI.transfer(0xAA);
            adc_values[1] = SPI.transfer(test_indicator & 0xFF);
            adc_values[2] = SPI.transfer(0x55);
            adc_values[3] = SPI.transfer(0x55);
            digitalWrite(cs_pin, HIGH);
            SPI.endTransaction();
    
            result = adc_values[0] << 8;
            result |= adc_values[1];
            result = result << 8;
            result |= (adc_values[2] & 0x7F);
            result = (result << 8) >> 8;
            // this does not matter yet - byte values are being checked on the oscilloscope
        }
    
        // DEBUG OUTPUT but at a slower pace
        if (report > REPORT_INTERVAL_MS) {
            report = 1;
            Serial.print(millis());
            Serial.print("\t");
            Serial.println(result, DEC);
            digitalWrite(LED_BUILTIN, toggle);
            toggle = 1 - toggle;
            test_indicator++;
        }
    }
    teensy 4.1 SPI Slave - something wrong here. NOTE: the data being pushed is just fake, I am including an index number so that I can look on the scope and see if the bytes are the correct ones.

    Code:
    #include <Arduino.h>
    #include "SPISlave_T4.h"
    #include "SPI.h"
    
    constexpr int32_t READ_INTERVAL_MS   = 12;
    constexpr int32_t REPORT_INTERVAL_MS = 500;
    constexpr uint8_t cs_pin_1           = 6;
    constexpr uint8_t test_pin           = 2;
    
    int32_t spi_data_n      = 0;
    uint8_t spi_arr[]       = {3, 2, 8, 3};
    int32_t interrupt_count = 0;
    int32_t loop_count      = 0;
    SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);
    
    elapsedMillis report;
    elapsedMillis read_adc_ms;
    
    // T4 SLAVE using swapPins
    // 11 MOSI
    // 12 MISO
    // 10 CS
    // 13 CLK
    
    SPISlave_T4<&SPI, SPI_8_BITS> mySPI;
    
    void myFunc() {
        // There are 4 bytes being sent at 200khz clock speed SPI Mode 0
        // at 5ms intervals from Teensy LC
        // The CS line goes low and 4 bytes of clock come in
        // and 4 bytes of dummy data from MOSI
        // however, this test_pin does not raise until the beginning of
        // the 4th byte
        digitalWrite(test_pin, 1);
        interrupt_count++;
        while (mySPI.active()) {
            if (mySPI.available()) {
                spi_data_n++;
    
                if (spi_data_n > 3) {
                    spi_data_n = 0;
                }
                loop_count++;
                // looking at these bytes on the scope, lined up with Chip Select as trigger
                // The bytes are not lined up 0, 1,2 ,3 in fact they are randomly placed
                mySPI.pushr(0x50 | spi_data_n);
            }
        }
        digitalWrite(test_pin, 0);
    }
    
    void setup() {
        Serial.begin(115200);
        pinMode(test_pin, OUTPUT);
    
        mySPI.onReceive(myFunc);
        mySPI.begin();
        mySPI.swapPins(); // allows direct 10-10, 11-11, 12-12, 13-13
    }
    
    
    void loop() {
        // DEBUG OUTPUT
        if (report > REPORT_INTERVAL_MS) {
            report = 1;
            Serial.print(millis() - 2);
            Serial.print("\t");
            Serial.print(loop_count);
            Serial.print("\t");
            Serial.println(interrupt_count);
        }
    }


    My questions:
    Is it appropriate and correct to use 8-bit transfers even though I want to send 32 bits of data? I think I should stay this way because it is how I have had the most success. This code at least stays running and other attempts have led to worse problems I will not go into.

    This code is 'running' but is also useless because the bytes being sent are not what I intend to send.

    When is the onRecieve function supposed to be called? what is the trigger for this?

    how are the pushr and popr supposed to be used? Is there some kind of buffer at play here that causes my data is getting out of alignment?

  4. #54
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    for the 4.x slave check if you're using the GND beside the 5v pin, and not the one beside pin 0

    there is no buffer, this is a fixed register in the SPI hardware
    POPR receives byte from bus master
    PUSHR stores byte to be transfered to master

  5. #55
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    thanks for the quick response!, I added the extra GND connection. The images I see on the scope seem to indicate no signal problems relative to the low clock speed I am running. popr and pushr are quite straightforward I am glad to know there isn't something fancier behind those.

    I cannot understand the behavior of the myFunc() in which my code sets the pin high at the beginning and low at the end. I did another change and had my spi master send 8 bytes instead of 4. Now what I see is after 7 bytes sent the line goes high for the last byte. Previously it went high after 3 bytes. I will keep studying this.

    now I realize that one has to pushr the first byte before any transaction occurs because there must be something available to clock out upon the CS line going active. I added that to my setup()

    ? is the .active function meant to track the state of the CS signal?

    ? what is the .available() designed to do? is it checking the presence of a byte in the buffer? would this function have a way to know that I have grabbed the previous value?
    thanks!

  6. #56
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    update, I changed my Teensy LC SPI Master to send out 8 bytes at 100khz clock speed at the same 5ms intervals. Previously I used 200khz clock speed and sent 4 bytes. I get something kind of similar.


    This is showing that the peripheral sends some bytes out, but I cannot control which ones get sent in alignment with the packet.
    Click image for larger version. 

Name:	TEK00002.PNG 
Views:	6 
Size:	136.0 KB 
ID:	28722


    This shows the gpio that I am raising during the onRecieve event. Curiously it raises in alignment with the last byte. I don't think this is technically what is going on - after all how could it possibly predict the future ?!! but it is how this appears.
    Also if I widened the time scale on the scope I can see that this pin is only being raised for every other packet where previously it was happening every 4th. this is very odd ! ?

    Click image for larger version. 

Name:	TEK00000.PNG 
Views:	8 
Size:	82.8 KB 
ID:	28723


    Teensy 4.1 as SPI Slave - added some counters to help debugging

    Code:
    #include <Arduino.h>
    #include "SPISlave_T4.h"
    #include "SPI.h"
    
    constexpr int32_t READ_INTERVAL_MS   = 12;
    constexpr int32_t REPORT_INTERVAL_MS = 500;
    constexpr uint8_t cs_pin_1           = 6;
    constexpr uint8_t test_pin           = 2;
    
    int32_t spi_data_n      = 0;
    uint8_t spi_arr[]       = {3, 2, 8, 3, 0, 0, 0, 0}; // not used yet
    int32_t interrupt_count = 0;
    int32_t loop_count      = 0;
    int32_t cs_assert_time  = 0;
    SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);
    
    elapsedMillis report;
    elapsedMillis read_adc_ms;
    
    // T4 SLAVE using swapPins
    // 11 MOSI
    // 12 MISO
    // 10 CS
    // 13 CLK
    
    SPISlave_T4<&SPI, SPI_8_BITS> mySPI;
    
    void myFunc() {
        int32_t local_time;
        // There are 8 bytes being sent at 100khz clock speed SPI Mode 0
        // at 5ms intervals from Teensy LC
        // The CS line goes low and 8 bytes of clock come in
        // and 8 bytes of dummy data from MOSI
        // however, this test_pin does not raise until the beginning of
        // the 7th byte (of 8 transmitted within chip select being active)
        digitalWrite(test_pin, 1);
        interrupt_count = 0;
        local_time      = micros();
        while (mySPI.active()) {
            loop_count++;
            if (mySPI.available()) {
                spi_data_n++;
                interrupt_count++; // I would like this to be 8 but is actually 60-61
                if (spi_data_n > 7) {
                    spi_data_n = 0;
                }
    
                // looking at these bytes on the scope, lined up with Chip Select as trigger
                // The bytes are not lined up 0, 1, 2, 3, etc. in fact they seem randomly placed
                mySPI.pushr(0x50 | spi_data_n);
            }
        }
        cs_assert_time = micros() - local_time;
        digitalWrite(test_pin, 0);
    }
    
    void setup() {
        Serial.begin(115200);
        pinMode(test_pin, OUTPUT);
    
        mySPI.onReceive(myFunc);
        mySPI.begin();
        mySPI.swapPins();               // allows direct 10-10, 11-11, 12-12, 13-13
        mySPI.pushr(0x50 | spi_data_n); // put the first value
    }
    
    
    void loop() {
        // DEBUG OUTPUT
        if (report > REPORT_INTERVAL_MS) {
            report = 1;
            Serial.print(millis() - 2);
            Serial.print("ms\t");
            Serial.print(loop_count);
            Serial.print("\t");
            Serial.print(cs_assert_time);
            Serial.print(" cs us\t");
            Serial.print(interrupt_count);
            Serial.println(" counts during loop of onRecieve");
        }
    }


    Here is some of the output. I have timed the onRecieve function at about 86us and this corresponds with the trace I see on the scope. In order for me to get all the bytes out this Function should be active coincident to the CS line and then I would need some way to know 'when' each Byte is available. or I would need an interrupt for every single individual byte one at a time.

    222299ms 26879643 86 cs us 110 counts during loop of onRecieve
    222799ms 26940692 86 cs us 110 counts during loop of onRecieve
    223299ms 27001741 86 cs us 110 counts during loop of onRecieve
    223799ms 27062790 86 cs us 111 counts during loop of onRecieve
    224299ms 27123839 86 cs us 110 counts during loop of onRecieve
    224799ms 27184888 86 cs us 111 counts during loop of onRecieve
    225299ms 27245937 86 cs us 110 counts during loop of onRecieve
    225799ms 27306986 86 cs us 110 counts during loop of onRecieve
    226299ms 27368035 86 cs us 110 counts during loop of onRecieve
    226799ms 27429084 86 cs us 110 counts during loop of onRecieve
    227299ms 27490133 86 cs us 110 counts during loop of onRecieve
    227799ms 27551182 86 cs us 110 counts during loop of onRecieve
    228299ms 27612231 86 cs us 110 counts during loop of onRecieve
    228799ms 27673280 86 cs us 110 counts during loop of onRecieve
    229299ms 27734329 86 cs us 110 counts during loop of onRecieve

  7. #57
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    i don't see POPR used in your last code, both of them must be used. if you dont care for POPR (receiving) then flush it at very least:

    Code:
    (void)mySPI.popr();

  8. #58
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    shoot, no go on that. I tried that statement just after.. .and then just before the pushr in that loop and what this does is make the serial output halt/never start. There is still strange activity on the logic analyzer/scope but nothing worth bothering with. I am pretty sure I had that line in the code before and probably just randomly took it out as a try. I had been having problems where my serial output didn't work at all so I was happy to have that running. I did that testing before I put the scope on it.

    as you stated, I didn't use the code for receiving because I didn't intend to ever do anything with that data. Being just a single register (not a queue or buffer, etc.) I don't see why I would need to grab the value from it. couldn't it just keep getting over-ridden without being used?

    I'm not sure where to go next.

    are there any other working examples out there that I could try? I am still wondering what event is supposed to trigger the callback of onReceive.

  9. #59
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    I got an account and got the reference manual. I see the SPI (LPSPI ) peripheral has 16-word FIFO. This probably explains why my onReceive function was only being called each 4 transactions when the board was receiving 4 bytes - and when I changed to send 8 bytes it was every other transaction. There is some kind of buffer in the hardware or in the peripheral somehow there so I've got to deal with that.

  10. #60
    I am encountering some issues with communicating to a teensy 4.1 running the library with a teensy 4.0. The teensy 4.1 that is acting as a slave is hanging until it receives the first message over SPI. The slave functions normally and as expected after the first message is received.

    My goal is to have the 4.1 board running before the first SPI message without any hanging. Is this possible?

    I am receiving every message correctly, but it hangs until it receives the first message.

    Click image for larger version. 

Name:	spi.PNG 
Views:	7 
Size:	13.9 KB 
ID:	28787

    I have the hardware connected in the following way:
    Teensy 4.0 (Master) CS (10) MOSI (11) MISO (12) SCK (13) GND
    Teensy 4.1 (Slave) CS (10) MISO(12) MISO (11) SCK (13) GND

    My slave code for the teensy 4.1.
    This is the example program that is included with the library. I swapped the onReceive and begin function calls for the same reasons as previous users have stated in the forum.
    Code:
    #include "SPISlave_T4.h"
    SPISlave_T4<&SPI, SPI_8_BITS> mySPI;
    
    void setup() {
      Serial.begin(115200);
      while (!Serial);
      mySPI.onReceive(myFunc);
      mySPI.begin();
      
    }
    
    void loop() {
      Serial.print("millis: "); Serial.println(millis());
      delay(1000);
    }
    
    void myFunc() {
      Serial.println("START: ");
      uint8_t arr[] = { 3, 2, 8, 3, 10, 11, 33, 13, 14 };
      uint8_t i = 0;
      while ( mySPI.active() ) {
        if (mySPI.available()) {
          if ( i++ > sizeof(arr) ) i = 0;
          mySPI.pushr(arr[i]);
          Serial.print("VALUE: ");
          Serial.println(mySPI.popr());
        }
      }
      Serial.println("END");
    }
    My master code for the teensy 4.0
    This is example code from the base teensy SPI library.

    Code:
    #include <SPI.h>  // include the SPI library:
    
    const int slaveSelectPin = 10;
    
    void setup() {
      // set the slaveSelectPin as an output:
      pinMode (slaveSelectPin, OUTPUT);
      // initialize SPI:
      SPI.begin(); 
    }
    
    void loop() {
      // go through the six channels of the digital pot:
      for (int channel = 0; channel < 6; channel++) { 
        // change the resistance on this channel from min to max:
        for (int level = 0; level < 255; level++) {
          digitalPotWrite(channel, level);
          delay(10);
        }
        // wait a second at the top:
        delay(100);
        // change the resistance on this channel from max to min:
        for (int level = 0; level < 255; level++) {
          digitalPotWrite(channel, 255 - level);
          delay(10);
        }
      }
    }
    
    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); 
    }
    Last edited by TylerJulian; 06-23-2022 at 01:10 PM. Reason: (added image and clarification)

  11. #61
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    the master 4.x need a patch for the DSE bits, check out the commits for SPI_MSTransfer_T4, this only affects the master, just make sure your ground is the one next to the 5v pin (not near pin 0)

  12. #62
    Thank you for the quick reply!

    Is there a way to fix it on the slave side? I want to eventually switch the master over to one of the Texas Instrument microcontrollers leaving only the teensy as a slave.

  13. #63
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    just my opinions as new users of Teensy and the slave library....

    I have made some edits to the library to get my system working - just sharing what I did right or wrong - I have been observing the transactions on the scope as I do the changes.

    I changed this:
    SLAVE_IER = 0x1; /* RX Interrupt */

    to
    SLAVE_IER = LPSPI_IER_FCIE; // ((uint32_t)(1<<9))

    making use of #defines in imxrt.h

    what this does is set the interrupt to only occur at the end of a frame.

    TylerJulian, you are sending 2 bytes so you could change your slave to SPI_16_BITS instead of SPI_8_BITS. The receive and send buffers can hold 32 bit words.


    because I changed the interrupt to work on the end of the frame the receive FIFO has all the words (qty 1 in your case TylerJulian) and will be in need of one word for the TX FIFO for the next transaction.

    The nominal interrupt code could then be this (bear in mind the library adds additional code for the interrupt beyond this, to clear the flags and something else...)

    Code:
    void frame_complete_isr() {
        // at this point there should be 0 items in the send buffer
       
        // read one and get one 16 bit value
        mySPI.pushr(value);
        data_sent  = mySPI.popr();
        
    }
    although this does not account for errors or help get the fifo buffers into the correct state at startup. my code has some protections for this by reading the current size of each fifo buffer. it would only be active at program start, if ever.

    I didn't use the .active() or .available() because they don't seem needed when the interrupt runs at the end of the frame.

    although it is not pertinent to the most recent question, I added a definition for a 64 bit frame size because my master code is sending 2 32 bit words.
    Code:
    typedef enum SPI_BITS {
        SPI_8_BITS = 8,
        SPI_16_BITS = 16,
        SPI_32_BITS = 32,
        SPI_64_BITS = 64,
    } SPI_BITS;
    Last edited by themzlab; 06-23-2022 at 03:08 PM.

  14. #64
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    Quote Originally Posted by TylerJulian View Post
    Thank you for the quick reply!

    Is there a way to fix it on the slave side? I want to eventually switch the master over to one of the Texas Instrument microcontrollers leaving only the teensy as a slave.
    only thr t4.x masters needs specific dse bits set, other masters work fine

  15. #65
    Junior Member
    Join Date
    May 2022
    Posts
    12
    Hi all,

    Thanks for this library. I wondering if I could get some help! I've been tinkering with it for a while, and I don't understand some of the issues I am seeing. I have established communication between a master and slave T4.1. The data that comes from the master to the slave looks correct, and I can get up to 4 bytes returned from slave to master. But this only works when I have a few bytes hard coded to send. If I do anything in my code, I don't seem to see the changes and/or the changes don't make sense.

    Slave:
    Code:
    void setup() 
    {  
      // Debug output
      Serial.begin(9600);
    
      delay(2000);
    
      //init the SPI
      
      mySPI.begin();
      mySPI.swapPins();
      mySPI.sniffer(false);
      mySPI.onReceive(spi_interrupt);
       
      delay(2000);
    }
    
    void loop() 
    {
      relay_select(2);
      delay(1000);
      relay_select(13);
      delay(1000);
      // relay_select(2);
      // delay(1000);
    
      if(new_SPI)
      {
        new_SPI = false;
        relay_select(2); // make sound
      }
    }
    
    void spi_interrupt(void)
    {
    
      uint8_t arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      uint8_t i = 0;
      
      while ( mySPI.active() ) 
      {
        if (mySPI.available()) 
        {
          if ( i++ > sizeof(arr) )
          {
            i = 0;
          } 
          mySPI.pushr(arr[i]);    //i - 1?
          SPI_data = mySPI.popr();    
        }
      }
    }
    relay_select() just makes a ticking sound from a relay to let me know where the program is

    master code:
    Code:
    void setup (void)
    {
      Serial.begin(115200);                   //Starts Serial Communication at Baud Rate 115200 
      pinMode(ipbutton,INPUT);                //Sets pin 2 as input 
      pinMode(LED,OUTPUT);                    //Sets pin 7 as Output
      SPI.begin();                            //Begins the SPI commnuication
      SPI.setBitOrder(MSBFIRST);
      SPI.setDataMode(SPI_MODE0);
    
      SPI.setClockDivider(SPI_CLOCK_DIV32);    //Sets clock for SPI communication at 8 (16/32=0.5Mhz)
      
      digitalWrite(SS, HIGH);
      delay(500);
      digitalWrite(SS, LOW); 
      delay(500); 
      digitalWrite(SS, HIGH);
      delay(5000);
    }
    
    
    void loop(void)
    {
      Serial.println("Start");
      byte Mastersend;          
      uint8_t Mastereceive;
    
      Serial.println("test");
      digitalWrite(SS, LOW);       
      delay(10); 
      Mastereceive=SPI.transfer(0xAA);    // Update voltages command (should tick)
      Mastereceive=SPI.transfer(0xAA); 
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      digitalWrite(SS, HIGH);
      delay(3000);
        
      Serial.println("Writing initial byte");  
      digitalWrite(SS, LOW);       
      delay(10);           
      Mastereceive=SPI.transfer(0x07);    // Update voltages command (should tick)  
      Mastereceive=SPI.transfer(0xAA);    // Update voltages command (should tick)
      digitalWrite(SS, HIGH);
      
      delay(7500);    //allow time for updates, should hear tick go away
    
      Serial.println("Get readings");  
      digitalWrite(SS, LOW);       
      delay(10); 
      Mastereceive=SPI.transfer(0x01);    // Update voltages command (should tick)
      Mastereceive=SPI.transfer(0x01); 
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      Mastereceive=SPI.transfer(0xAA); 
      Mastereceive=SPI.transfer(0xAA);
      Serial.println(Mastereceive);
      digitalWrite(SS, HIGH);
    
      delay(1000);
    
      Serial.println("yup I'm alive");
    
    }
    As soon as the master sends an SPI byte, I no longer hear ticking and it seems like the the main loop is not running anymore. It never comes back until I reset the device. Is the interrupt hanging? Its odd because although the loop is not going, future reads from the master to return the correct bytes.

    If I try to change the contents of the array in the slave based on the byte sent by the master, i do notice a different value but its not the value I set.

    Any tips or advice for me?

    Thanks!

  16. #66
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    if you are using a T4.x master there is a slight bug in the DSE gpio bits, which is fixed in SPI_MSTransfer_T4. Other master controllers don't seem to have this issue. Also for your common ground don't use the GND pin next to pin 0 on master T4, use the one beside the 3.3/5v pins instead, either the GND or the pin config settings will help you get better results

  17. #67
    Junior Member
    Join Date
    May 2022
    Posts
    12
    Quote Originally Posted by tonton81 View Post
    if you are using a T4.x master there is a slight bug in the DSE gpio bits, which is fixed in SPI_MSTransfer_T4. Other master controllers don't seem to have this issue. Also for your common ground don't use the GND pin next to pin 0 on master T4, use the one beside the 3.3/5v pins instead, either the GND or the pin config settings will help you get better results
    Thanks for this!

    Are you suggesting that my master controller is not de-asserting the SS pin or something like that? I was able to observe that this isn't the case with a scope. In either case, my master is using SPI.h.

    Apologies if its apparent to a better programmer than me, but will a slave running SPI_MSTransfer_T4 interface with any (non bugged of course) master controller? Or do I need to use SPI_MSTransfer_T4 on the master as well? I'm using a T4.1 right now for a master, but long term this will not be the case. All I need to do is transfer a few bytes back and forth.

    Thanks!

  18. #68
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    SPI_MSTransfer_T4 is a 2-way daisy-chainable data transfer utility. It includes the slave and master headers and source files, with simple examples.

    if you prefer to keep a teensy4.x as master using SPISlave_T4 i suggest you use the mentioned common ground path and the patch that is in SPI_MSTransfer_T4 posted below:

    Code:
    #if defined(__IMXRT1062__)
        IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SDI (MISO) */
        IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SDO (MOSI) */
        IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SCK (CLK) */
        IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 PCS0 (CS) */
    #endif
    if you are using teensy 3.x or LC, they run fine without the DSE pad settings being corrected

  19. #69
    Junior Member
    Join Date
    May 2022
    Posts
    12
    Tonton, thank you again.

    My Teensy SPI slave device will eventually connect with a master R-Pi. This R-Pi is in development, and the hardware is set in stone, hence why I am stuck with SPI.

    My current mock up master (using Teensy 4.1) doesn't use SPISlave_T4 at all, it uses the standard Arduino SPI library, this should be no problem, correct?

    The part I don't understand is why my slave loop seems to freeze when it receives a message from the master, yet apparently the slave can still respond to SPI messages even with this frozen loop. Can you help me to understand at all?

    If I understand you, I should be able to make SPISlave_T4 work if I apply the patch you mentioned in the above quote? Becaue SPI_MSTranser_T4 is intended as a data transfer utility that where I must use that library on both master and slave?

    Thanks!

  20. #70
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    yes but the master end *should* work on any other arduinos, you'd have to test as it uses the standard SPI library for master. The slave end is only working for the Teensy 3.x/LC/T4.x end. The patch is if you still want to use SPISlave_T4 with a master T4.x, if RPI is master you should be able to send fine via it's own SPI library with a TLC/T3.x/T4.x slave using SPISlave_T4

  21. #71
    Junior Member
    Join Date
    May 2022
    Posts
    12
    Ok, thanks again. I will try it again tonight and see where I get.

    Do you know of any examples of SPISlave_T4 being used to receive a byte, and then return a group of bytes based on what the first byte was?

    Is there a good way to not have the slave device hang until the SS pin of the master goes HIGH LOW HIGH?

    My code above doesn't seem to work well. I really appreciate you taking the time to help me out.

  22. #72
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,074
    its one byte/word at a time, not grouped. if you want the slave to send more data you need to basically send dummy bytes/words to push the data out of the slave, so you need to handle that as needed

  23. #73
    Junior Member
    Join Date
    May 2022
    Posts
    12
    I believe my code above is sending one byte at time, no?

  24. #74
    Junior Member
    Join Date
    Feb 2019
    Posts
    11
    Quote Originally Posted by mmdo View Post
    Ok, thanks again. I will try it again tonight and see where I get.

    Do you know of any examples of SPISlave_T4 being used to receive a byte, and then return a group of bytes based on what the first byte was?

    Is there a good way to not have the slave device hang until the SS pin of the master goes HIGH LOW HIGH?

    My code above doesn't seem to work well. I really appreciate you taking the time to help me out.
    if I were doing this I would do it as two transactions from the master. The first is to send a packet of the same size you intend to receive and at some position in there put your command word or byte. Based on this command word you can set up the return packet as desired

    There would be two separate assertions of the chip select line.

    The second transactions sends meaningless bytes and definitely do NOT have any valid command words in there and then of course receive the pertinent data from that transaction.

    The simplicity is having both packets or frames be the same size to make the slave code easier.

    I recommend you have an oscilloscope connected and also reference the datasheet. This is pretty advanced stuff and I expect you will need to modify things to get it working.

  25. #75
    Hello!

    Great Library, what would it take to support two simutanious SPI slaves on SPI0 and SPI1?

Posting Permissions

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