I2Cバスの読み書き
I2C(Inter-Integrated Circuit)は2線式のシリアルインターフェースです。アイ・スクエアード・シーと読みます。
デジタルセンサーなどの接続に I2C バスが使用されます。
基本API
サンプル等で用いられる SMBus.c をプロジェクトに含めて使用します。SMBus.c 中で定義されている関数で良くつかわれるものを紹介します。
vSMBusInit
I2Cバスの初期化を行います。I2C バスの速度の設定もこの関数内部で行っています。
void vSMBusInit()
- 引数、戻り値ともにありません。
以下のように vAHI_SiMasterConfigure() が呼び出されており、その第3引数の値によりクロックが決まります。
vAHI_SiMasterConfigure(TRUE, FALSE, 47); // 16/[(PreScaler + 1) x 5]MHz // -- 31:100KHz, 7:400KHz, 47:66Khz
bSMBusWrite
I2Cバスに書き込みを行います。任意のバイト数のデータ部を含めることができます。
bool_t bSMBusWrite(uint8 u8Address, uint8 u8Command, uint8 u8Length, uint8* pu8Data)
- u8Address : I2Cアドレス
- u8Command : I2Cコマンド
- u8Length : 書き出しバイト数 (0 なら、付随データなし)
- pu8Data : u8Length の指定長のデータを持つ領域へのポインタ (データなしなら NULL)
- 戻り値 : TRUE(通信が成功した), FALSE(通信が失敗した)
bSMBusSequentialRead
I2Cバスから読み出しを行います。読み出しバイト数を指定します。
bool_t bSMBusSequentialRead(uint8 u8Address, uint8 u8Length, uint8* pu8Data)
- u8Address : I2Cアドレス
- u8Command : I2Cコマンド
- u8Length : 読み出しバイト数
- pu8Data : データ領域へのポインタ
- 戻り値 : TRUE(通信が成功した), FALSE(通信が失敗した)
BH1715 センサーの例
ここでは、API 手続きを簡素化した SMBus.c SMBus.h を使用した参考コードを示します。参考コードでは RoHM 社のI2Cデジタル照度センサーBH1715FVCの値を読み取ります。
参考コードを使用した場合、センサーデータの読み出し手続きは以下となります。
- vSMBusInit() を呼び出す(I2C機能を有効化する)
- bBH1715reset() を呼び出す(初期化コマンドなどはBH1715のデータシート参照)
- bBH1715startRead() を呼び出す
- 24ms 待つ。時間待ちは、ループによる時間消費 vSleepLoop() やタイマーなどを使用します。
- i16BH1715readResult() を呼び出す。
戻り値がセンサーlx値の1/5。
// RoHM BH1715FVC (I2C light sensor) #define BH1715_ADDRESS (0x23) #define BH1715_TRIG (0x23) #define BH1715_SOFT_RST (0x07) #define BH1715_CONVTIME (24+2) // 24ms MAX #define BH1715_DATA_NOTYET (-32768) #define BH1715_DATA_ERROR (-32767) /**************************************************************************** * * NAME: bBH1715reset * * DESCRIPTION: * to reset BH1715 device * * RETURNS: * bool_t fail or success * ****************************************************************************/ PUBLIC bool_t bBH1715reset() { bool_t bOk = TRUE; bOk &= bSMBusWrite(BH1715_ADDRESS, BH1715_SOFT_RST, 0, NULL); // then will need to wait at least 15ms return bOk; } /**************************************************************************** * * NAME: bBH1715startRead * * DESCRIPTION: * to start a read of the light sensor. * NOTE: it takes 24ms to finish conversion, then results can be read. * * RETURNS: * bool_t fail or success * ****************************************************************************/ PUBLIC bool_t bBH1715startRead() { bool_t bOk = TRUE; // start conversion (will take some ms according to bits accuracy) bOk &= bSMBusWrite(BH1715_ADDRESS, BH1715_TRIG, 0, NULL); return bOk; } /**************************************************************************** * * NAME: u16BH1715readResult * * DESCRIPTION: * Read the light value. * * RETURNS: * int16: 0~10000(approx): [1:=5lx], 100 means 500lx. * SENSOR_TAG_DATA_ERROR: error * * NOTES: * the data conversion fomula is : * ReadValue / 1.2 [LUX] * ****************************************************************************/ PUBLIC int16 i16BH1715readResult() { bool_t bOk = TRUE; int32 i32result; uint8 au8data[4]; bOk &= bSMBusSequentialRead(BH1715_ADDRESS, 2, au8data); if (bOk == FALSE) { i32result = SENSOR_TAG_DATA_ERROR; } else { i32result = ((au8data[0] << 8) | au8data[1]); i32result = (i32result * 10 + 30) / 60; // i32result/1.2/5 } return (int16)i32result; } /**************************************************************************** * * NAME: vSleepLoop * * DESCRIPTION: * * waiting by looping. * ****************************************************************************/ PRIVATE void vSleepLoop(uint32 c) { static volatile uint32 u32ct = 0; while(c-- > 0) u32ct++; }