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++;
}