ESP32とPICをI2Cで繋いでみる(その2)PICにデータを転送

今日はESP32をマスター、PICをスレーブ としてESP32からPICにデータを転送してみます。💪

ESP32からデータを転送して、そのデータ値でLEDを点滅させたいと思います。

I2Cの通信規格はネットで調べるとたくさん出て来るので、今回は省略しますね。

1、回路図

ポイントとしてはSCK、SDAのプルアップ抵抗は必ず入れて下さい。4.7kΩ程度で良いと思います。

スクリーンショット 2020-12-19 9.15.00

2、PIC側のプログラム

Arduinoのwire.begin()という訳にはいかないですね。I2Cの動作に関わるレジスタを設定して動作させています。

マスターから通信が自分の設定したアドレス(下記であれば0x07)であればデータ受信を開始します。データが送られて来ると割り込みが掛かるので、割り込み処理で受信データをバッファに格納していきます。

もっと高級なCPUだとFIFOを持っていて受信データをある程度溜め込んでくれるのでポーリングで受信データを読んでも良いのですが、PICはFIFOがないので割り込みで処理で自前のバッファにデータを格納していきます。

格納バッファにはリングバッファという手法を使い、データの読み込みが遅れても消えないようにしています。ソフトウェアFIFOというところでしょうか。

割り込みで使用するグローバル変数はvolatileで定義します。volatileは変数のアドレスを固定するためリロケータブルにはなりません。

割り込み処理で使用する変数を参照するときは、割り込み禁止をかけてバッファの内容が不意に書き換えられないようにしています。

通信データについは、0x55、0xaaとしています。この値は通信を評価する際によく使用されるデータで2進数だと0b01010101、0b10101010になります。

シリアル通信の場合、このように01が交互に出現するデータで評価すると、クロックとのタイミングを評価するときに良いです。またオシロで波形をみる際にも見やすいです。



#include <xc.h>

//I2C関連
#define rcvBuffSize 16
volatile short rcvCnt=0;
volatile short readCnt=0;
volatile char rcvData[rcvBuffSize];

void interrupt InterI2C( void )
{

    if (SSP1IF == 1) {  // I2C割込み発生?
        //受信時の処理
         if (!(SSP1STAT & 0b00000100)) { //SSP1STAT R/W(受信?)
              if (!(SSP1STAT & 0b00100000)) {//SSP1START D/A(アドレス?))
                   // 受信バイトがアドレス時の処理
              char     dummy = SSP1BUF ;       // アドレスデータを空読み
              //受信データがデータの時の処理
              } else {
                   // データ受信リングバッファに格納
                   rcvData[rcvCnt] = SSP1BUF ; // データを読込む
                   rcvCnt ++;
                   if(rcvCnt >= rcvBuffSize){rcvCnt=0;}                    
              }
              
              SSP1IF = 0 ;             // 割込みフラグクリア
              SSP1CON1 = SSP1CON1 | 0b00010000;  // SCLラインをオン
         
         }
        
    }  
}
void main(void) {
   OSCCON = 0b01110000;  //clock set16MHz PLLEN=ON 32MHz
   TRISA =  0B00001110;   //I2Cで使うポートはINPUT

//I2C
    SSP1STAT= 0b10000000 ;   // 標準速度モード(100kHz)
    SSP1CON1= 0b00100110 ;   // スレーブモード
    SSP1CON2bits.SEN = 1 ;   // SCL制御
    SSP1ADD = 0x07 << 1     ;   // アドレス0x07
    SSP1MSK = 0b11111110 ;   // アドレスマスクデータ
    SSP1IF = 0 ;             // SSP割り込みフラグをクリア
    SSP1IE = 1 ;             // SSP割り込みを許可
    PEIE   = 1 ;             // 周辺装置割り込みを許可
    GIE    = 1 ;             // 全割り込み処理を許可す

    char data;
    PORTA = 0b00000000;
    while(1){
         GIE    = 0 ;             // 全割り込み禁止
        if(rcvCnt != readCnt){
        
           //リングバッファからのデータの取り出し
           data = rcvData[readCnt];
                   readCnt ++;
                   if(readCnt >= rcvBuffSize){readCnt=0;}           
                    
        }
          GIE    = 1 ;             // 全割り込み処理許可
          
                   if(data == 0x55) PORTA = 0b00100000;
                   if(data == 0xaa) PORTA = 0b00000000;        
        
    }
             
 } 
   


3、ESP32側のプログラム

こちらは慣れ親しんだwire.bigin()で😃

なんかホッとしますね!

#include <Wire.h>
void setup() {
 Serial.begin(115200);
 Wire.begin(21,22);//define(SDA,SCL)
}
void loop() {
 
 Wire.beginTransmission(0x07);
 Wire.write(0x55);
 Wire.endTransmission();
 delay(1000);
 
 Wire.beginTransmission(0x08);
 Wire.write(0xaa);
 Wire.endTransmission();
 delay(1000);
}

下記は動作している動画です。

点滅はESP32からの送信データでやってます。💯


ワイヤレス通信の実験が多かったけど、高速で信頼性の高い通信はやっぱりワイヤー接続の通信ですね。I2Cでも数メートルの引き回しはできます。😙

次回はPICからESP32にデータを送信してみたいと思います。

では🤚



この記事が気に入ったらサポートをしてみませんか?