Teensy 4.1 SPI stops

Status
Not open for further replies.

Roter Baron

New member
Hi,

i'm currently working on a project where the Teensy 4.1 sends data over SPI. When I reset the slave device, the master MOSI signal becomes stuck at 0 for the entirety of each transfer (and therefore the slave only receives zeros). The slave doesn't sent anything back, SS and SCK seem to work.

Code:
#define LOOP_TIME_MS 10
#define SS_PIN 10

uint8_t tArr[] = {4,2,3,4};

#include "SPI.h"

void setup() {
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH);
  
  SPI.begin();
}

void loop() {
  uint32_t timestamp = millis();
  SPI.beginTransaction(SPISettings(100000U, MSBFIRST, SPI_MODE0));
  digitalWrite(SS_PIN, LOW);
  SPI.transfer(tArr, 4);
  digitalWrite(SS_PIN, HIGH);
  SPI.endTransaction();
  while(millis() - timestamp < LOOP_TIME_MS);
}
 
I would like to try this, but I don't understand "When I reset the slave device".

Can you be more specific about exactly which SPI device you have connected, and exactly what you're doing to "reset" it? I don't see anything in this code which looks like it would reset another chip, so I'm rather confused about how to perform this test.
 
Found the issue.
Code:
SPI.transfer(pointer, bytecount)
doesn't work. The same setup with
Code:
for(int i =0; i < sizeof(data); i++) 
{
SPI.transfer(((uint8_t*)&data)[i]); 
}
works.

It's also never mentioned that
Code:
SPI.transfer(pointer, bytecount)
is supported, but I guess it would have helped (for me at least) to mention it won't work like this in the producct page.
 
My guess is you're not dealing with the fact that SPI.transfer(buffer, length) overwrites the buffer with whatever is received on the MISO pin. Of course that's just guesswork since you only showed tiny code fragments, so nobody can know what the surrounding code does.


But regarding those code fragments, there is a clear error. You replaced SPI.transfer(buffer, length) with this:

Code:
for(int i =0; i < sizeof(data); i++) {
  SPI.transfer(((uint8_t*)&data)[i]); 
}

But the actual functionality SPI.transfer(buffer, length) implements is this:

Code:
for(int i =0; i < sizeof(data); i++) {
  ((uint8_t*)&data)[i] = SPI.transfer(((uint8_t*)&data)[i]); 
}

You can't say SPI.transfer(buffer, length) is incorrect when you tested a replacement that isn't the same thing!



I ran your code from msg #1 without anything connected, just my oscilloscope. Here's the result.

file1.png

At first glance, this looks like the SPI port is failing to transmit your 4 data bytes. But it does indeed transmit them correctly, the first time loop() runs. Then they are overwritten with whatever MISO receives, which happens to be zeros when I tested here. That's why the blue trace doesn't show your 4 data bytes.

But it I edit the code to always initialize the array with the data, indeed the data transmits every time.

Code:
#define LOOP_TIME_MS 10
#define SS_PIN 10

uint8_t tArr[] = {4,2,3,4};

#include "SPI.h"

void setup() {
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH);
  
  SPI.begin();
}

void loop() {
  uint32_t timestamp = millis();
  tArr[0] = 4;
  tArr[1] = 2;
  tArr[2] = 3;
  tArr[3] = 4;
  SPI.beginTransaction(SPISettings(100000U, MSBFIRST, SPI_MODE0));
  digitalWrite(SS_PIN, LOW);
  SPI.transfer(tArr, 4);
  digitalWrite(SS_PIN, HIGH);
  SPI.endTransaction();
  while(millis() - timestamp < LOOP_TIME_MS);
}

file2.png
 
Note: there is also a transfer of a buffer that allows you to not overwrite... SPI.transfer(buffer, return_buffer, count);
Where buffer and/or retbuffer can be NULL. Like when you are not interested in what comes back on the MISO line
SPI.transfer(tArr, nullptr, 4);

Should transfer your array, and toss the results
 
Status
Not open for further replies.
Back
Top