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)

bSMBusSequentialRead

I2Cバスから読み出しを行います。読み出しバイト数を指定します。

bool_t bSMBusSequentialRead(uint8 u8Address, uint8 u8Length, uint8* pu8Data)

 

BH1715 センサーの例

ここでは、API 手続きを簡素化した SMBus.c SMBus.h を使用した参考コードを示します。参考コードでは RoHM 社のI2Cデジタル照度センサーBH1715FVCの値を読み取ります。

参考コードを使用した場合、センサーデータの読み出し手続きは以下となります。


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