PIC18FQ MCC で I2C
PIC18FQ MCC で I2C とは
呪文みたいな表題になってしまったが、ちょっと I2C 通信でトラブったので、そのメモ代わりに書いておく。
MCC とは Microchip Code Cpnfigure といったソフトで、 UI でCPUの周辺動作を規定したり、動かすのに必要なドライバーを書き出してくれるます。 MPLAB-X IDE という 最近の開発環境での付加ソフトなのですが、最近まで使っている古い MPLAB IDE というソフトと違って、簡単にソフトが作れるそうなのですが、内部構造が判りにくくて、資料が少ないことから結構難儀しました。
今回は I2C 関連でのおはなし
i2c1_master_example.c というサンプルコードが生成されるので、見てみると
void I2C1_WriteNBytes(i2c1_address_t address, uint8_t* data, size_t len)
{
while(!I2C1_Open(address)); // バスがBUSYのうちは待っている
I2C1_SetBuffer(data,len); // 書き込むデーターの アドレスと長さ
I2C1_SetAddressNackCallback(NULL,NULL);
//反応無いとき "NACK"の場合の処理 ここでは何もしない
I2C1_MasterWrite(); // 書込処理
while(I2C1_BUSY == I2C1_Close()); // 完了待って STOP 処理
}
これは大体判る。ここにある xxxxCallback という部分がくせもの
ここでの i2c1_address_t address は,7ビットなので、実際送信時は シフトされて RW ビットが追加される。
次は EEPROM読み出しなどに使うアドレス指定書込後、RESTART してデーターを読むようなのだが
void I2C1_ReadDataBlock(i2c1_address_t address, uint8_t reg, uint8_t *data, size_t len)
{
i2c1_buffer_t bufferBlock; // 結果を書き込むバッファを作成
bufferBlock.data = data;
bufferBlock.len = len;
while(!I2C1_Open(address)); // バス開放待ち
I2C1_SetDataCompleteCallback(
rdBlkRegCompleteHandler,&bufferBlock); //ここがキモ
I2C1_SetBuffer(®,1); // 送信するデーター 1バイト
I2C1_SetAddressNackCallback(NULL,NULL);
//反応無いとき "NACK"の場合の処理 ここでは何もしない
I2C1_MasterWrite();
while(I2C1_BUSY == I2C1_Close()); // 完了まで待って STOP 処理
}
ちょっと見ると I2C1_MasterWrite(); だけなので、書き込むだけでどこで読むんだろう?
と思って見てみると I2C1_SetDataCompleteCallback というのがありますね。
DataComplate とあるので、送信が完了した時の動作を指定するところのようです。
この rdBlkRegCompleteHandler というのは、まさに RESTART を送って、データーを読み込む所のようです。
i2c1_buffer_t bufferBlock; と言う物を作って、アドレスと長さを指定します。
このルーチンは、送信時のレジスタ指定が1バイトなので、256バイト以下ならいいですが、大きな EEPROM などでは足りません。
そこで、
(i2c1_address_t address, uint8_t reg, uint8_t *data, size_t len)
....
I2C1_SetBuffer(®,1);
の部分を
(i2c1_address_t address, uint8_t *reg, uint8_t *data, size_t len)
...
I2C1_SetBuffer( reg,2);
と2バイトにして ( uint16_t にしてもいいかな?)
新たな関数を作ってみました。
*結局 MCCの作成する I2C ルーチンは、ステータスを定義して
バスは空いているか?
書き込めるか?
書いたら完了したか?
応答はあったか?
完了したら次はどうするか?
全部終了したか?
STOPで終わる
など、順次実行するもので、ソフト上からはあまり良く判らないのが難点ですね。
そのままだと、相手がいなくても、反応がなくても止まることがないので初心者にはいいかな?
エラー処理をきちんとやろうとすると面倒かも?