Uncategorized
1

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

spi 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

spi 10mhz repeat send 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.