3

I'm using a Pi 3B to interface with an SPI device. My program is written in Python 2, the Pi is the SPI master and the external device is the slave. I am using both the spidev module and the RPi.GPIO modules, with good success. I can communicate with my SPI slave using either spidev or a bit-banged SPI driver I wrote using RPi.GPIO. Both work fine on their own.

My troubles arise when I communicate using my bit-banged RPI.GPIO-based driver, and then try to use spidev: I can see on my oscilloscope that spidev can't drive the MOSI or SCLK lines after I've used my bit-banged RPi.GPIO driver.

The cause of this is clear to me, using the gpio readall command I can see that RPi.GPIO.cleanup() leaves the MOSI and SCLK pins as INPUTS. Prior to running any of my code (i.e. right after booting the Pi) I can see that MOSI and CLK are set to ALT0 -- just what I'd expect.

My question is, how can I get RPi.GPIO to, on exit, reconfigure the GPIO pins as they were before I used RPi.GPIO? Or, if that's not possible, is there a way to assign a GPIO pin to an alternate function (like ALT0 in this case) either from Python or the command line?

I'm pretty sure it's possible from C, but I'd like to avoid that route if possible.

Now for the obligatory code snippets:

This works (using spidev):

import spidev
spi = spidev.SpiDev()
spi.open(0, 0)
spi.xfer([0xaa])   # results appear on the scope as expected
spi.close()

This also works (using a bit-banged driver):

import RPi.GPIO as gpio
gpio.setmode(gpio.BCM)
gpio.setup(10, gpio.OUT)
gpio.setup(11, gpio.OUT)
gpio.setup(8, gpio.OUT)
# bit-bang pins 10, 11 and 8 here ...
# scope signals look good, just as expected
gpio.cleanup()  # this leaves MOSI & CLK as INputs
                # *not* calling gpio.cleanup() leaves MOSI and CLK
                # as OUTputs, which doesn't work either

But after the above RPi.GPIO-based code executes, the spidev code doesn't work any longer.

I don't have anything hooked up to the GPIO pins other than the scope itself -- there are no loads or supplies other than what the Pi provides.

I sure would appreciate any ideas!

2

There are at least two ways from the command line.

I'm fairly sure wiringPi's gpio utility allows for the mode of a GPIO to be set. man gpio for details.

My pigpio pigs utility does.

sudo pigpiod # Start daemon if not already running.

pigs m 7 0 # CE1 mode ALT 0
pigs m 8 0 # CE0 mode ALT 0
pigs m 9 0 # MISO mode ALT 0
pigs m 10 0 # MOSI mode ALT 0
pigs m 11 0 # SCLK mode ALT 0

man pigs or pigs for details.

Another alternative is to use the pigpio Python module which sets the correct modes for SPI anyhow.

  • Thanks @joan for these tips. I'm already using your pigpiod to measure pulse widths in this same application, so this works out well. Am I correct that your examples above should use 0 zero rather than o for the mode parameter? – Rich Dec 11 '16 at 3:23
  • It appears that gpio can only be used to change the mode to in, out, PWM, or control the pull-ups. At least, this is what the documentation says. There is no man page installed for gpio on my Raspbian distro. – Rich Dec 11 '16 at 3:34
  • @Rich Yes, it should be 0-5 for ATL_0 - ALT5, r for INPUT, and w for OUTPUT. I shall correct the answer. – joan Dec 11 '16 at 9:13

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.