OrangePi-PCを使ってみる

複数デバイスとのSPI通信

RaspberryPiには/dev/spidev0.0  と /dev/spidev0.1 の2つのデバイスが有り、2つのSPIデバイスを同時に接続する事ができます。
RaspberryPiで2つのデバイスとSPIで通信する場合は以下の様に、CE0とCE1を別々のSLAVEに接続します。
左側のチップはMCP3204 右側のチップはMCP3002のADコンバータです。



RaspberryPiで以下のコードを実行すると、MCP3202 MCP3002 のそれぞれとSPI通信をすることができます。
/*
 * Read MPC3002/MCP3204 with wiringPiSPIDataRW
 */
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>

#define DEBUG 1
#define SPI0 0 // /dev/spidev0.0
#define SPI1 1 // /dev/spidev0.1

int main(int argc, char **argv){
  int retCode;
  int i;
  int a2dChannel = 0;  // analog channel
  int a2dVal = 0;
  float a2dVol = 0;
  float Vref = 3.3;
  unsigned char data[3];

  if (argc == 2) {
    printf("argv[1]=%s\n",argv[1]);
    a2dChannel=atoi(argv[1]);
  }

// SPI channel 0 (1MHz)
  if (wiringPiSPISetup(SPI0, 1000000) < 0)
  {
    printf("SPISetup failed:\n");
  }

// SPI channel 1 (1MHz)
  if (wiringPiSPISetup(SPI1, 1000000) < 0)
  {
    printf("SPISetup failed:\n");
  }

  for(i=0;i<10;i++) {
    data[0] = 0b01100000 |( ((a2dChannel & 0x03) << 4));  //  first byte transmitted -> start bit
    data[1] = 0; // third byte transmitted....don't care
if(DEBUG)printf("[MCP3002]data[write]=%02x-%02x\n",data[0],data[1]);
    retCode=wiringPiSPIDataRW (SPI0,data,sizeof(data));
if(DEBUG)printf("[MCP3002]wiringPiSPIDataRW=%d\n",retCode);
if(DEBUG)printf("[MCP3002]data[read]=%02x-%02x\n",data[0],data[1]);
    a2dVal = (data[0]<< 8) & 0b1100000000; //first 2 bit
    a2dVal |=  (data[1] & 0xff);
    a2dVol = (float)a2dVal/1023 * Vref;
    printf("[MCP3002]a2dVal=%d\n",a2dVal);
    printf("[MCP3002]a2dVol=%f[V]\n",a2dVol);
    sleep(1);

    data[0] = 0b00000110 |( ((a2dChannel & 0x04) >> 2));  //  first byte transmitted -> start bit -> (SGL/DIF = 1, D2=0)
    data[1] = 0b00000000 |( ((a2dChannel & 0x03) << 6)); // second byte transmitted -> (D1=D0=0)
    data[2] = 0; // third byte transmitted....don't care
if(DEBUG)printf("[MCP3204]data[write]=%02x-%02x-%02x\n",data[0],data[1],data[2]);
    retCode=wiringPiSPIDataRW (SPI1,data,sizeof(data));
if(DEBUG)printf("[MCP3004]wiringPiSPIDataRW=%d\n",retCode);
if(DEBUG)printf("[MCP3204]data[read]=%02x-%02x-%02x\n",data[0],data[1],data[2]);
    a2dVal = (data[1]<< 8) & 0b111100000000; //first 4 bit
    a2dVal |=  (data[2] & 0xff);
    a2dVol = (float)a2dVal/4095 * Vref;
    printf("[MCP3204]a2dVal=%d\n",a2dVal);
    printf("[MCP3204]a2dVol=%f[V]\n",a2dVol);
    sleep(1);
  }
}

OrangePi-PC の場合、CE0しかありません。
そこで、2つのデバイスとSPIで通信する場合は以下の様に、ChipSelectに汎用のGPIOポートを使います。
汎用のGPIOポートをChipSelectとして使うので、ChipSelectの制御はアプリ内で行う必要が有ります。
以下の例ではGPIO8(Pin#3) と GPIO9(Pin#5) をChipSelectとして使っています。(OrangePi のFritzing パーツ図欲しいです)
OrangePi ONEのFritzingパーツ図はこちらにありました。



OrangePiでも以下のコードを実行すると、MCP3202 MCP3002 のそれぞれとSPI通信をすることができます。
/*
 * Read MPC3002/MCP3204 with wiringPiSPIDataRW
 */
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>

#define DEBUG 1
#define SPI0 0 // /dev/spidev0.0
#define CS0  8 // Slave1 ChipSelect
#define CS1  9 // Slave2 ChipSekect

int main(int argc, char **argv){
  int retCode;
  int i;
  int a2dChannel = 0;  // analog channel
  int a2dVal = 0;
  float a2dVol = 0;
  float Vref = 3.3;
  unsigned char data[3];

  if (argc == 2) {
    printf("argv[1]=%s\n",argv[1]);
    a2dChannel=atoi(argv[1]);
  }

  if (wiringPiSetup() == -1) {
    printf("wiringPiSetup Error\n");
  }
  pinMode(CS0,OUTPUT);
  pinMode(CS1,OUTPUT);
  digitalWrite(CS0,HIGH);
  digitalWrite(CS1,HIGH);

// SPI channel 0 を 1MHz で開始。
  if (wiringPiSPISetup(SPI0, 1000000) < 0)
  {
    printf("SPISetup failed:\n");
  }

  for(i=0;i<10;i++) {
    digitalWrite(CS0,LOW);
    data[0] = 0b01100000 |( ((a2dChannel & 0x03) << 4));  //  first byte transmitted -> start bit
    data[1] = 0; // third byte transmitted....don't care
if(DEBUG)printf("[MCP3002]data[write]=%02x-%02x\n",data[0],data[1]);
    retCode=wiringPiSPIDataRW (SPI0,data,sizeof(data));
if(DEBUG)printf("[MCP3002]wiringPiSPIDataRW=%d\n",retCode);
if(DEBUG)printf("[MCP3002]data[read]=%02x-%02x\n",data[0],data[1]);
    a2dVal = (data[0]<< 8) & 0b1100000000; //first 2 bit
    a2dVal |=  (data[1] & 0xff);
    a2dVol = (float)a2dVal/1023 * Vref;
    printf("[MCP3002]a2dVal=%d\n",a2dVal);
    printf("[MCP3002]a2dVol=%f[V]\n",a2dVol);
    digitalWrite(CS0,HIGH);
    sleep(1);

    digitalWrite(CS1,LOW);
    data[0] = 0b00000110 |( ((a2dChannel & 0x04) >> 2));  //  first byte transmitted -> start bit -> (SGL/DIF = 1, D2=0)
    data[1] = 0b00000000 |( ((a2dChannel & 0x03) << 6)); // second byte transmitted -> (D1=D0=0)
    data[2] = 0; // third byte transmitted....don't care
if(DEBUG)printf("[MCP3204]data[write]=%02x-%02x-%02x\n",data[0],data[1],data[2]);
    retCode=wiringPiSPIDataRW (SPI0,data,sizeof(data));
if(DEBUG)printf("[MCP3004]wiringPiSPIDataRW=%d\n",retCode);
if(DEBUG)printf("[MCP3204]data[read]=%02x-%02x-%02x\n",data[0],data[1],data[2]);
    a2dVal = (data[1]<< 8) & 0b111100000000; //first 4 bit
    a2dVal |=  (data[2] & 0xff);
    a2dVol = (float)a2dVal/4095 * Vref;
    printf("[MCP3204]a2dVal=%d\n",a2dVal);
    printf("[MCP3204]a2dVol=%f[V]\n",a2dVol);
    digitalWrite(CS1,HIGH);
    sleep(1);
  }
}

次回は1 Wireデバイスの使い方を紹介します。