yoshiyuki's blog

Arduino/Teensy/Raspberry pi pico を利用した I2C, SPI 通信アプリを紹介します

Arduino / I2C Slave デバイスを作る

Arduino を I2C Slave デバイスにするための Sketch です。自作アプリの動作確認用に作成しました。

主な仕様

  • SDA = A4
  • SCL = A5
  • 7-bit Slave Address = 0x24 (8-bit表記では 0x48/0x49)
  • SCL/SDA 内蔵 Pull-up 有り (内蔵 Pull-up 無しの Sketch もあり)
  • 16-byte Register (Address: 0x00 to 0x0F)
  • Burst mode 対応
  • Register Address = 0x00 に値を書き込むと、値の回数だけ Arduino上の LED が点滅する

Register Map

Address (Hex) R/W 初期値 (Hex)
00 R/W 00
01 R/W 10
02 R/W 02
03 R/W 30
04 R/W 04
05 R/W 50
06 R/W 06
07 R/W 70
08 R/W 08
09 R/W 90
0A R/W 0A
0B R/W B0
0C R/W 0C
0D R/W D0
0E R/W 0E
0F R/W F0

Sketch

#include <Wire.h>

byte byteSlaveADR = 0x24; // 7-bit Slave Address
byte byteADR;
byte byteDAT[32];
byte byteREG[] = {0x00, 0x10, 0x02, 0x30, 0x04, 0x50, 0x06, 0x70, 0x08, 0x90, 0x0a, 0xb0, 0x0c, 0xd0, 0x0e, 0xf0};
bool trig; 

int led=13;

void setup() {
  pinMode(led, OUTPUT);
  
  Wire.begin(byteSlaveADR);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(sendEvent);

  trig = false;
}

void loop() {
  if(trig){
    blink_led(byteREG[0]);
  }

  delay(1000);
}

void blink_led(byte byteCNT){
  int i;

  for(i=0;i<byteCNT;i++){
    digitalWrite(led, HIGH);
    delay(100);
    digitalWrite(led,LOW);
    delay(500);
  }

  trig = false;
}

void receiveEvent(){
  int i = 0;
  int j;
  byte byteTMP;
  
  while(Wire.available()){
    if(i < 32){
      byteDAT[i] = Wire.read();      
    }
    else{
      Wire.read();
    }
    i = i + 1;
  }

  byteADR = byteDAT[0];

  if(i > 1){
    for(j=0;j<(i-1);j++){
      byteTMP = byteADR + j;

      if(byteTMP < 32){
        byteREG[byteTMP] = byteDAT[j+1];

        if(byteTMP == 0){
          trig = true;
        }
      }
    }
  }
}

void sendEvent(){
  int i;

  for(i=byteADR;i<16;i++){
    Wire.write(byteREG[i]);
  }
}

Sketch (SCL/SDA 内蔵Pull-up 無効)

上の Sketch に SCL/SDA の内蔵Pull-up を無効にする記述を追加したものです。

#include <Wire.h>

byte byteSlaveADR = 0x24; // 7-bit Slave Address
byte byteADR;
byte byteDAT[32];
byte byteREG[] = {0x00, 0x10, 0x02, 0x30, 0x04, 0x50, 0x06, 0x70, 0x08, 0x90, 0x0a, 0xb0, 0x0c, 0xd0, 0x0e, 0xf0};
bool trig; 

int led=13;

void setup() {
  pinMode(led, OUTPUT);
  
  Wire.begin(byteSlaveADR);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(sendEvent);

  pinMode(SDA, INPUT); // disable internal pull-up
  pinMode(SCL, INPUT); // disable internal pull-up

  trig = false;
}

void loop() {
  if(trig){
    blink_led(byteREG[0]);
  }

  delay(1000);
}

void blink_led(byte byteCNT){
  int i;

  for(i=0;i<byteCNT;i++){
    digitalWrite(led, HIGH);
    delay(100);
    digitalWrite(led,LOW);
    delay(500);
  }

  trig = false;
}

void receiveEvent(){
  int i = 0;
  int j;
  byte byteTMP;
  
  while(Wire.available()){
    if(i < 32){
      byteDAT[i] = Wire.read();      
    }
    else{
      Wire.read();
    }
    i = i + 1;
  }

  byteADR = byteDAT[0];

  if(i > 1){
    for(j=0;j<(i-1);j++){
      byteTMP = byteADR + j;

      if(byteTMP < 32){
        byteREG[byteTMP] = byteDAT[j+1];

        if(byteTMP == 0){
          trig = true;
        }
      }
    }
  }
}

void sendEvent(){
  int i;

  for(i=byteADR;i<16;i++){
    Wire.write(byteREG[i]);
  }
}