Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPI.beginTransaction() doesn't set the new mode. #828

Open
zapta opened this issue Jan 14, 2024 · 1 comment
Open

SPI.beginTransaction() doesn't set the new mode. #828

zapta opened this issue Jan 14, 2024 · 1 comment

Comments

@zapta
Copy link

zapta commented Jan 14, 2024

TL:DR, SPI clock level is not adjusted to SPI mode before CS is asserted low.

Consider the example program below on Raspberry Pi Pico. It performs alternative SPI transactions using two SPI settings and two respective CS outputs. The first setting uses SPI MODE0 and the second SPI MODE2. The expectation is that the clk idle level should be adjusted to the mode by SPI.beginTransaction() but it is adjusted only when the actual transfer starts, after the CS was asserted low.

The oscilloscope screenshot below shows a transaction using MODE0 and CS1. Notice how the idle level when CS is asserted low is incorrect for MODE0.

Expected behavior: SPI.beginTransaction() should adjust immediately the clk idle level to the mode passed to it. Or, provide an alternative method to adjust the mode and clock idle level before asserting the CS low.

#include <SPI.h>

#define CS1 20
#define CS2 21

SPISettings settings1(1000000, MSBFIRST, SPI_MODE0);
SPISettings settings2(1000000, MSBFIRST, SPI_MODE2);

void setup() {
  Serial.begin(115200);

  pinMode(CS1, OUTPUT);
  pinMode(CS2, OUTPUT);

  digitalWrite(CS1, HIGH);
  digitalWrite(CS2, HIGH);

  SPI.begin();
}

void loop() {
  // MODE1 transaction on CS1.
  SPI.beginTransaction(settings1);
  digitalWrite(CS1, LOW);   // CS1 on
  SPI.transfer(0x11);
  SPI.endTransaction();
  digitalWrite(CS1, HIGH);  // CS1 off

  // MODE2 transaction on CS2.
  SPI.beginTransaction(settings2);
  digitalWrite(CS2, LOW);   // CS2 on
  SPI.transfer(0x22);
  SPI.endTransaction();
  digitalWrite(CS2, HIGH);  // CS2 off

  Serial.println("loop");
  delay(1000);
}

SCR01

@zapta
Copy link
Author

zapta commented Jan 17, 2024

One workaround that works, is to issue a begin/transfer/end transaction with zero bytes, each time the SPI mode (or just CPOL?) change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant