STM32F767でソフトウェアI2Cスレーブで遊ぶ　その1  (100KHz)



x まだ試していない 確認済み2022/5/8 20:41

目的
I2Cスレーブの規格を都合よく解釈して
I2Cスレーブを作ってみた。
めざせ進研xx 100khz

フルの移行図なんか完全に無視


![o_con368.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/0bb0018d-243b-8512-77f7-1b83c31c96ee.jpeg)


●ソフトウェアI2Cスレーブ 10khz　成功


![o_con405.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/fd50724c-09ee-0bc0-0a4d-dcc69d46a1c3.jpeg)


●Aの連続送信のプログラム　100khz?

テストソース


```c++


//I2C_A_031_1

#include <Arduino.h>
#include <Wire.h>

//STM32G031J6M6 i2cピンの定義
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

#define en     PB7     // 1pin

#define ADDR1  0x40

//初期化
void setup() {

  delay(3000); //not Delete

  //GPIOの初期化
  pinMode(en, OUTPUT);

  //i2cの初期化
  Wire.begin(sdaPin, sclPin); //STM32G031J6M6

}//setup

//メインループ
void loop() {

  digitalWrite(en, 1); //LED ON debug

  //I2Cに送信
  Wire.beginTransmission(ADDR1);
  Wire.write('A');
  Wire.endTransmission();

  delay(500);//0.5秒待つ


  digitalWrite(en, 0); //LED OFF debug
  delay(500);//0.5秒待つ

}//loop


```




https://qiita.com/caa45040/items/5032e6905c9425f41495


100khz 失敗　1000 0000    0100 0001になるはず
次は、アドレスAAと55を繰り返す

![o_con406.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/086ccd53-b14f-cb4a-66fd-5268f164c87e.jpeg)


●　アドレスAAと55を繰り返す

(テストソース)

```c++

//I2C_ADD_2A_55_031_1

#include <Arduino.h>
#include <Wire.h>

//STM32G031J6M6 i2cピンの定義
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

#define en     PB7     // 1pin


//初期化
void setup() {

  delay(3000); //not Delete

  //GPIOの初期化
  pinMode(en, OUTPUT);

  //i2cの初期化
  Wire.begin(sdaPin, sclPin); //STM32G031J6M6

}//setup

//メインループ
void loop() {

////////////////////////

  digitalWrite(en, 1); //LED ON debug

  //I2Cに送信
  Wire.beginTransmission(0x2a);
  Wire.write('A');
  Wire.endTransmission();

  delay(500);//0.5秒待つ


  digitalWrite(en, 0); //LED OFF debug
  delay(500);//0.5秒待つ

////////////////////

////////////////////////

  digitalWrite(en, 1); //LED ON debug

  //I2Cに送信
  Wire.beginTransmission(0x55);
  Wire.write('A');
  Wire.endTransmission();

  delay(500);//0.5秒待つ


  digitalWrite(en, 0); //LED OFF debug
  delay(500);//0.5秒待つ

////////////////////

}//loop


```



[結果画面] アドレス読み込み　成功　ーー　次は強制アンク(返事の事)


![o_con407.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/bc427aed-6df1-cf21-4d31-e01d1e3d162a.jpeg)


●強制アンク処理の追加

[結果画面]　成功


![o_con409.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/bdf192e5-4e54-22a6-7b8f-3b86085f9770.jpeg)





ドレインモードとアンク


```c++


pinMode(SDA1, OUTPUT_OPEN_DRAIN);digitalWrite(SDA1,HIGH);



```



```c++


  //アンクの処理
  SCL_H(); digitalWrite(SDA1,0);
  SCL_L(); //digitalWrite(SDA1,0);//pinMode(SDA1, OUTPUT);digitalWrite(SDA1,1);
  //a0 = SDA1;

  //データの取り込み
  SCL_H(); digitalWrite(SDA1,1);//pinMode(SDA1, INPUT);
  SCL_L();
  d7 = digitalRead(SDA1);



```






いろいろ
2022/5/8 19:36ふろ行ってくらー　どうでもいい情報　アイスは、風呂の後
とりあえずソフトウェアI2Cマスター　10khzでためす
次は、たぶんSTM32G031のI2Cマスターで100khz?


強制アンクありのプログラム


```c++


//soft_i2c_slave_test_767_2


#include <Arduino.h>

//ピン 13 LED1
//ピン Vdd
//ピン Gnd
//ピン 

//ピン 
//ピン 
//ピン A4 SDA
//ピン A5 SCL

//GPIOの初期化 //LED1
#define myled 13


#define DW   digitalWrite



#define  SDA1 A4
#define  SCL1 A5

int TinmOut1 = 100000;

//SDAがHの間は、ループ
#define SDA_START() while(digitalRead(SDA1) == 1){}

//SDAがHの間は、ループ TinmOut1付き
#define SDA_H() while(digitalRead(SDA1) == 1 && TinmOut1 != 0){TinmOut1--;}

//SDAがLの間は、ループ TinmOut1付き
#define SDA_L() while(digitalRead(SDA1) == 0 && TinmOut1 != 0){TinmOut1--;}

//SCLがHの間は、ループ TinmOut1付き
void SCL_H() {
  while (digitalRead(SCL1) == 1 && TinmOut1 != 0) {
    TinmOut1--;
  }
}

//SCLがLの間は、ループ TinmOut1付き
void SCL_L() {
  while (digitalRead(SCL1) == 0 && TinmOut1 != 0) {
    TinmOut1--;
  }
}

int input, input_bk = 1;

/*
  //立ち上がり
  void SCL_UP_H()
  {
    while(TinmOut1 != 0){

       //立ち上がり
       input = SCL1;
       if( input_bk != input ){
           if( input == 1 ) break;
       }//endif

      //バックアップの保存
      input_bk = input;

      TinmOut1--;
    }//while
  }//SCL_UP_H()
*/

//初期化関数
void setup()
{

  //シリアルの初期化
  Serial.begin(9600);

  //LED1ポートの初期化
  pinMode(myled, OUTPUT);

  //ソフトI2Cの初期化
  //pinMode(SDA1, INPUT);
  //pinMode(SDA1, INPUT);
  //pinMode(SDA1, INPUT);
  pinMode(SDA1, OUTPUT_OPEN_DRAIN);digitalWrite(SDA1,HIGH);
  pinMode(SCL1, INPUT);
  

}//setup

char buf[10]; //I2Cバッファー
int ii; //ループカウンター

//アドレス
int a0, a1, a2, a3, a4, a5, a6, a7;
int a[8];

//データ
int d0, d1, d2, d3, d4, d5, d6, d7;
int d[8];

//無限ループ
void loop()
{

  //スタート信号の立下りを待つ
  //タイムアウトの設定
  TinmOut1 = 100000;

  //開始
  SDA_START();

  //アドレスの取り込み
  SCL_H();
  SCL_L();
  a7 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a6 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a5 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a4 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a3 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a2 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a1 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a0 = digitalRead(SDA1);


  //a7 = 1;
  //a6 = 0;
  //a5 = 0;
  //a4 = 0;
  //a3 = 0;
  //a2 = 0;
  //a1 = 0;
  //a0 = 0;

  //アンクの処理
  SCL_H(); digitalWrite(SDA1,0);
  SCL_L(); //digitalWrite(SDA1,0);//pinMode(SDA1, OUTPUT);digitalWrite(SDA1,1);
  //a0 = SDA1;

  //データの取り込み
  SCL_H(); digitalWrite(SDA1,1);//pinMode(SDA1, INPUT);
  SCL_L();
  d7 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d6 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d5 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d4 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d3 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d2 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d1 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d0 = digitalRead(SDA1);

  //d7 = 0;
  //d6 = 0;
  //d5 = 1;
  //d4 = 1;
  //d3 = 0;
  //d2 = 0;
  //d1 = 0;
  //d0 = 0;


  digitalWrite(myled, HIGH); //LED ON  debug

  buf[0] = 'U';//バッファーのクリア
  buf[1] = 0;


  //I2Cスレーブの受信データの表示
  Serial.print(buf);
  Serial.print("\r\n");


  //I2Cスレーブの受信データの表示 debug
  //pc_printf("Read A: %x\r\n", buf[0]);

  digitalWrite(myled, HIGH); //LED OFF  debug


  a[7] = a0;
  a[6] = a1;
  a[5] = a2;
  a[4] = a3;
  a[3] = a4;
  a[2] = a5;
  a[1] = a6;
  a[0] = a7;

  d[7] = d0;
  d[6] = d1;
  d[5] = d2;
  d[4] = d3;
  d[3] = d4;
  d[2] = d5;
  d[1] = d6;
  d[0] = d7;

  //アドレスの表示
  for (ii = 0; ii < 8; ii++) {
    if (ii == 4) Serial.print(": ");

    if (a[ii] == 0) {
      Serial.print("__ ");
    } else {
      Serial.print("[] ");
    }//ebdif
    
  }//for
  Serial.print("\r\n");//リターン


  //データの表示
  for (ii = 0; ii < 8; ii++) {
    if (ii == 4) Serial.print(": ");

    if (d[ii] == 0) {
      Serial.print("__ ");
    } else {
      Serial.print("[] ");
    }//endif
    
  }//for
  Serial.print("\r\n");//リターン

  digitalWrite(myled, LOW); //LED OFF  debug

  delay(500);//0.5秒待つ
  
}//loop



```





アンクなし　Arduino Uno用がそのまま動いた。


```c++




//soft_i2c_slave_test_767_1


#include <Arduino.h>

//ピン 13 LED1
//ピン Vdd
//ピン Gnd
//ピン 

//ピン 
//ピン 
//ピン A4 SDA
//ピン A5 SCL

//GPIOの初期化 //LED1
#define myled 13


#define DW   digitalWrite



#define  SDA1 A4
#define  SCL1 A5

int TinmOut1 = 100000;

//SDAがHの間は、ループ
#define SDA_START() while(digitalRead(SDA1) == 1){}

//SDAがHの間は、ループ TinmOut1付き
#define SDA_H() while(digitalRead(SDA1) == 1 && TinmOut1 != 0){TinmOut1--;}

//SDAがLの間は、ループ TinmOut1付き
#define SDA_L() while(digitalRead(SDA1) == 0 && TinmOut1 != 0){TinmOut1--;}

//SCLがHの間は、ループ TinmOut1付き
void SCL_H() {
  while (digitalRead(SCL1) == 1 && TinmOut1 != 0) {
    TinmOut1--;
  }
}

//SCLがLの間は、ループ TinmOut1付き
void SCL_L() {
  while (digitalRead(SCL1) == 0 && TinmOut1 != 0) {
    TinmOut1--;
  }
}

int input, input_bk = 1;

/*
  //立ち上がり
  void SCL_UP_H()
  {
    while(TinmOut1 != 0){

       //立ち上がり
       input = SCL1;
       if( input_bk != input ){
           if( input == 1 ) break;
       }//endif

      //バックアップの保存
      input_bk = input;

      TinmOut1--;
    }//while
  }//SCL_UP_H()
*/

//初期化関数
void setup()
{

  //シリアルの初期化
  Serial.begin(9600);

  //LED1ポートの初期化
  pinMode(myled, OUTPUT);

  //ソフトI2Cの初期化
  pinMode(SDA1, INPUT);
  pinMode(SCL1, INPUT);

}//setup

char buf[10]; //I2Cバッファー
int ii; //ループカウンター

//アドレス
int a0, a1, a2, a3, a4, a5, a6, a7;
int a[8];

//データ
int d0, d1, d2, d3, d4, d5, d6, d7;
int d[8];

//無限ループ
void loop()
{

  //スタート信号の立下りを待つ
  //タイムアウトの設定
  TinmOut1 = 100000;

  //開始
  SDA_START();

  //アドレスの取り込み
  SCL_H();
  SCL_L();
  a7 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a6 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a5 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a4 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a3 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a2 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a1 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  a0 = digitalRead(SDA1);


  //a7 = 1;
  //a6 = 0;
  //a5 = 0;
  //a4 = 0;
  //a3 = 0;
  //a2 = 0;
  //a1 = 0;
  //a0 = 0;

  //アンクの処理
  SCL_H();
  SCL_L();
  //a0 = SDA1;

  //データの取り込み
  SCL_H();
  SCL_L();
  d7 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d6 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d5 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d4 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d3 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d2 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d1 = digitalRead(SDA1);

  SCL_H();
  SCL_L();
  d0 = digitalRead(SDA1);

  //d7 = 0;
  //d6 = 0;
  //d5 = 1;
  //d4 = 1;
  //d3 = 0;
  //d2 = 0;
  //d1 = 0;
  //d0 = 0;


  digitalWrite(myled, HIGH); //LED ON  debug

  buf[0] = 'U';//バッファーのクリア
  buf[1] = 0;


  //I2Cスレーブの受信データの表示
  Serial.print(buf);
  Serial.print("\r\n");


  //I2Cスレーブの受信データの表示 debug
  //pc_printf("Read A: %x\r\n", buf[0]);

  digitalWrite(myled, HIGH); //LED OFF  debug


  a[7] = a0;
  a[6] = a1;
  a[5] = a2;
  a[4] = a3;
  a[3] = a4;
  a[2] = a5;
  a[1] = a6;
  a[0] = a7;

  d[7] = d0;
  d[6] = d1;
  d[5] = d2;
  d[4] = d3;
  d[3] = d4;
  d[2] = d5;
  d[1] = d6;
  d[0] = d7;

  //アドレスの表示
  for (ii = 0; ii < 8; ii++) {
    if (ii == 4) Serial.print(": ");

    if (a[ii] == 0) {
      Serial.print("__ ");
    } else {
      Serial.print("[] ");
    }//ebdif
    
  }//for
  Serial.print("\r\n");//リターン


  //データの表示
  for (ii = 0; ii < 8; ii++) {
    if (ii == 4) Serial.print(": ");

    if (d[ii] == 0) {
      Serial.print("__ ");
    } else {
      Serial.print("[] ");
    }//endif
    
  }//for
  Serial.print("\r\n");//リターン

  digitalWrite(myled, LOW); //LED OFF  debug

  delay(500);//0.5秒待つ
  
}//loop







```