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
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
-
Hey. I tested your code. I got voltage somewhere around 1.632 – Oncetwice Jul 3 at 18:06
-
Well, of course there is something wrong with 1.632V. Usually I swap things to troubleshoot. For example, I might try SPI(1, 2) which uses different CLK, MOSI, and CS pins. Or I might try UART which also uses different pins. BTW, I assume your SPI wires are less than 1 metre, not 100 metres! 🙂 – tlfong01 Jul 4 at 0:58
-
Hey, Sorry for the delay, i couldn’t get my hands on a logic analyzer due to summer holidays. This is the update so far. I tried with SPI 1 port, same issue. i tried a Raspberry Pi 2 B model and i got the same issue. I changed the logic analyzer, same issue. I reinstalled logic analyzer software on my linux desktop, same issue. I tried the new buster OS, same issue. I am not able to debug this at all – Oncetwice Jul 22 at 20:30
-
@Oncetwice, Interesting. Just brainstorming: (1) Use a scope instead, (2) connect scope probe ground as near as possible to SPI signal ground. Let me know if it doesn’t help. – tlfong01 Jul 23 at 2:05
-
Hey i found the reason. It may sound stupid but it was actually the sampling rate of the logic analyzer that was messing everything up. Such a stupid mistake. Thanks for replying man. Have a nice day. 🙂 – Oncetwice Jul 23 at 16:57
Categories: Uncategorized