How to use multiple SPIs on Raspberry Pi (e.g. 3.5 inch Touchscreen, MCP 3008)

A display or a digital/analog converter (DAC) uses the SPI (serial peripheral interface) to communicate with the Raspberry Pi. The MCP 3008 is a DAC which reads analog values and converts them into digital ones. The Raspberry Pi itself can’t read analog values. When a SPI used by a device, the GPIO’s are often physically blocked (e.g. touschreen with a 26 pin header). This means a SPI can’t be connected to multiple devices simultaniously. A workaround is, to use SPIs which use a different set of GPIOs.

In this tutorial, we will use SPI0 and SPI1 on a Raspberry Pi 2 Model B and we are going to connect our DAC (MCP 3008) and our MHS 3.5inch touchscreen simultaniously. This is not a tutorial about how to setup the touchscreen or the MCP 3008. If that’s what you need, then please check out my other tutorials (links are at the bottom of this page).

The SPI is deactivated by default. To activate it you need to edit the config.txt

sudo nano /boot/config.txt

and add following line to the and of the file or if it already exists, uncomment it, if not already done

dtparam=spi=on

To check which SPIs are running, you simply do

ls /dev/spi*

Now let’s take a look at the pin layout of the Raspberry Pi.

Raspberry Pi 2 SPI| https://pinout.xyz/pinout/spi
http://www.lcdwiki.com/MHS-3.5inch_RPi_Display

The touchscreen uses SPI0. SPI1 with CE2 seem to be unused, so we will use it, to connect our DAC. SPI1 needs to be activated

To activated it you simply modify the /boot/config.txt and add the following line at the and of the file

dtoverlay=spi1-3cs

Unfortunately with this configuration our display will remain white. SPI1 with CS0 (spi1-1cs) is the only configuration which works. But SPI1 with CS0 is located at Pin 12 which is already physically blocked by the touchscreen. Luckily we can reconfigure Pin 36 (SPI with CS2) to be SPI with CS0.

For that we need to create our own device tree file. We can find the device tree files for SPI0 and SPI1 here

cd /boot/overlays
pi@raspberrypi:~ $ ls /boot/overlays/spi*
/boot/overlays/spi-gpio35-39.dtbo /boot/overlays/spi1-1cs.dtbo /boot/overlays/spi3-2cs.dtbo
/boot/overlays/spi-gpio40-45.dtbo /boot/overlays/spi1-2cs.dtbo /boot/overlays/spi4-1cs.dtbo
/boot/overlays/spi-rtc.dtbo /boot/overlays/spi1-3cs.dtbo /boot/overlays/spi4-2cs.dtbo
/boot/overlays/spi0-1cs.dtbo /boot/overlays/spi2-1cs.dtbo /boot/overlays/spi5-1cs.dtbo
/boot/overlays/spi0-2cs.dtbo /boot/overlays/spi2-2cs.dtbo /boot/overlays/spi5-2cs.dtbo
/boot/overlays/spi0-cs.dtbo /boot/overlays/spi2-3cs.dtbo /boot/overlays/spi6-1cs.dtbo
/boot/overlays/spi0-hw-cs.dtbo /boot/overlays/spi3-1cs.dtbo /boot/overlays/spi6-2cs.dtbo

We will create a copy of spi1-1cs.dtbo in our home directory

sudo cp spi1-1cs.dtbo /home/pi/spi1-1cs-p36.dtbo

Because it’s a data tree blob overlay file (.dtbo) it’s not human-readable. Therefore we need to convert it to a data tree source file (.dts) which we can read and edit. But first we need to install the device tree compiler

sudo apt-get install device-tree-compiler

convert the .dtbo file to a .dts file

dtc -I dtb -O dts -f spi1-1cs-p36.dtbo -o spi1-1cs-p36.dts

now we can edit it

sudo nano spi1-1cs-p36.dts

and change two entries (spi1_cs_pins -> brcm, pins and cs-gpios) We replace 0x12 (hexadecimal for 18) wit 0x10 (hexadecimal for 16) which means CS0 on GPIO 18 (pin 12) is assigned to GPIO 16 (pin 36)

/dts-v1/;

/ {
	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

	fragment@0 {
		target = <0xffffffff>;

		__overlay__ {

			spi1_pins {
				brcm,pins = <0x13 0x14 0x15>;
				brcm,function = <0x3>;
				phandle = <0x1>;
			};

			spi1_cs_pins {
				brcm,pins = <0x10>;
				brcm,function = <0x1>;
				phandle = <0x2>;
			};
		};
	};

	fragment@1 {
		target = <0xffffffff>;

		__overlay__ {
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			pinctrl-names = "default";
			pinctrl-0 = <0x1 0x2>;
			cs-gpios = <0xffffffff 0x10 0x1>;
			status = "okay";
			phandle = <0x3>;

			spidev@0 {
				compatible = "spidev";
				reg = <0x0>;
				#address-cells = <0x1>;
				#size-cells = <0x0>;
				spi-max-frequency = <0x7735940>;
				status = "okay";
				phandle = <0x4>;
			};
		};
	};

	fragment@2 {
		target = <0xffffffff>;

		__overlay__ {
			status = "okay";
		};
	};

	__overrides__ {
		cs0_pin = [00 00 00 02 62 72 63 6d 2c 70 69 6e 73 3a 30 00 00 00 00 03 63 73 2d 67 70 69 6f 73 3a 34 00];
		cs0_spidev = [00 00 00 04 73 74 61 74 75 73 00];
	};

	__symbols__ {
		spi1_pins = "/fragment@0/__overlay__/spi1_pins";
		spi1_cs_pins = "/fragment@0/__overlay__/spi1_cs_pins";
		frag1 = "/fragment@1/__overlay__";
		spidev1_0 = "/fragment@1/__overlay__/spidev@0";
	};

	__fixups__ {
		gpio = "/fragment@0:target:0", "/fragment@1/__overlay__:cs-gpios:0";
		spi1 = "/fragment@1:target:0";
		aux = "/fragment@2:target:0";
	};

	__local_fixups__ {

		fragment@1 {

			__overlay__ {
				pinctrl-0 = <0x0 0x4>;
			};
		};

		__overrides__ {
			cs0_pin = <0x0 0x10>;
			cs0_spidev = <0x0>;
		};
	};
};

We save our file with ctrl + x and y.

The .dts file need to be converted back to a .dtbo file

dtc -@ -I dts -O dtb -o spi1-1cs-p36.dtbo spi1-1cs-p36.dts

and copied to the folder with all the other device tree files

sudo cp spi1-1cs-p36.dtbo /boot/overlays/

To activate the changes we simply edit the config.txt

sudo nano /boot/config.txt

and change spi1-3cs to

dtoverlay=spi1-1cs-p36

and finally we do a reboot

sudo reboot

That’s it!

If you want to learn more about device trees and how they work in detail, i recommend the documentation of Raspberry Pi: https://www.raspberrypi.org/documentation/configuration/device-tree.md

I’ve got the idea to modify an existing .dtbo file from this thread:

https://www.raspberrypi.org/forums/viewtopic.php?t=203776

Tutorials:

Leave a Reply

Your email address will not be published. Required fields are marked *