arduino / ArduinoCore-mbed

346 stars 199 forks source link

Minimal example of SPI for Portenta H7 #131

Closed MatInGit closed 3 years ago

MatInGit commented 3 years ago

Hi, I am looking for a minimal example of SPI usage on the Arduino Portenta H7. In particular reading multiple bytes from a slave device. The traditional Arduino SPI header does not appear to work and I assume it is related to issue #117, however, I am not entirely certain.

MatInGit commented 3 years ago

This code has worked for me:

// Minimal SPI example

#include "mbed.h"
#include "Arduino.h"

using namespace mbed;

SPI spi(PC_3, PC_2, PI_1);            // MOSI,MISO,SCK,CS* (* - optional).

void setup() {
  Serial.begin(2000000);              // Initialization of serial communication.
  spi.frequency(1000000);             // Set up your frequency.
  spi.format(16, 3);                  // Messege length (bits), SPI_MODE - check these in your SPI decice's data sheet.

}

void loop() {

    Serial.println(get_data());       // Retrive the data from SPI device
    delay(100);
}

int get_data(){

  digitalWrite(PI_0, LOW);            // Drive the CS LOW.
  delayMicroseconds(1);               // Wait 1 us to settle.
  int data = spi.write(0);            // Send 0x00 and record reply. 
  digitalWrite(PI_0, HIGH);           // Drive the CS HIGH.
  return data;
}

There is a number of different libraries referring to the SPI interface, I am still not sure if the above is the correct usage. I have also noticed that is you use .select() and .deselct() methods of the SPI object, they do not drive the CS pin LOW (when the optional parameter in the constructor has been defined). Not sure if this is a bug or my incorrect usage on my part?

manchoz commented 3 years ago

@MatInGit the classic SPI library is fully supported by the Portenta H7 and the Mbed-based boards; there is no need to use the low-level MbedOS API.

The classic SPI API on Mbed-based boards has been extensively tested with common sensors and devices, such as BME280, SD Cards, SPI Flash Memories, and so on.

Please, try the following sketch:


#include <SPI.h>

// The sending timer and interval
uint32_t sendNow { 0 };
constexpr uint32_t sendInterval { 2500 };

// An incremental counter for testing SPI communications
uint8_t counter;

void setup()
{
    // PIN_SPI_SS is the Chip Select pin defined in the core for the Portenta H7
    // and is defined to be the pin 7, but you can use any free pin.
    pinMode(PIN_SPI_SS, OUTPUT);
    digitalWrite(PIN_SPI_SS, HIGH);

    // Wait for Serial connection
    Serial.begin(115200);
    while (!Serial)
        ;

    SPI.begin();

    counter = 0;
}

void loop()
{
    // put your main code here, to run repeatedly:
    if (millis() > sendNow) {
        // Send a byte
        Serial.print("Sending byte: 0x");
        if (counter < 16) Serial.print(0);
        Serial.println(counter, HEX);

        // Select the remote SPI device
        digitalWrite(PIN_SPI_SS, LOW); 
        // Start the SPI transaction
        SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
        // Start transferring (or requesting for) the data
        // Response will be in ret
        auto ret = SPI.transfer(counter++);
        // End the transaction
        SPI.endTransaction();
        // Deselect the remote SPI device
        digitalWrite(PIN_SPI_SS, HIGH);

        Serial.print("Received: 0x");
        Serial.println(ret, HEX);

        // Wait for the next cycle
        sendNow = millis() + sendInterval;
    }
}
MatInGit commented 3 years ago

@manchoz The code works great, I would include it in the core as an example.

Workshopshed commented 3 years ago

Thanks @manchoz so just to clarify. The global variable SPI defined in SPI.h is connected to SPI1 on the edge of the board, aka Digital pins, D8, D9, 10 (and as above D7) ?

manchoz commented 3 years ago

Thanks @manchoz so just to clarify. The global variable SPI defined in SPI.h is connected to SPI1 on the edge of the board, aka Digital pins, D8, D9, 10 (and as above D7)?

Yes, it is.

Workshopshed commented 3 years ago

SPI working fine with Waveshare EPD_2in13_V2 display using SPI global and pins as above