SPIデバイスの活用

6.1. SPIとは

SPIは「Serial Peripheral Interface」の略で、主に機器内の通信に用いられる通信方式です。 I2Cと同様に機器内のセンサーやメモリー等のインターフェースとして普及していますが、より近距離で高速な通信に用いられる場合が多いです。

一般的な接続方法を下図に示します。 なお、Armadillo-640はマスターとして別のデバイスと通信できます。

images/bus_structures/spi.svg

図6.1 SPIの接続方法


images/bus_structures/spi_3slaves.svg

図6.2 複数のスレーブを接続する場合


SPIの主な特徴を以下に示します。

  • デバイスはマスターとスレーブが存在
  • 1つのバス上にマスターは1つ、スレーブは複数接続可能
  • データはクロックに合わせて変化
  • 信号線はクロック、送受信のデータ、スレーブセレクト(SS)
  • 通信は常にマスターが開始し、SS=Lowでスレーブを選択
  • クロックは最高100MHz程度

SPIでは信号名・ピン名は統一されておらず、主に2通りの呼び方があります。

  • シリアルクロック(SCLK) = SCK
  • マスターアウト/スレーブイン(MOSI) = [マスターのSDO、スレーブのSDI]
  • マスターイン/スレーブアウト(MISO) = [マスターのSDI、スレーブのSDO]
  • スレーブセレクト(SS) = チップセレクト(CS)

SDOは相手のSDIに接続します。 双方向通信が不要の場合、MOSIもしくはMISOを接続しないことがあります。

SPIではクロックの極性(Polarity)と位相(Phase)も統一されておらず、通信相手に合わせて設定する必要があります。 極性はCPOL、位相はCPHAで設定します。

  • CPOL=0: クロックを出力していないときSCLKをLowに保ちます。

    • CPHA=0: クロックの立ち上がりでデータをラッチします。
    • CPHA=1: クロックの立ち下がりでデータをラッチします。
  • CPOL=1: クロックを出力していないときSCLKをHighに保ちます。

    • CPHA=0: クロックの立ち下がりでデータをラッチします。
    • CPHA=1: クロックの立ち上がりでデータをラッチします。

CPOLとCPHAの組み合わせを、SPIモードで表現する場合もあります。

表6.1 SPIモード

モード CPOL CPHA

0

0

0

1

0

1

2

1

0

3

1

1


各モードの波形は以下のようになっています。

images/waveforms/spi.svg

図6.3 SPIモードと波形


x

6.2. A/Dコンバーター(MCP3204)を使用する

ここでは、SPIバスにA/Dコンバーターを接続する方法を紹介します。

使用するデバイスは以下のとおりです。

  • MCP3204(Microchip Technology製)

今回使用するMCP3204は、以下の特長を持ちます。

  • 単電源動作(2.7~5.5V)
  • SPI接続 最大2MHz(Vdd=5V時)、最大1MHz(Vdd=2.7V時)
  • サンプリング速度 最大100ksps(Vdd=5V時)、50ksps(Vdd=2.7V時)
  • 分解能 12ビット
  • 逐次比較型
  • 4入力
  • 疑似差動入力によるコモンモードノイズ除去が可能

6.2.1. 接続方法

Armadillo-640との接続を示します。 Armadillo-640のCON9から出ているECSPI1にMCP3204を接続します。 SS信号には、GPIOを使用します。 AIN0~AIN3がアナログ入力ピンです。 AIN0にかかる電圧を、10kΩの可変抵抗で変えられるようにしています。 AIN1~AIN3はそれぞれ固定電圧としています。 リファレンス電圧VREFに電源電圧と同じ3.3Vを入力しているため、 0Vから3.3Vの範囲のアナログ入力を12ビット(4096段階)のデジタル値に変換します。

SPI接続A/Dコンバーター回路図

図6.4 SPI接続A/Dコンバーター回路図


6.2.2. 対応カーネルイメージの作成

SPIドライバ・MCP3204のドライバを有効にしたLinuxカーネルと、DTBを作成します。

標準状態のカーネルのソースコードを元に変更する手順は次の通りです。

  1. Device Treeの編集
  2. カーネルコンフィギュレーションでのSPIの有効化
  3. カーネルコンフィギュレーションでのデバイスドライバの有効化
  4. カーネルとDTBをビルドしArmadilloに書き込み

はじめにDevice Treeを作成します。ファイル名は arch/arm/boot/dts/armadillo-640-ecspi1.dtsiです(「サンプルソースコード」のページからダウンロードできます)。

&iomuxc {
        pinctrl_ecspi1: ecspi1grp {
                fsl,pins = <
                        MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK       0x1b0b0 // CON9_15
                        MX6UL_PAD_LCD_DATA21__GPIO3_IO26        0x1b0b0 // CON9_16
                        MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI       0x1b0b0 // CON9_17
                        MX6UL_PAD_LCD_DATA23__ECSPI1_MISO       0x1b0b0 // CON9_18
                >;
        };
};

&ecspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi1>;
        cs-gpios = <&gpio3 26 GPIO_ACTIVE_HIGH>;
        status = "okay";

        mcp3204@0 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "mcp3204";
                spi-max-frequency = <1000000>;
                reg = <0>;
        };
};

図6.5 armadillo-640-ecspi1.dtsi


さきほどのファイルへのincludeをarch/arm/boot/dts/armadillo-640.dtsに追加してください。

#include "armadillo-640-lcd70ext-l00.dtsi"
#endif
#include "armadillo-640-ecspi1.dtsi"        //追加行

/ {
        model = "Atmark Techno Armadillo-640";

図6.6 armadillo-640.dts


続いて「イメージをカスタマイズする」と同様にmenuconfigを使用してカーネルコンフィギュレーションを変更します。

[ATDE ~/linux-4.14-at[version]]$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

図6.7 menuconfigの実行


Device Drivers  --->
  [*] SPI support  --->                                 ← 有効にする
    [*]   Freescale i.MX SPI controllers                ← 有効にする
  [*] Industrial I/O support  --->                      ← 有効にする
    Analog to digital converters  --->
      [*] Microchip Technology MCP3x01/02/04/08         ← 有効にする

図6.8 menuconfig


変更を加え、カーネルコンフィギュレーションを確定してください。

以上の変更後、「イメージをカスタマイズする」と同様にカーネルとDTBをビルドし、Armadilloに書き込んでください。

6.2.3. 使用例

実際に、MCP3204から値の取得をおこなう手順を説明します。

[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
0123                                                                   ←VR1を回すと値が変化
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
1234                                                                   ←VR1を回すと値が変化
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
2345                                                                   ←VR1を回すと値が変化
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage1_raw
2048
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage2_raw
4095
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage3_raw
0
[armadillo ~]# cat /sys/bus/iio/devices/iio\:device0/in_voltage2-voltage3_raw
2048                                                                   ←CH2-CH3の差動電圧

図6.9 コマンド実行例


6.2.4. プロトコル

MCP3204は、SPIモード0(CPOL=0、CPHA=0)またはSPIモード3(CPOL=1、CPHA=1)で 通信をおこないます。MCP3204の通信フォーマットを 図6.10「MCP3204通信フォーマット」に示します。

MCP3204通信フォーマット

図6.10 MCP3204通信フォーマット


MOSIから1を出力することで、転送の開始をMCP3204に指示します。SGL/DIFF*、 D2、D1、D0の組み合わせにより、A/D変換をおこなうチャンネルを指定します。 D0以降、MOSIから出力されるデータは意味を持ちません。

表6.2 MCP3204チャンネル指定

SGL/DIFF D2[a] D1 D0 入力構成 チャンネル

1

d.c.

0

0

シングルエンド

CH0

1

d.c.

0

1

シングルエンド

CH1

1

d.c.

1

0

シングルエンド

CH2

1

d.c.

1

1

シングルエンド

CH3

0

d.c.

0

0

ディファレンシャル

CH0=IN+、CH1=IN-

0

d.c.

0

1

ディファレンシャル

CH0=IN-、CH1=IN+

0

d.c.

1

0

ディファレンシャル

CH2=IN+、CH3=IN-

0

d.c.

1

1

ディファレンシャル

CH2=IN-、CH3=IN+

[a] MCP3204ではD2は意味を持ちません。


MCP3204は、11番目のクロックの立ち上がりでアナログ入力のサンプリングを開始し、 次のクロックの立ち下がりで完了します。A/D変換結果は、B11~B0に出力されま す。