OrangePi-PCを使ってみる

SPI通信 その1

OrangePi-PC でSPI通信を試してみます。
OrangePi-PC のFAQに よると、

The SPI driver is compiled as a module. You need to load the SPI driver to enable it:
sudo modprobe spi-sun7i

と書かれていますが、spi-sun7i はどこにも存在しません。
結論から言うと、SPIドライバーはカーネルに組み込まれています。

デバイススペシャルファイルも1つだけ存在しています。



そこで、以下のような回路でmcp23S17の動作を確認しました。




以下のプログラムをRaspberryPiで実行すると、LEDが順番に点滅します。
OrangePi-PC でも、全く同じコード、同じワイヤリングで正常に動作しました。

//
// test program for MCP23S17 with wiringPi
// cc -o mcp23s17Led mcp23s17Led.c -l wiringPi
//
#include <stdio.h>
#include <time.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>

#define IODIRA          0x00            // MCP23S17 address of I/O direction
#define IODIRB          0x01            // MCP23S17 address of I/O direction
#define GPIOA           0x12            // MCP23S17 address of GP Value
#define GPIOB           0x13            // MCP23S17 address of GP Value
#define ADDRESS         0b01000000      // MCP23S17 SPI Address
#define CHANNEL         0               // MCP23S17 SPI Port

// MCP23S17 SPI Data Transfer
void SPI_TX(unsigned char device, unsigned char regadd, unsigned char
tx_data) {
  char tbuf[3];
  device = device & 0b11111110; // Clear last bit for a write
  tbuf[0]=device;
  tbuf[1]=regadd;
  tbuf[2]=tx_data;
  wiringPiSPIDataRW(CHANNEL,tbuf,sizeof(tbuf));
}

int main(int argc, char **argv) {
  int i;
  int byte;

  if (wiringPiSPISetup(CHANNEL, 32000000) < 0) {
    printf("wiringPiSPISetup Error\n");
    return 1;
  }

  SPI_TX(ADDRESS,IODIRA,0x00);
  SPI_TX(ADDRESS,IODIRB,0x00);
  SPI_TX(ADDRESS,GPIOA,0x00);
  SPI_TX(ADDRESS,GPIOB,0x00);

  byte=0;
  for(i=0;i<8;i++) {
    byte=(byte<<1) + 1;
    SPI_TX(ADDRESS,GPIOA,byte);
    delay(1000);
  }
  delay(2000);

  for(i=0;i<10;i++) {
    byte=0;
    SPI_TX(ADDRESS,GPIOA,byte);
    delay(1000);
    byte=0xff;
    SPI_TX(ADDRESS,GPIOA,byte);
    delay(1000);
  }
  delay(2000);

  byte=0xff;
  for(i=0;i<8;i++) {
    byte=(byte>>1);
    SPI_TX(ADDRESS,GPIOA,byte);
    delay(1000);
  }
}

mcp23s17Setup を使った digitalWrite も正常に動きました。
ちなみに mcp23s17Setup を使うと
#define MCP_SPEED       4000000 (4MHz)
で動きます。
これは OrangePi-PC でも RaspberryPi でも同じです。

//
// test program for MCP23S17 with wiringPi
// cc -o mcp23s17Setup mcp23s17Setup.c -l wiringPi
//
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <mcp23s17.h>

#define PINBASE 100

int main(int argc, char **argv) {
 int i;

  if (mcp23s17Setup(PINBASE,0,0) == -1){
    printf("mcp23s17Setup Fail\n");
    return 1;
  }

  for(i=0;i<8;i++) {
    pinMode(PINBASE+i,OUTPUT);
    digitalWrite(PINBASE+i,0);
  }

  for(i=0;i<8;i++) {
    digitalWrite(PINBASE+i,1);
    delay(1000);
  }
  delay(2000);

  for(i=0;i<8;i++) {
    digitalWrite(PINBASE+7-i,0);
    delay(1000);
  }
}

こちらで紹介しているプログラムを試してみました。

$ sudo ./mcp23s17w
time:19.0Sec

CPUパワーの差で、RaspberryPI(35秒)よりも少し早いです。
30000回のパラレルI/Oの時間比較。

wiringPiライブラリ bcm2835ライブラリ
RPi+MCP23S17(SPI) 35秒 1秒
OPi+MCP23S17(SPI) 19秒 サポートしていない

例えばSPI接続のTFTなど、高速でSPI通信したいとき、OPiではどうにもなりません。

Orange Pi PCのマニュアルによると、ピンヘッダーには SPI0_CS(Pin#24 PC3)/SPI0_CLK(Pin#23 PC2)と
SPI1_CS(Pin#8 PA13)/SPI1_CLK(Pin#10 PA14)の2つがありますが、
デバイススペシャルファイルは「/dev/spidev0.0」1つだけです。
あちこち探したら、こちらに 情報が有りました。
おそらくロシア語のページですが何となく意味は分かります。
script.bin の以下の部分を変更すれば、2つのSPIデバイスができますが、SPI1のMOSI(PA15)/MISO(PA16)は
ピンヘッダーに出ていないので、要するにSPI1は使えません。
script.bin の変更手順はこちらで紹介しています。

[spi0]
spi_used = 1
spi_cs_bitmap = 1
spi_mosi = port:PC00<3><default><default><default>
spi_miso = port:PC01<3><default><default><default>
spi_sclk = port:PC02<3><default><default><default>
spi_cs0 = port:PC03<3><1><default><default>

[spi1]
spi_used = 0 → 1
spi_cs_bitmap = 1
spi_cs0 = port:PA13<2><1><default><default>
spi_sclk = port:PA14<2><default><default><default>
spi_mosi = port:PA15<2><default><default><default>
spi_miso = port:PA16<2><default><default><default>

[spi_devices]
spi_dev_num = 1 → 2

[spi_board0]
modalias = "spidev"
max_speed_hz = 33000000
bus_num = 0
chip_select = 0
mode = 0
full_duplex = 1
manual_cs = 0

[spi_board1] → セクションを追加
modalias = "spidev"
max_speed_hz = 33000000
bus_num = 1
chip_select = 0
mode = 0
full_duplex = 1
manual_cs = 0




[leds_para]
leds_used = 1 → 0
green_led = port:PL10<1><default><default><1>
green_led_active_low = 0
red_led = port:PA15<1><default><default><0>
red_led_active_low = 0



[audio0]
audio_used = 1 → 0
lineout_vol = 31
cap_vol = 5
audio_hp_ldo = "none"
adcagc_used = 0
adcdrc_used = 0
dacdrc_used = 0
adchpf_used = 0
dachpf_used = 0
audio_pa_ctrl = port:PA16<1><default><default><0>




Raspberryでは「/dev/spidev0.0」と「/dev/spidev0.1」の2つのデバイスを使うことができます。
「/dev/spidev0.0」ではGPIO8をChipSelectとして使い、「/dev/spidev0.1」ではGPIO7を ChipSelectとして使うことで
2つのSlaveデバイスと同時にSPIで通信することができます。
RPI--+-- GPIO8(Active LOW) --- Slave Device 1
     |-- GPIO7(Active LOW) --- Slave Device 2

OrangePiでは1つしかデバイスファイルが無いので、2つのSlaveデバイスと同時にSPIで通信するためには、
ChipSelectのためのGPIOを別に用意する必要が有ります。

次回は2つのSlaveデバイスと同時にSPIで通信する方法を紹介しま す。