今回の目的
PMODコネクタ経由で何かI2C方式のセンサを制御したいということで、定番の温湿度センサBME280のボードを接続してデータを取り込みました。
最初通信がうまくいかずAnalog Discovery2を買って波形確認などしたのですが、単にPMRレジスタのPSEL設定ミスでした。修正後無事にデータが取り込めましたので、簡単に設定について記録します。
情報収集
BOSCH様のデータシートを入手してアドレスやレジスタ構成を確認しました。
https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
直接通信には使用しないCSBとSDO端子ですが、データシートの記述通り
- CSB…通信方式の選択、VCCレベル入力でI2C
- SDO…VCCかGNDかでデバイスアドレスの末尾が"1","0"と変わる
ためブレッドボードで固定が必要でした。
プログラムのフローはGR-CITRUSで動作された例の紹介がありましたので、こちらを参考にさせて頂きました。
https://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-citrus/5659/gr-citrus-bme280
ただしKitの開発環境はArduino.hが現状使えませんので、Wire.やSerial.といった関数を自分で作成する必要がありました。
コーディング
PMOD2で簡易I2Cを制御するため下記の初期設定を行います。
//I2C PMOD2
int i2c_init(void) {
int i;
//Port Settings
MPC.PWPR.BYTE = 0x00; //B0WI=0
MPC.PWPR.BYTE = 0x40; //PFS Write Enable
PORT9.PMR.BIT.B0 = 1; //P90:peripheral
PORT9.PMR.BIT.B2 = 1; //P92:peripheral
PORT9.ODR0.BIT.B0 = 1; //P90:NchOpenDrain (ODR0.B0!)
PORT9.ODR0.BIT.B4 = 1; //P92:NchOpenDrain (ODR0.B4!)
MPC.P90PFS.BYTE = 0x0A; //P90:SSDA7 (PSEL=0A!)
MPC.P92PFS.BYTE = 0x0A; //P92:SSCL7 (PSEL=0A!)
//for I2C
SYSTEM.MSTPCRB.BIT.MSTPB24 = 0; //SCI7(I2C)
SCI7.SCR.BYTE = 0x00; //TE=0,RE=0 (At the same time)
SCI7.SIMR3.BYTE = 0xF0; //SSDA,SSCL:Hiz
SCI7.SMR.BYTE = 0x00; //CKS[1:0]=00b
SCI7.SCMR.BYTE = 0xFA; //SDIR=1:MSB first (I2C)
//SCI7.BRR = 0x33; //19200bps:32MHz,1:1 (51.08d)
SCI7.BRR = 0x09; //100000bps:32MHz,1:1 N=((32*10^6)/(64*2^(-1)*100000))-1 = 9(dec)
//SCI7.SEMR.BYTE = 0x00;
SCI7.SEMR.BIT.NFEN = 1; //ノイズ除去フィルタあり
//SCI7.SNFR.BIT.NFCS=1; //1分周のクロックをノイズフィルタに使用
SCI7.SNFR.BYTE = 0x01; //1分周のクロックをノイズフィルタに使用
//for (i=0;i<1000;i++) {} //wait
//SCI7.SSR.BYTE = 0x00; //status clear
SCI7.SIMR1.BIT.IICM=1; //簡易I2Cモード
SCI7.SIMR1.BIT.IICDL=1; //SCLから1サイクル遅れてSDAを変化させる
SCI7.SIMR2.BIT.IICACKT=1; //NACK送信またはACK/NACK受信
SCI7.SIMR2.BIT.IICCSC=1; //クロック同期を行う(スレーブからのクロックストレッチを受け入れる)
SCI7.SIMR2.BIT.IICINTM=1; //0:ACK/NACK INterrrupt、1:送受信割込み
SCI7.SPMR.BYTE=0; //SPI Stop
SCI7.SCR.BYTE |= 0x30; //TIE=0,RIE=0,TE=1,RE=1
return 0;
}
SCI7がPMOD2に割り当てられていて、簡易I2Cの接続は
- P90/SMOSI7がSSDA7
- P92/SMOSI7がSSCL7
となります。
I2Cの送受信とも前回のISL29034制御のプログラムと同じで問題ありませんでした。
BME280のPOR発行や制御レジスタの設定を初期化ルーチンで最初の一度のみ行います。Wire関数が使えませんのでsend関数に渡します。
...
send_i2c( BME280_REGISTER_SOFTRESET, 0xB6 );
//delay( 300 );
for(i=0;i<300;i++);
send_i2c( BME280_REGISTER_CONTROLHUMID, ctrl_hum_reg);
send_i2c( BME280_REGISTER_CONTROL, ctrl_meas_reg);
send_i2c( BME280_REGISTER_CONFIG, config_reg);
...
Readも原始的ですが1バイトづつ読んで配列に入れています。
for (i=0;i<8;i++){
data[i] = recv_i2c((BME280_REGISTER_PRESSUREDATA + i), 1);
//ee_printf("READ:data[%d]..%lu\n",i,data[i]);
}
BME280はNACKの発行の仕方次第でバースト転送も可能ということで、そのうち挑戦しようと思います。
上記参考サイトの製品がRX63系ということもあり、キャリブレーションの関数等はそのままでもコンパイルが通りました。
実行の結果が下記です。ESP32の結果との相関も確認できましたので、PMOD2経由でのI2C制御も出来たということになります。
感想
動いてしまえばなんということもないのですが、PMRの記述ミスに気付かずESP32-DevkitCで動作確認したりAnalogDiscovery2のロジアナ機能で波形を見たりと少し遠回りしました。
やはり、
- インターネット上での動作報告やサンプルコードが豊富なArduino環境
- 波形を確認する手段
があるとだいぶ違いますね。
スマートコンフィギュレータやFITの使い方もそろそろ覚えたいです。