I2C使用实例

本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。

本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下:

  • SOC:hi3516dv300
  • Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。
  • 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO

本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其某某个内部寄存器进行随机读写,测试I2C通路是否正常。

I2C使用实例 - 图1 说明: 本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。

示例如下:


1. #include "i2c_if.h"          /* I2C标准接口头文件 */
2. #include "gpio_if.h"         /* GPIO标准接口头文件 */
3. #include "hdf_log.h"         /* 标准日志打印头文件 */
4. #include "osal_io.h"         /* 标准IO读写接口头文件 */
5. #include "osal_time.h"       /* 标准延迟&睡眠接口头文件 */

7. /* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */
8. struct TpI2cDevice {
9. uint16_t rstGpio;             /* 复位管脚 */
10. uint16_t busId;               /* I2C总线号 */
11. uint16_t addr;                /* I2C设备地址 */
12. uint16_t regLen;              /* 寄存器字节宽度 */
13. struct DevHandle *i2cHandle;  /* I2C控制器句柄 */
14. };

16. /* I2C管脚io配置,需要查阅SOC寄存器手册  */
17. #define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */
18. #define I2C3_CLK_REG_ADDR 0x112f0090  /* 3号I2C控制器SCL管脚配置寄存器地址 */
19. #define I2C_REG_CFG 0x5f1             /* 3号I2C控制器SDA及SCL管脚配置值 */

21. static void TpSocIoCfg(void)
22. {
23. /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */
24. OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR));
25. OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR));
26. }

28. /* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20s, 完成复位动作 */
29. static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice)
30. {
31. int32_t ret;

33. /* 设置复位管脚方向为输出 */
34. ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT);
35. if (ret != HDF_SUCCESS) {
36. HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret);
37. return ret;
38. }

40. ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
41. if (ret != HDF_SUCCESS) {
42. HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret);
43. return ret;
44. }
45. OsalMSleep(20);

47. ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW);
48. if (ret != HDF_SUCCESS) {
49. HDF_LOGE("%s: set rst low fail!:%d", __func__, ret);
50. return ret;
51. }
52. OsalMSleep(50);

54. ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
55. if (ret != HDF_SUCCESS) {
56. HDF_LOGE("%s: set rst high fail!:%d", __func__, ret);
57. return ret;
58. }
59. OsalMSleep(20);

61. return HDF_SUCCESS;
62. }

64. /* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */
65. static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr,
66. unsigned char *regData, unsigned int dataLen, uint8_t flag)
67. {
68. int index = 0;
69. unsigned char regBuf[4] = {0};
70. struct I2cMsg msgs[2] = {0};

72. /* 单双字节寄存器长度适配 */
73. if (tpDevice->regLen == 1) {
74. regBuf[index++] = regAddr & 0xFF;
75. } else {
76. regBuf[index++] = (regAddr >> 8) & 0xFF;
77. regBuf[index++] = regAddr & 0xFF;
78. }

80. /* 填充I2cMsg消息结构 */
81. msgs[0].addr = tpDevice->addr;
82. msgs[0].flags = 0; /* 标记为0,表示写入 */
83. msgs[0].len = tpDevice->regLen;
84. msgs[0].buf = regBuf;

86. msgs[1].addr = tpDevice->addr;
87. msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */
88. msgs[1].len = dataLen;
89. msgs[1].buf = regData;

91. if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) {
92. HDF_LOGE("%s: i2c read err", __func__);
93. return HDF_FAILURE;
94. }
95. return HDF_SUCCESS;
96. }

98. /* TP寄存器读函数 */
99. static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
100. unsigned char *regData, unsigned int dataLen)
101. {
102. return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1);
103. }

105. /* TP寄存器写函数 */
106. static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr,
107. unsigned char *regData, unsigned int dataLen)
108. {
109. return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0);
110. }

112. /* I2C例程总入口 */
113. static int32_t TestCaseI2c(void)
114. {
115. int32_t i;
116. int32_t ret;
117. unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC };
118. unsigned char bufRead[7] = {0};
119. static struct TpI2cDevice tpDevice;

121. /* IO管脚功能配置 */
122. TpSocIoCfg();

124. /* TP设备信息初始化 */
125. tpDevice.rstGpio = 3;
126. tpDevice.busId = 3;
127. tpDevice.addr = 0x38;
128. tpDevice.regLen = 1;
129. tpDevice.i2cHandle = NULL;

131. /* GPIO管脚初始化 */
132. ret = TestCaseGpioInit(&tpDevice);
133. if (ret != HDF_SUCCESS) {
134. HDF_LOGE("%s: gpio init fail!:%d", __func__, ret);
135. return ret;
136. }

138. /* 打开I2C控制器 */
139. tpDevice.i2cHandle = I2cOpen(tpDevice.busId);
140. if (tpDevice.i2cHandle == NULL) {
141. HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId);
142. return -1;
143. }

145. /* 向TP-IC的0xD5寄存器连续写7字节数据 */
146. ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7);
147. if (ret != HDF_SUCCESS) {
148. HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret);
149. I2cClose(tpDevice.i2cHandle);
150. return -1;
151. }
152. OsalMSleep(10);

154. /* 从TP-IC的0xDO寄存器连续读7字节数据 */
155. ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7);
156. if (ret != HDF_SUCCESS) {
157. HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
158. I2cClose(tpDevice.i2cHandle);
159. return -1;
160. }

162. HDF_LOGE("%s: tp i2c write&read reg success!", __func__);
163. for (i = 0; i < 7; i++) {
164. HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]);
165. }

167. /* 访问完毕关闭I2C控制器 */
168. I2cClose(tpDevice.i2cHandle);
169. return ret;
170. }