Question
SPI 800kHz CLK amplitude is 3.29V, and decreases as SPI frequency increases,
SPI 9.6 MHz amplitude is only 1.6V, ...
Answer
For my Rpi3B+ stretch9, SPI 100kHz, 1MHz, and 5MHz, signal amplitude
does not change noticeably, ...
References
Rpi SPI Pinout
SPI1 (Auxiliary SPI) Config and Kernel Module
Appendices
Appendix A - SPI Signal Waveforms at 5MHz

Appendix B - SPI Test Program
# Program - spi_test_v1312_2019jul0301 tlfong01 2019jul03hkt1027
# Config - Rpi3B+ raspberrypi 4.19.42-v7+, IDLE python 3.5.3
# Function - (1) SPI loopback 1/2/3 bytes, (2) SPI repeat send one byte
# Rpi Interfaces Configuration dtparam=
# SPI, I2C, 1-Wire enable, Serial Port diaable
# Test 1 - loopBackTest - SPI port send and receive 1/2/3 bytes.
# Function - Send 1/2/3 bytes to MOSI and read it back from MISO.
# Setup - Connet MOSI pin to MISO pin to form a loop.
# Test 2 - repeat send one byte - SPI port repeat send one byte (need a scope to display waveforms).
# Function - repeat send data byte 0x5b and use scope to display waveforme CLK. MOSI, MISO, CS0, CS1.
# Setup - nil
# dtoverlay to enable SPI Channal 1 and Channal 1
# /boot/config.txt dtoverlay setting
# dtparam=i2c_arm=on
# dtparam=spi=on
# dtoverlay=spi1-3cs
# /dev/spi listing
# ls -l /dev/spi*
# should show the following:
# 1. /dev/spidev0.0
# 2. /dev/spidev0.1
# 3. /dev/spidev1.0
# 4. /dev/spidev1.1
# 5. /dev/spidev1.2
from time import sleep
import spidev
# *** SPI Setup/Config ***
spiPort00 = spidev.SpiDev()
spiPort00.open(0, 0)
# spiPort00.max_speed_hz = 100000 # 0.1 MHz (100 kHz)
# spiPort00.max_speed_hz = 1000000 # 1 MHz
spiPort00.max_speed_hz = 5000000 # 5 MHz
spiPort01 = spidev.SpiDev()
spiPort01.open(0, 1)
spiPort01.max_speed_hz = 100000
# *** Not tested - tlfong01 2019jul03hkt1047 ***
'''
spiPort10 = spidev.SpiDev()
spiPort10.open(1, 0)
spiPort10.max_speed_hz = 100000
spiPort11 = spidev.SpiDev()
spiPort11.open(1, 1)
spiPort11.max_speed_hz = 100000
spiPort12 = spidev.SpiDev()
spiPort12.open(1, 2)
spiPort12.max_speed_hz = 100000
'''
# *** Spi port functions ***
def setSpiPortSpeed(spiPortNum, speedName):
spiPortList[spiPortNum].max_speed_hz = speedDict[speedName]
return
def closeSpiPortAll():
for i in spiPortList:
i.close()
return
def padDataByte(dataByte):
unPadString = (hex(dataByte)[2:])
if (len(unPadString) != 2):
unPadString = '0' + unPadString
padString = '0x' + unPadString
return padString
def printTitleDataByte(title, dataByte):
print(title, padDataByte(dataByte))
return
# *** SPI Write/Read/Loopback 1/2/3 Bytes ***
# *** SPI Send/Receive 1/2/3 Bytes ***
def spiSendRecvOneByte(spiPort, sendByte):
sendByteArray = [sendByte]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
sendByteArray = [sendByte1, sendByte2]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
sendByteArray = [sendByte1, sendByte2, sendByte3]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
# *** Loopback 1/2/3 Bytes ***
def loopbackOneByte(spiPort, sendByte):
recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
recvByte = recvByteArray[0]
print('\n Begin loopbackOneByte(),...')
printTitleDataByte(' sendByte = ', sendByte)
printTitleDataByte(' recvByte = ', recvByte)
#print('')
print(' End loopbackOneByte().', end = '')
return
def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
recvByteArray = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
recvByte1 = recvByteArray[0]
recvByte2 = recvByteArray[1]
print('\n Begin loopbackThreeBytes(),...')
#print('')
print(' sendBytes = ', padDataByte(sendByte1), padDataByte(sendByte2))
print(' recvBytes = ', padDataByte(recvByte1), padDataByte(recvByte2))
#print('')
print(' End loopbackTwoBytes().', end = '')
return
def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
recvByteArray = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
recvByte1 = recvByteArray[0]
recvByte2 = recvByteArray[1]
recvByte3 = recvByteArray[2]
print('\n Begin loopbackThreeBytes(),...')
print(' sendBytes = ', padDataByte(sendByte1), padDataByte(sendByte2), padDataByte(sendByte3))
print(' recvBytes = ', padDataByte(recvByte1), padDataByte(recvByte2), padDataByte(recvByte3))
#print('')
print(' End loopbackThreeBytes().', end = '')
return
# *** Test SPI Loopback 1/2/3 bytes ***
def testLoopbackOneByteSpiPort00():
print('\nBegin loopbackOneByteSpiPort00(),...', end = '')
loopbackOneByte(spiPort00, 0x5b)
print('\nEnd loopbackOneByteSpiPort00().', end = '')
return
def testLoopbackTwoBytesSpiPort00():
print('\nBegin loopbackTwoBytesSpiPort00(),...', end = '')
loopbackTwoBytes(spiPort00, 0x5b, 0x6b)
print('\nEnd loopbackTwoByte0SpiPort00().', end = '')
return
def testLoopbackThreeBytesSpiPort00():
print('\nBegin loopbackThreeBytesSpiPort00(),...', end = '')
loopbackThreeBytes(spiPort00, 0x5b, 0x5c, 0x5d)
print('\nEnd loopbackThreeByteSpisPort00().', end = '')
return
def testLoopbackThreeBytesSpiPort12():
print('\nBegin loopbackThreeBytesSpiPort12(),...', end = '')
loopbackThreeBytes(spiPort12, 0xb5, 0xc5, 0xd5)
print('\nEnd loopbackThreeByteSpisPo1200().', end = '')
return
def testSpiLoopbackAll00():
testLoopbackOneByteSpiPort00()
print('')
testLoopbackTwoBytesSpiPort00()
print('')
testLoopbackThreeBytesSpiPort00()
return
# *** Test SPI Repeat Send Byte 0x55 ***
def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatCount):
print('\n\nBegin repeatSendByte(),....')
for i in range(repeatCount):
spiSendRecvOneByte(spiPort, sendByte)
sleep(pauseSeconds)
print('End repeatSendByte().')
return
def testRepeatSendOneByteSpiPort00():
repeatSendOneByte(spiPort = spiPort00, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort01():
repeatSendOneByte(spiPort = spiPort01, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort10():
repeatSendOneByte(spiPort = spiPort10, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort11():
repeatSendOneByte(spiPort = spiPort11, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort12():
repeatSendOneByte(spiPort = spiPort12, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
# *** Test Results - tlfong01 2019jun12hkt2247 ***
#testSpiLoopbackAll00() # OK
#testLoopbackThreeBytesSpiPort12() # OK
#testRepeatSendOneByteSpiPort00() # OK
#testRepeatSendOneByteSpiPort01() # OK
#testRepeatSendOneByteSpiPort10() # not working !!!
#testRepeatSendOneByteSpiPort11() # not working !!!
#testRepeatSendOneByteSpiPort12() # OK
# *** Main Tests ***
testRepeatSendOneByteSpiPort00() # OK
#testSpiLoopbackAll00()
# *** End of Program ***
'''
Sample ouput tlfong01 2019jun12
RESTART: /home/pi/Python Programs/test1301/spi/spi_test_v1308_2019jun1201.py
Begin loopbackOneByteSpiPort00(),...
Begin loopbackOneByte(),...
sendByte = 0x5b
recvByte = 0x00
End loopbackOneByte().
End loopbackOneByteSpiPort00().
Begin loopbackTwoBytesSpiPort00(),...
Begin loopbackThreeBytes(),...
sendBytes = 0x5b 0x6b
recvBytes = 0x00 0x00
End loopbackTwoBytes().
End loopbackTwoByte0SpiPort00().
Begin loopbackThreeBytesSpiPort00(),...
Begin loopbackThreeBytes(),...
sendBytes = 0x5b 0x5c 0x5d
recvBytes = 0x00 0x00 0x00
End loopbackThreeBytes().
End loopbackThreeByteSpisPort00().
Begin repeatSendByte(),....
'''
# *** End of Sample Output ***
Appendix C - SPI 10MHz Repeat Send Byte 0x5b

Appendix D - SPI 10MHz Repeat Send Byte 0x5b Program
# Program - spi_test_v1315_2019jul0401 tlfong01 2019jul04kt1106
# Config - Rpi3B+ raspberrypi 4.19.42-v7+, IDLE python 3.5.3
# Function - (1) SPI loopback 1/2/3 bytes, (2) SPI repeat send one byte
# Rpi GUI Desktop Config > Preferences > Interfaces Configuration
# SPI, I2C, 1-Wire enable, Serial Port diaable
# Test 1 - loopBackTest - SPI port echo/loopback 1/2/3 bytes.
# Function - Send 1/2/3 bytes to MOSI and read it back from MISO.
# Setup - Connet MOSI pin to MISO pin to form echo loop.
# Test 2 - repeat send one byte - SPI port repeat send one byte (need a scope to display waveforms).
# Function - repeat send data byte 0x5b and use scope to display waveforme CLK. MOSI, MISO, CS0, CS1.
# Setup - nil
# dtoverlay to enable SPI Channal 0 and Channal 1
# sudo nano /boot/config.txt dtoverlay setting
# dtparam=i2c_arm=on
# dtparam=spi=on
# dtoverlay=spi1-3cs
# /dev/spi listing
# $ ls -l /dev/spi*
# should show the following:
# 1. /dev/spidev0.0
# 2. /dev/spidev0.1
# 3. /dev/spidev1.0
# 4. /dev/spidev1.1
# 5. /dev/spidev1.2
from time import sleep
import spidev
# *** SPI Setup/Config ***
spiPort00 = spidev.SpiDev()
spiPort00.open(0, 0)
# spiPort00.max_speed_hz = 100000 # 0.1 MHz (100 kHz)
# spiPort00.max_speed_hz = 1000000 # 1 MHz
spiPort00.max_speed_hz = 5000000 # 5 MHz
spiPort01 = spidev.SpiDev()
spiPort01.open(0, 1)
spiPort01.max_speed_hz = 100000
# *** Not tested - tlfong01 2019jul03hkt1047 ***
'''
spiPort10 = spidev.SpiDev()
spiPort10.open(1, 0)
spiPort10.max_speed_hz = 100000
spiPort11 = spidev.SpiDev()
spiPort11.open(1, 1)
spiPort11.max_speed_hz = 100000
spiPort12 = spidev.SpiDev()
spiPort12.open(1, 2)
spiPort12.max_speed_hz = 100000
'''
# *** Spi port functions ***
def setSpiPortSpeed(spiPortNum, speedName):
spiPortList[spiPortNum].max_speed_hz = speedDict[speedName]
return
def closeSpiPortAll():
for i in spiPortList:
i.close()
return
# ** Pretty Print Functions ***
def padDataByte(dataByte):
unPadString = (hex(dataByte)[2:])
if (len(unPadString) != 2):
unPadString = '0' + unPadString
padString = '0x' + unPadString
return padString
def printTitleDataByte(title, dataByte):
print(title, padDataByte(dataByte))
return
# *** SPI Write/Read/Loopback 1/2/3 Bytes ***
# *** SPI Send/Receive 1/2/3 Bytes ***
def spiSendRecvOneByte(spiPort, sendByte):
sendByteArray = [sendByte]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
sendByteArray = [sendByte1, sendByte2]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
sendByteArray = [sendByte1, sendByte2, sendByte3]
recvByteArray = spiPort.xfer(sendByteArray)
return recvByteArray
# *** Loopback 1/2/3 Bytes ***
def loopbackOneByte(spiPort, sendByte):
recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
recvByte = recvByteArray[0]
print('\n Begin loopbackOneByte(),...')
printTitleDataByte(' sendByte = ', sendByte)
printTitleDataByte(' recvByte = ', recvByte)
#print('')
print(' End loopbackOneByte().', end = '')
return
def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
recvByteArray = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
recvByte1 = recvByteArray[0]
recvByte2 = recvByteArray[1]
print('\n Begin loopbackThreeBytes(),...')
#print('')
print(' sendBytes = ', padDataByte(sendByte1), padDataByte(sendByte2))
print(' recvBytes = ', padDataByte(recvByte1), padDataByte(recvByte2))
#print('')
print(' End loopbackTwoBytes().', end = '')
return
def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
recvByteArray = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
recvByte1 = recvByteArray[0]
recvByte2 = recvByteArray[1]
recvByte3 = recvByteArray[2]
print('\n Begin loopbackThreeBytes(),...')
print(' sendBytes = ', padDataByte(sendByte1), padDataByte(sendByte2), padDataByte(sendByte3))
print(' recvBytes = ', padDataByte(recvByte1), padDataByte(recvByte2), padDataByte(recvByte3))
#print('')
print(' End loopbackThreeBytes().', end = '')
return
# *** Test SPI Loopback 1/2/3 bytes ***
def testLoopbackOneByteSpiPort00():
print('\nBegin loopbackOneByteSpiPort00(),...', end = '')
loopbackOneByte(spiPort00, 0x5b)
print('\nEnd loopbackOneByteSpiPort00().', end = '')
return
def testLoopbackTwoBytesSpiPort00():
print('\nBegin loopbackTwoBytesSpiPort00(),...', end = '')
loopbackTwoBytes(spiPort00, 0x5b, 0x6b)
print('\nEnd loopbackTwoByte0SpiPort00().', end = '')
return
def testLoopbackThreeBytesSpiPort00():
print('\nBegin loopbackThreeBytesSpiPort00(),...', end = '')
loopbackThreeBytes(spiPort00, 0x5b, 0x5c, 0x5d)
print('\nEnd loopbackThreeByteSpisPort00().', end = '')
return
def testLoopbackThreeBytesSpiPort12():
print('\nBegin loopbackThreeBytesSpiPort12(),...', end = '')
loopbackThreeBytes(spiPort12, 0xb5, 0xc5, 0xd5)
print('\nEnd loopbackThreeByteSpisPo1200().', end = '')
return
def testSpiLoopbackAll00():
testLoopbackOneByteSpiPort00()
print('')
testLoopbackTwoBytesSpiPort00()
print('')
testLoopbackThreeBytesSpiPort00()
return
# *** Test SPI Repeat Send Byte 0x5b ***
# *** Initialized SPI Frequency ***
def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatCount):
print('\n\nBegin repeatSendByte(),....')
for i in range(repeatCount):
spiSendRecvOneByte(spiPort, sendByte)
sleep(pauseSeconds)
print('End repeatSendByte().')
return
def testRepeatSendOneByteSpiPort00():
repeatSendOneByte(spiPort = spiPort00, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort01():
repeatSendOneByte(spiPort = spiPort01, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort10():
repeatSendOneByte(spiPort = spiPort10, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort11():
repeatSendOneByte(spiPort = spiPort11, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
def testRepeatSendOneByteSpiPort12():
repeatSendOneByte(spiPort = spiPort12, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000)
return
# *** 5MHz and 10MHz Tests ***
def testRepeatSendOneByteSpi10MhzPort00():
spiPort00.max_speed_hz =10000000
repeatSendOneByte(spiPort = spiPort00, sendByte = 0x5b, pauseSeconds = 0.001, repeatCount = 200000000)
return
# *** Test Results - tlfong01 2019jun12hkt2247 ***
#testSpiLoopbackAll00() # OK
#testLoopbackThreeBytesSpiPort12() # OK
#testRepeatSendOneByteSpiPort00() # OK
#testRepeatSendOneByteSpiPort01() # OK
#testRepeatSendOneByteSpiPort10() # not working !!!
#testRepeatSendOneByteSpiPort11() # not working !!!
#testRepeatSendOneByteSpiPort12() # OK
# *** Main Tests ***
#testSpiLoopbackAll00()
#testRepeatSendOneByteSpiPort00() # OK
testRepeatSendOneByteSpi10MhzPort00()
# *** End of SPI Test Program ***
# *** Sample Output 2019jun12 ***
'''
RESTART: /home/pi/Python Programs/test1301/spi/spi_test_v1308_2019jun1201.py
Begin loopbackOneByteSpiPort00(),...
Begin loopbackOneByte(),...
sendByte = 0x5b
recvByte = 0x00
End loopbackOneByte().
End loopbackOneByteSpiPort00().
Begin loopbackTwoBytesSpiPort00(),...
Begin loopbackThreeBytes(),...
sendBytes = 0x5b 0x6b
recvBytes = 0x00 0x00
End loopbackTwoBytes().
End loopbackTwoByte0SpiPort00().
Begin loopbackThreeBytesSpiPort00(),...
Begin loopbackThreeBytes(),...
sendBytes = 0x5b 0x5c 0x5d
recvBytes = 0x00 0x00 0x00
End loopbackThreeBytes().
End loopbackThreeByteSpisPort00().
Begin repeatSendByte(),....
'''
# *** End of Sample Output ***
Appendix C - SPI 1 Learning Notes
SPI1 (Auxiliary SPI) Config and Kernel Module
SPI1 (an auxiliary SPI device) is supported in raspbian kernels from
4.4 onwards.
SPI1 uses GPIO16-21 (by default) and is found on all 40 pin rPi’s to
date.
It has up to three CS lines allowing you to control 3 devices
natively. The kernel module allows for the CS lines to be repositioned
on any free GPIO pin via the appropriate options passed to the
dtoverlay.
The device reports supporting the following Linux SPIdev options:
SPI_CS_HIGH (CS inverted)
SPI_NO_CS (Device is signalled elsewhere) – this option is utilised
for the GPIO CS implementation the kernel driver now uses.
The implementation of SPI1 allows for a fair bit of flexibility. There
three overlays, a 1CS, 2CS and 3CS option. If you only need to control
one device use the 1CS option. You can expand to more CS lines later
enable spi1 with a single CS line dtoverlay=spi1-1cs
enable spi1 with two CS lines dtoverlay=spi1-2cs
enable spi1 with three CS lines dtoverlay=spi1-3cs
Additionally the CS lines are now software controlled so they can be
reconfigured to any available GPIO pin. See the /boot/overlays/README
for details.
Kernel Module
The module is called spi_bcm2835.
If SPI1 is enabled in the config.txt the kernel module should load
automatically after a reboot. Check with lsmod.
$ lsmod | grep spi spi_bcm2835 7216 0
If it doesn’t appear make sure this isn’t blacklisted
in/etc/modprobe.d/raspi-blacklist.conf. When the module is running you
will find device nodes have been created as per the dtoverlay in the
the config.txt.
crw-rw---- 1 root spi 153, 0 Jan 11 15:47 spidev1.0 crw-rw---- 1 root
spi 153, 1 Jan 11 15:47 spidev1.1
System Config
You should already have a user group called ‘spi’ which has read/write
access to the device nodes. Add yourself and any other accounts that
need access to this group if you have not already done so.
sudo usermod -a -G spi