XIAO SPI Speed slower than a UNO

I’m using SPI for a MCP4802 DAC which I tested first with a UNO and have now hooked up to a Seeeduino XIAO expecting a faster speed, given the clock is 4 times as fast but it’s actually a little bit slower! The DAC can handle up to 20MHz which is probably much more than either the XIAO or the UNO can manage. Just uploading 0 and 128 in a loop to get a square wave my scope is showing a miserable 12.7kHz, i.e. two channels of 8 bits uploaded at a rate of 25,400 per second.
With the UNO, I can roughly double this speed by writing directly to PORT B for CS but I’m not sure if this would work with the XIAO? Are there ways to scale the clock to make XIAO SPI work faster? Thanks for any help with this!

Which is your XIAO: SAMD21, nRF52840, ESP32C3, RP2040
If nRF52840, what board library are you using?
What is the frequency of the UNO SPI clock?

Thanks for coming back to me
It’s an early one, so I’m pretty sure it’s a SAMD21 - no extra bells and whistles.
I’m just using SPI.h - same code as used with the UNO except for CS pin
I’ve read that the SPI clock on a UNO with a 16MHz processor clock runs at 4MHz. Allowing for some overhead, maybe that speed from the UNO is the best it can do?
As an example of the faster speed I get from the XIAO, it can do about 70k analogReads a second, compared to less than 9k with the UNO
If a later XIAO would help, I’m happy to acquire - it would help if the pin allocations are the same.

The maximum SPI clock for XIAO_SAMD21 is 12 MHz.
I checked with a digital oscilloscope, and SPI transfers byte-data with 12MHz clock, but only once every 5.25uS. The real throughput is up to 190 kByte/sec.
There is also the problem in SPI.h. You have to change line 57 from 12000000 to 24000000 to get the maximum 12MHz. In your sketch, it might be better to explicitly set the SPI clock to 12MHz, as it might be set to 1/2 if you use the default.

Thanks again. I’m not that familiar with getting “under the hood” of the Arduino IDE - I’ve found the SPI.h and CPP on my computer but when I open them in notepad I’m not seeing line numbers and whilst SPI.h has a 4000000 in it, I’m not seeing 12000000 and when I tried to change 4000000 it didn’t allow me to save the change? In short, you sound like you know what you are doing, but sadly I don’t understand :frowning:

“SPI.h” and “SPI.cpp” are located at

C:\Users\xxxxxxxxxxxx\AppData\Local\Arduino15\packages\Seeeduino\hardware\samd\1.8.3\libraries\SPI

“SPI.h” should be editable by notepad.exe.
Find and change the following location around line 50.


#if defined(__SAMD51__)
  // SAMD51 has configurable MAX_SPI, else use peripheral clock default.
  // Update: changing MAX_SPI via compiler flags is DEPRECATED, because
  // this affects ALL SPI peripherals including some that should NOT be
  // changed (e.g. anything using SD card). Use the setClockSource()
  // function instead. This is left here for compatibility with interim code.
  #if !defined(MAX_SPI)
    #define MAX_SPI 24000000
  #endif
  #define SPI_MIN_CLOCK_DIVIDER 1
#else
  // The datasheet specifies a typical SPI SCK period (tSCK) of 42 ns,
  // see "Table 36-48. SPI Timing Characteristics and Requirements",
  // which translates into a maximum SPI clock of 23.8 MHz.
  // Conservatively, the divider is set for a 12 MHz maximum SPI clock.
  #if !defined(MAX_SPI)
// ******************************************************************************
//    #define MAX_SPI 12000000
    #define MAX_SPI 24000000	// <--------------------------- modify the value
// ******************************************************************************
  #endif
  #define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / MAX_SPI))
#endiftype or paste code here