[RPI] Использование SPI из Python на Raspberry Pi

Hardware issues, electronic components, schemas, Arduino, STM32, Robots, Sensors

[RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 26-Feb-2014, 17:54


Для включение аппаратного интерфейса SPI нужно в файле /etc/modprobe.d/raspi-blacklist.conf закомментировать строку "blacklist spi-bcm2708" и перезагрузить Pi. Для того, что бы убедиться, что SPI включен можно запустить листинг директории /dev:

RaspberryPI_SPI_devices.jpg (89.74 KiB) Viewed 18579 times

Расположение сигналов SPI на разъеме GPIO:

Raspberry-PI-rev2-gpio-pins.png (65.92 KiB) Viewed 15299 times

Для проверки корректности работы SPI нужно замкнуть между собой MOSI и MISO и выполнить следующие команды:

Code: Select all
$ wget https://raw2.github.com/torvalds/linux/master/Documentation/spi/spidev_test.c

$ gcc spidev_test.c

$ sudo ./a.out -D /dev/spidev0.0

Правильный результат выполнения должен быть таким:

RaspberryPI_SPI_test_bits.jpg (17.96 KiB) Viewed 18579 times

Python модуль для работы с SPI можно взять здесь. Установка модуля выполняется следующим образом:

Code: Select all
$ git clone https://github.com/doceme/py-spidev

$ cd py-spidev/

$ sudo python setup.py install

Основные функции модуля py-spidev.

•SpiDev([bus],[client]). Return a new SPI object that is (optionally) connected to the specified SPI device interface.
•open(bus, device). Connects the object to the specified SPI device. open(X,Y) will open /dev/spidev-X.Y
•xfer2([values]). Perform SPI transaction. CS will be held active between blocks.
•close(). Disconnects the object from the interface.

Пример работы с SPI из Python:

Code: Select all
nrf = spidev.SpiDev(0, 0)
nrf.xfer2([0x1, 0x8])
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 14-Mar-2014, 19:35


SpiDev Documentation

This module defines an object type that allows SPI transactions on hosts running the Linux kernel. The host kernel must have SPI support and SPI device interface support. All of these can be either built-in to the kernel, or loaded from modules.
Because the SPI device interface is opened R/W, users of this module usually must have root permissions.
This tutorial is written for the use with a Raspberry Pi (Raspbian Wheezy distribution), but it should match for several others, too.

SPI installation
First things first, it’s always the best to keep your Raspberry Pi up to date, otherwise some things here may not work. Open a new console and execute the following commands:
sudo apt-get update
sudo apt-get upgrade
sudo reboot

If you don’t have done this yet, grab some coffee or something else because this may take up to an hour or two.
If you don’t have installed it already you need to install the Python Dev package:
sudo apt-get install python-dev

On Fedora (Pidora) the equivalent of that last command is:
sudo yum install yum-utils
sudo yum-builddep python

You need to be sure that SPI is enabled in your system (disabled by default because rarely used).
Open a new terminal and enter:
sudo nano /etc/modprobe.d/raspi-blacklist.conf

This will open a text editor. You should see a line like this in this file:

Put a # before this line to comment it out. Save (Ctrl+O) and exit (Ctrl+X). After a reboot the device should be found.
sudo reboot # --- after reboot --- lsmod

In the list lsmod outputs you should find the entry “spi_bcm2708” now.
Also you need the SpiDev Python module. Open a new terminal and execute the following commands:

Now the SPI device should be available to Python.

How to run python scripts
Of course there are several ways. You can either simple save your script and run it using:
sudo python myscript.py

Or you can mark the file as executable. For this you need to add one line at the top of your script:

Now mark it as executable:
sudo chmod +x myscript.py

Now you can execute it like any other application:
sudo ./myscript.py

Simple output
This example will open SPI and writes a byte (0xAA) to it each 0.1 second until you cancel it with Ctrl+C.
Code: Select all

import spidev
import time

= spidev.SpiDev() # create spi object
  spi.open(0, 1)           # open spi port 0, device (CS) 1

   while True:
       resp = spi.xfer2([0xAA]) # transfer one byte
       time.sleep(0.1)              # sleep for 0.1 seconds
   #end while
except KeyboardInterrupt:     # Ctrl+C pressed, so… 
      spi.close() # … close the port before exit
#end try

Helpful scripts
Reverse bits
This script will reverse the bit ordering in one byte (if you are not able to change LSB / MSB first to your needs.
Code: Select all

def ReverseBits
    byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4)
    byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2)
    byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1)
    return byte
#end def

Print bytes
This script will print out a byte array in a human readable format (hexadecimal). This is often useful during debugging.
Code: Select all

def BytesToHex
    return ''.join(["0x%02X " % x for x in Bytes]).strip()
#end def


  • bits_per_word
    Description: Property that gets / sets the bits per word.
    Range: 8 .. 16
  • close
    Syntax: close()
    Returns: None
    Description: Disconnects the object from the interface.
  • cshigh
    Description: Property that gets / sets if the CS is active high.
  • loop
    Description: Property that gets / sets “loopback configuration”. This is used to test the pcb for example. Anything that gets received will be echoed back.
  • lsbfirst
    Description: Property that gets / sets if LSB should be transferred first or last.
    Remarks: Needs Boolean value. However, this property seems to be read only and the value dependences on the endianess of the controller / cpu. The Raspberry Pi can only send MSB first, so you may need to convert the byte(s) manually (see code examples for such a script).
  • max_speed_hz
    Description: Property that gets / sets the maximum bus speed in Hz.
  • mode
    Description: Property that gets / sets the SPI mode as two bit pattern of Clock Polarity and Phase [CPOL|CPHA]
    Range: 0b00 = 0 .. 0b11 = 3
  • open
    Syntax: open(bus, device)
    Description: Connects the object to the specified SPI device.
    open(X,Y) will open /dev/spidev-X.Y
  • readbytes
    Syntax: read(len)
    Returns: [values]
    Description: Read len bytes from SPI device.
  • threewire
    Description: Property that gets / sets “SI/SO signals shared” so you have only 1 data line. Read the data sheets for more details.
  • writebytes
    Syntax: write([values])
    Returns: None
    Description: Write bytes to SPI device.
  • xfer
    Syntax: xfer([values])
    Returns: [values]
    Description: Perform SPI transaction.
    CS will be released and reactivated between blocks. delay specifies delay in μsec between blocks.
  • xfer2
    Syntax: xfer2([values])
    Returns: [values]
    Description: Perform SPI transaction. CS will be held active between blocks.
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 15-Mar-2014, 12:04

http://en.wikipedia.org/wiki/Serial_Per ... erface_Bus
SPI_single_slave_svg.png (4.69 KiB) Viewed 18539 times

As the names suggest, the M_CLK line carries clock pulses which provide synchronisation. When a transfer is taking place, a bit of data is transferred via MOSI from Master to slave and at the same time a bit of data is transferred via MISO from Slave to Master. At the end of eight clock pulses an entire byte of data has been transferred in each direction.

http://www.openlabtools.org/reports/201 ... Report.pdf

http://www.100randomtasks.com/simple-sp ... spberry-pi

This article aims to show a simple method of setting up the SPI interface on the Raspberry Pi Computer with Python. The SPI interface is one of the busses made available on the 26 pin GPIO header of the Raspberry Pi.

An image of the GPIO header is shown to the right with the necessary connections marked in purple. They include the MOSI, MISO, CLK, CE0, and CE1 pins. In addition the +3.3v, and Ground pins will also be needed to power the slave device.
Raspberry-GPIOs.png (39.99 KiB) Viewed 18542 times

The above program will work nicely with the schematic below:
ADC to RPi Schematic.jpg
ADC to RPi Schematic.jpg (64.14 KiB) Viewed 18542 times

The key parts of the SPI interface are as follows:
spi.open(0,0) will open bus 0, CE0.
spi.open(0,1) will open bus 0, CE1.
spi.xfer2([array of bytes]) will send an array of bytes keeping the CE asserted the whole time.
spi.xfer([array of bytes]) will send an array of bytes de-asserting and re-asserting the CE with every byte.

The above circuit is pin compatible with the Microchip MCP3001 10 bit A/D converter. However, it will be necessary to alter the python script to send 2 bytes and format the 2 byte response for a 10 bit value as per the datasheet.
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 15-Mar-2014, 12:08

https://projects.drogon.net/understandi ... pberry-pi/

The Raspberry Pi only implements master mode at this time and has 2 chip-select pins, so can control 2 SPI devices. (Although some devices have their own sub-addressing scheme so you can put more of them on the same bus)

One thing to remember about SPI is that to receive a byte, you need to send a byte. This may sound a little odd, but consider a device which accepts a command byte, then a data byte, then sends back a result byte… To make this happen, we need to send three bytes to the device, which will send back 2 dummy bytes, followed by the 3rd byte with data in it. For example, a GPIO expander chip (e.g. the MCP23S17 as used in the PiFace) where you send it a command (read register), then the data (the register number), then it sends back a return value (the register contents). So, when you send the command, it will send back a byte which you ignore, you send it the data, it sends back a byte which you also ignore, but to make it send the result, you need to send it a third byte which it will ignore!

Additionally we may need to change the permissions and/or ownerships of the files in /dev/ so that we can access them from out programs without needing to be root or run them with sudo.

http://www.raspberrypi.org/forum/viewto ... 44&t=56669
I have checked that all is where it should be and everything is there. I then put together a piece of test code to check the connection by handshaking the MISO and MOSI pins on the Rpi.

I have looked at the permissions on the spidev0.0 and it is for the 'root' crw. As as user would I need to give myself permission on this to get it working when running the code such as:
sudo chmod 666 /dev/spidev0.0

Make sure you have: #!/usr/bin/python in the first line of your scripts.


Processor MCK (Hz) SPI Min
AT91SAM9261 99,993,600 392,132
AT91SAM9G20 132,096,000 518,024
AT91SAM9G10 120,000,000 471,000
AT91SAM9G45 132,096,000 518,024

.bus_num This chooses if SPI0 or SPI1 of the AT91SAM9xx is used.
.mode There are four different SPI modes, mode three is most commonly used by peripherals which can be only slaves. The mode of master and slave have to be the same, so when in doubt consult the datasheet of your device. There are two relevant parameters, the clock phase (CPHA) and clock polarity (CPOL). Is the phase zero (CPHA = 0), then data is sampled at rising edge with CPOL=0 and falling edge with CPOL=1. This behaviour switches with CPHA=1, then data is sampled at falling edge with CPOL=0 and rising edge with CPOL=1.

0 0 0
1 0 1
2 1 0
3 1 1


Оригинальный модуль-интерфейс к SPI (альтернативный)
http://elk.informatik.fh-augsburg.de/da ... ng/py-spi/

Пример для него.
Code: Select all
# this script was used with an AVR8 testboard which sent back
# the written value plus one, just to test the SPI interface
# so a write () of [0,0,1,2,3,0,0] would result in a read ()
# of [X,1,1,2,3,4,1]

import spi
from time import sleep

= spi.SPI(0,1)

print "PY: initialising SPI mode, speed, delay"
a.mode = 3
.msh = 2000000    # 2 MHz are okay for my setup
        # 4 MHz are definitly to much
delay = 5000

= 0
while(< 16):
    print "tx:", i
    print "rx:", a.read(1)


= 0
while(< 16):
    liste = [i,i,i,i,i,i,i]
    print "tx:", liste
"rx:", a.msg(liste, delay)
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 22-Mar-2014, 19:45

http://www.raspberrypi.org/forum/viewto ... 33&t=59931
by halhertani » Mon Nov 04, 2013 5:03 pm

With I2C, each slave device has an address and the master chip (microcontroller or RPi) must first send the address of the device of interest to initiate communication with it. In SPI there's no such slave device address. Instead, every SPI slave device has an active low chip(slave) select pin that must be asserted (pulled low) before the master initiates communication with the slave. The chip select pin must then be de-asserted when communication is complete. If there are multiple slave devices on the bus, the master device should only pull one of them low at a time to initiate communication with that particular device...this is how slave devices are accessed(addressed) in SPI without any fancy addressing scheme.

On the Raspberry PI (with Raspbian) if you enable SPI, and run a "ls /dev/spi*" command you'll see two files; i) "/dev/spidev0.0" & ii) "/dev/spidev0.1". This first number after spidev "0.*" indicates the spi device number and the second number is the chip select number. This basically means that there's only one spi device on the RPi and it can connect to a maximum of two slave devices because there are only two chip selects "0.0" & "0.1".

When using userspace spidev under Linux you do not need to assert chip select pins individually. For example to interface an MCP3008 SPI ADC, simply connect:
MCP3008 -------- RPi
SI -------- MOSI
SO -------- MISO
SCK -------- SCLK
CS -------- CE0

The CE0 pin on the RPi is mapped to the "/dev/spidev0.0" entry in the "/dev" directory. So to access that particular device simply open() "/dev/spidev0.0" , initialize it and start reading and writing.

Similarly let's say you want to connect an MCP23S17 SPI GPIO expander but this time to the "/dev/spidev0.1" entry in the "/dev" directory. Connect:
MCP23S17 ---------- RPI
SI ---------- MOSI
SO ---------- MISO
SCK ---------- SCLK
CS ---------- CE1

The fact that CE1 on the RPI is connected to the chip select pin of the MCP23S17 means that in order to communicate with the chip you must open & initialize the "/dev/spidev0.1" entry in the /dev directory.

Also when setting up & reading/writing the SPI peripheral using spidev under Linux, you should not configure the SPI peripheral by writing bits to the SPI configuration registers like you would on a microcontroller/Arduino. You simply need to use the spidev api which involves using some special structures, ioctl()s and open()s (& sometimes read()s and writes()s). Under Linux "everything is accessed as a file". This is also true when accessing the I2C peripheral (via i2cdev) and GPIO via (sysfs) under Linux.
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 22-Mar-2014, 20:05

http://www.brianhensley.net/2012/07/get ... ry-pi.html

Getting SPI working on the Raspberry Pi

So one of the phases in my project is connecting the Raspberry Pi to a micro-controller that has many Pulse Width Modulation (PWM) signals. Since the Raspberry doesn't have the number of PWM signals I need to control i'm going to do so through SPI. This post is the 'how to' on getting your SPI signals outputting from your Raspberry Pi.

Serial Peripheral interface (SPI) is made up of 4 wires normally. It is a standard that was designed by Motorola for use with their micro controllers. If you're interested in learning more about SPI i've added the Wikipedia link. Here is what a standard SPI setup looks like, multiple slaves is optional.
SS - Slave Select (Beagleboard community calles this Chip Select (CS))
MOSI - Master Out Slave In
MISO - Master In Slave Out
CLK - Clock

SPI_layout.png (11.83 KiB) Viewed 18541 times

Install <skipped>

The last part of this is to test the SPI signal. I'm going to download spidev_test.c
wget http://git.kernel.org/?p=linux/kernel/g ... dev_test.c -O spidev_test.c
Next we want to short the MISO and MOSI pins. Located as GPIO 9 & GPIO 10 as seen below.

We want to edit the spidev_test.c file so it it uses the correct spidevice in our /dev/ folder.
Open in editor "nano spidev_test.c", scroll down and change the device to "spidev0.0" and then save it by pressing the Ctrl+O to save and Ctrl+X to exit. lets compile this thing and run it now.
gcc spidev_test.c
sudo ./a.out

If you see this it's working.
spi_working.PNG (8.65 KiB) Viewed 18541 times

If you see zeros - this it's not working.
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Re: [RPI] Использование SPI из Python на Raspberry Pi

Postby Administrator » 11-Apr-2015, 18:57

Raspberry Pi 2 Model B/B+, 40 pin header layout
Raspberry-Pi2-GPIO-Model-B.png (41.81 KiB) Viewed 15299 times
Site Admin
Posts: 43
Joined: 26-Feb-2014, 17:54

Return to Hardware, DIY (Do-It-Yourself)