0

I recently designed a PCB that features several SPI devices. One of the devices is the Microchip MCP23S17 GPIO expander (http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf). I have the chip select line connected to GPIO 24 (pin 18) on the Raspberry Pi 3.

Now I was previously planning on doing the SPI communications in C, however, I thought I'd get Python a try since everyone is always raving about it.

I went ahead and downloaded the Python spidev library (http://tightdev.net/SpiDev_Doc.pdf). One thing I noticed is that it forces you to choose one of the two chip select lines listed on the Raspberry Pi. I didn't plan on using these preselected IO points because I have more than two spi devices.

Instead, I'm manually toggling GPIO 24 before I issue a SPI data transfer. I've also went ahead and configured the Python SPI device to "chip select 0" which isn't connected to anything in my circuit. Thus I let "think" it has control over a chip select line when it actually doesn't.

However, now I can't get any of the SPI communications to work.

I've troubleshooted the following: - Verified the GPIO expander IC has power - Verified good solder connection to the pad - Verified chip select is actually being toggled

However, I haven't put a scope up to it yet since I don't currently have access to one.

For anyone who has worked with the Python SPI library, do you see any issues with what I'm trying to do?

Code:

#! /usr/bin/python

import spidev
import time
import RPi.GPIO as GPIO

#######################
#### FUNCTION DEFS ####
#######################

def configMCP23S17():

    # config port direction
    to_send = [0x40, 0x00, 0xFF]
    GPIO.output(24, GPIO.LOW)
    resp = spi.xfer2(to_send)
    GPIO.output(24, GPIO.HIGH)

    #config polarity
    to_send = [0x40, 0x02, 0x00]
    GPIO.output(24, GPIO.LOW)
    resp = spi.xfer2(to_send)
    GPIO.output(24, GPIO.HIGH)

    #config pull up resistors
    to_send = [0x40, 0x0C, 0xFF]
    GPIO.output(24, GPIO.LOW)
    resp = spi.xfer2(to_send)
    GPIO.output(24, GPIO.HIGH)

# end def

def readMCP23S17():

    #read port A
    GPIO.output(24, GPIO.LOW)
    to_send = [0x40, 0x12, 0x00]
    resp = spi.xfer2(to_send)
    GPIO.output(24, GPIO.HIGH);

    return resp

#end def

#######################
#### PROGRAM START ####
#######################

GPIO.setmode(GPIO.BCM)
GPIO.setup(05, GPIO.OUT)
GPIO.setup(06, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)

GPIO.output(05, GPIO.HIGH)
GPIO.output(06, GPIO.HIGH)
GPIO.output(12, GPIO.HIGH)
GPIO.output(24, GPIO.HIGH)


spi = spidev.SpiDev() 
spi.open(0, 0)

configMCP23S17()

try:
    while True:
        output = readMCP23S17()
        print(output)

        time.sleep(1.0)     

except KeyboardInterrupt:
    spi.close()
1

I haven't used SPI in Python but have used in c - often just to send serial data to shift registers etc which aren't specifically SPI.

There is nothing special about the CS pins, unless you are using the kernel drivers `/dev/spidev0.0' etc.

You can use any pin, particularly is timing is non-demanding, or even leave the chip permanently selected.

Whether you can do this using the library depends on the actual library implementation, which may control the default CS pins.

If you search you will find examples which actually use `/dev/spidev0.0' but add external gates to steer the lines to many different devices.

You can just use any pins as CS, but ignore the normal CS pins and manually select the devices. Obviously you can only use a single slave at one time.

One possible problem with your code is that you appear to be toggling the CS pin immediately after a write. This may actually happen before data transfer, but without more detail of your configuration it is difficult to say. I would just set CS until the whole transaction was complete.

1

If you read the SpiDev github, SpiDev has an option that you can set to ignore CS.

spi.no_cs = True  # Set the "SPI_NO_CS" flag to disable use of the chip select

You may still want to set the CS GPIO to output mode.

0

Your code appears correct as far as it goes and toggling the chip selects manually should be fine.

The problem may be down to a change in operation of the underlying Linux SPI driver.

I believe it now defaults to a SPI speed of 125Mbps which is far too high for the Pi and possibly too high for the MCP23S17.

Try explicitly setting a speed in your code.

I think the spidev property you need is max_speed_hz.

E.g. try

spi = spidev.SpiDev() 
spi.open(0, 0)
spi.max_speed_hz=1000000 # set 1Mbps

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.