Sipeed TANG PriMER を使ってみた [3] – RISC-V で I2C / SPI を使う

前回の記事で FPGA に RISC-V コアを書き込み、Arduino IDE でソフトを開発する環境を構築しました. 今回はこの RISC-V プロセッサの I/O を制御して外部デバイスを動かしてみます.
TANG PriMER FPGA 開発ボード

SPI を使ってみる
まずは SPI インターフェースを使ってみます.接続するデバイスはこちらの記事で使用した ROHM 社製の EEPROM BR25L320 デバイスです.
ハードウェア接続
TANG PriMER ボード上の I/O 端子と SPI 信号は以下のように対応しています.注意点として、SPI MOSI 信号のみボード上の 2.54mm ピッチのピンに接続されておらず、外側のハーフピッチのヘッダから引き出す必要があります. また、SPI CS 信号は、下記のプログラムの通り GPIO を利用した実装とします.
Lichee Tang PinSPI signal
B14SCLK
B10MISO
P4MOSI

ソフトウェア
以下のプログラムを ArduinoIDE 上で作成し、書き込みを行ないます.EEPROM のアドレス 0x01AB にデータ 0xAA を書き込み、読み出しを確認しています. EEPROM の CS, WP, HOLD の各信号は GPIO として実装します.
#include <SPI.h>

const int SPI_CS   = 2;
const int SPI_WP   = 3;
const int SPI_HOLD = 4;

void setup()
{
  pinMode(SPI_CS,   OUTPUT);
  pinMode(SPI_WP,   OUTPUT);
  pinMode(SPI_HOLD, OUTPUT);
  digitalWrite(SPI_CS,   HIGH);
  digitalWrite(SPI_WP,   LOW);
  digitalWrite(SPI_HOLD, LOW);

Serial.begin(19200);
while (!Serial);

SPI.begin();
}

void loop()
{
  byte data[5];
  data[0] = 0x06;
  spi_write_byte(data, 1);

data[0] = 0x02;
  data[1] = 0x01;
  data[2] = 0xAB;
  data[3] = 0xAA;
  spi_write_byte(data, 4);

data[0] = 0x04;
  spi_write_byte(data, 1);

delay(100);

data[0] = 0x03;
  data[1] = 0x01;
  data[2] = 0xAB;
  spi_read_byte(data, data, 3);

Serial.println(data[3], HEX);

delay(2000);           // wait  seconds for next scan
}

void spi_read_byte(byte *wdata, byte *rdata, byte length) 
{
    int i;

digitalWrite(SPI_CS,   LOW);
  digitalWrite(SPI_WP,   HIGH);
  digitalWrite(SPI_HOLD, HIGH);

for( i = 0; i < length; i++ ) {<br />
    SPI.transfer( wdata[i] );
  }
  rdata[i] = SPI.transfer( 0x00 );

digitalWrite(SPI_CS,   HIGH);
  digitalWrite(SPI_WP,   LOW);
  digitalWrite(SPI_HOLD, LOW);

return rdata[i];
}

void spi_write_byte(byte *data, int length) 
{
  int i;
  digitalWrite(SPI_CS,   LOW);
  digitalWrite(SPI_WP,   HIGH);
  digitalWrite(SPI_HOLD, HIGH);

for( i = 0; i < length; i++ ) {
    SPI.transfer( data[i] );
  }

digitalWrite(SPI_CS,   HIGH);
  digitalWrite(SPI_WP,   LOW);
  digitalWrite(SPI_HOLD, LOW);
}


I2C を使ってみる
続いて I2C を使ってみたいと思いますが、現在のところ E203 のハードウェア I2C は Arduino IDE ではサポートされておらず、ソフトウェア I2C で実装するしかなさそうです(E203 の RTL では I2C 回路は実装されているようなので、いずれ別環境で試してみたいと思います.
一応ソフトウェア I2C の機能を使用して実装した例を示します. 接続するデバイスは以下の記事で使用した温度センサ TMP102 です.

ハードウェア接続
TANG PriMER ボード上の I/O 端子と I2C 信号は以下のように対応させました.今回はソフトウェア I2C ですので、使用する端子はソフトウェアで設定可能です.
Lichee Tang PinI2C signal
J11SCL
F16SDA


ソフトウェア
以下のプログラムを ArduinoIDE 上で作成し、書き込みを行ないます.
#include <SlowSoftWire.h>

SlowSoftWire Wire = SlowSoftWire(18, 19, true);

void setup()
{
  Wire.begin();

Serial.begin(19200);
  while (!Serial);<br />
  Serial.println("\nI2C Scanner");
}

void loop()
{
  byte error, address; 
  byte tmp102 = 0;
  int nDevices;

Serial.println(F("Scanning I2C bus (7-bit addresses) ..."));

nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

<pre><code>if (error == 0) {
    Serial.print(F("I2C device found at address 0x"));
    if (address<16)
      Serial.print(F("0"));
    Serial.print(address, HEX);
    Serial.println(F("  !"));

    nDevices++;

    if(address == 0x48) {
      tmp102 = 1;
    }
    else {
      tmp102 = 0;
    }
}
else if (error==4) {
    Serial.print(F("Unknown error at address 0x"));
    if (address<16)
      Serial.print("0");
    Serial.println(address,HEX);
}    
</code></pre>

}

if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else { 
    Serial.println("done\n");

<pre><code>if(tmp102 == 1) {
  uint8_t data[2];
  Wire.requestFrom(0x48, 2, 1); 
  data[0]= Wire.read();
  data[1]= Wire.read();
  Serial.print(F("TMP102 data : 0x")); Serial.print(data[0], HEX); Serial.print(F(" 0x"));  Serial.print(data[1], HEX);
  Serial.println(F(""));
}
</code></pre>

}

delay(2000);           // wait 2 seconds for next scan
}
I2C アドレスをスキャンして、応答のあるデバイスを探し、その中に TMP102 デバイス(スレーブアドレス 0x48)があれば温度データを取得します.シリアルモニタ経由で温度表示が確認できれば通信成功です.

参考
以下を参考とさせていただきました.
https://qiita.com/Nanchite4618/items/62ff04e3345519b3a939

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です