I2C使用实例
本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。
本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下:
本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。
说明: 本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。
示例如下:
#include "i2c_if.h" /* I2C标准接口头文件 */
#include "gpio_if.h" /* GPIO标准接口头文件 */
#include "hdf_log.h" /* 标准日志打印头文件 */
#include "osal_io.h" /* 标准IO读写接口头文件 */
#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */
/* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */
struct TpI2cDevice {
uint16_t rstGpio; /* 复位管脚 */
uint16_t busId; /* I2C总线号 */
uint16_t addr; /* I2C设备地址 */
uint16_t regLen; /* 寄存器字节宽度 */
DevHandle i2cHandle; /* I2C控制器句柄 */
};
/* I2C管脚io配置,需要查阅SOC寄存器手册 */
#define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */
#define I2C3_CLK_REG_ADDR 0x112f0090 /* 3号I2C控制器SCL管脚配置寄存器地址 */
#define I2C_REG_CFG 0x5f1 /* 3号I2C控制器SDA及SCL管脚配置值 */
static void TpSocIoCfg(void)
{
/* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */
OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR));
OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR));
}
/* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20ms, 完成复位动作 */
static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice)
{
int32_t ret;
/* 设置复位管脚方向为输出 */
ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret);
return ret;
}
ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret);
return ret;
}
OsalMSleep(20);
ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set rst low fail!:%d", __func__, ret);
return ret;
}
OsalMSleep(50);
ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set rst high fail!:%d", __func__, ret);
return ret;
}
OsalMSleep(20);
return HDF_SUCCESS;
}
/* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */
static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr,
unsigned char *regData, unsigned int dataLen, uint8_t flag)
{
int index = 0;
unsigned char regBuf[4] = {0};
struct I2cMsg msgs[2] = {0};
/* 单双字节寄存器长度适配 */
if (tpDevice->regLen == 1) {
regBuf[index++] = regAddr & 0xFF;
} else {
regBuf[index++] = (regAddr >> 8) & 0xFF;
regBuf[index++] = regAddr & 0xFF;
}
/* 填充I2cMsg消息结构 */
msgs[0].addr = tpDevice->addr;
msgs[0].flags = 0; /* 标记为0,表示写入 */
msgs[0].len = tpDevice->regLen;
msgs[0].buf = regBuf;
msgs[1].addr = tpDevice->addr;
msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */
msgs[1].len = dataLen;
msgs[1].buf = regData;
if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) {
HDF_LOGE("%s: i2c read err", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
/* TP寄存器读函数 */
static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
unsigned char *regData, unsigned int dataLen)
{
return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1);
}
/* TP寄存器写函数 */
static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
unsigned char *regData, unsigned int dataLen)
{
return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0);
}
/* I2C例程总入口 */
static int32_t TestCaseI2c(void)
{
int32_t i;
int32_t ret;
unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC };
unsigned char bufRead[7] = {0};
static struct TpI2cDevice tpDevice;
/* IO管脚功能配置 */
TpSocIoCfg();
/* TP设备信息初始化 */
tpDevice.rstGpio = 3;
tpDevice.busId = 3;
tpDevice.addr = 0x38;
tpDevice.regLen = 1;
tpDevice.i2cHandle = NULL;
/* GPIO管脚初始化 */
ret = TestCaseGpioInit(&tpDevice);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: gpio init fail!:%d", __func__, ret);
return ret;
}
/* 打开I2C控制器 */
tpDevice.i2cHandle = I2cOpen(tpDevice.busId);
if (tpDevice.i2cHandle == NULL) {
HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId);
return -1;
}
/* 向TP-IC的0xD5寄存器连续写7字节数据 */
ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret);
I2cClose(tpDevice.i2cHandle);
return -1;
}
OsalMSleep(10);
/* 从TP-IC的0xDO寄存器连续读7字节数据 */
ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
I2cClose(tpDevice.i2cHandle);
return -1;
}
HDF_LOGE("%s: tp i2c write&read reg success!", __func__);
for (i = 0; i < 7; i++) {
HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]);
}
/* 访问完毕关闭I2C控制器 */
I2cClose(tpDevice.i2cHandle);
return ret;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
你好,我是用的是小熊派,编译时在最后报错,屏蔽掉下面就没有一点问题了
IMUupdate(Angle_gx,Angle_gy,Angle_gz,Angle_ax,Angle_ay,Angle_az);
想请教一下大神这是怎么回事啊