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"/* 标准延迟&睡眠接口头文件 */
  6. /* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */
  7. structTpI2cDevice{
  8. uint16_t rstGpio;/* 复位管脚 */
  9. uint16_t busId;/* I2C总线号 */
  10. uint16_t addr;/* I2C设备地址 */
  11. uint16_t regLen;/* 寄存器字节宽度 */
  12. structDevHandle*i2cHandle;/* I2C控制器句柄 */
  13. };
  14. /* I2C管脚io配置,需要查阅SOC寄存器手册 */
  15. #define I2C3_DATA_REG_ADDR 0x112f008c/* 3号I2C控制器SDA管脚配置寄存器地址 */
  16. #define I2C3_CLK_REG_ADDR 0x112f0090/* 3号I2C控制器SCL管脚配置寄存器地址 */
  17. #define I2C_REG_CFG 0x5f1/* 3号I2C控制器SDA及SCL管脚配置值 */
  18. staticvoidTpSocIoCfg(void)
  19. {
  20. /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */
  21. OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR));
  22. OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR));
  23. }
  24. /* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20s, 完成复位动作 */
  25. staticint32_tTestCaseGpioInit(structTpI2cDevice*tpDevice)
  26. {
  27. int32_t ret;
  28. /* 设置复位管脚方向为输出 */
  29. ret =GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT);
  30. if(ret != HDF_SUCCESS){
  31. HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret);
  32. return ret;
  33. }
  34. ret =GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
  35. if(ret != HDF_SUCCESS){
  36. HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret);
  37. return ret;
  38. }
  39. OsalMSleep(20);
  40. ret =GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW);
  41. if(ret != HDF_SUCCESS){
  42. HDF_LOGE("%s: set rst low fail!:%d", __func__, ret);
  43. return ret;
  44. }
  45. OsalMSleep(50);
  46. ret =GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH);
  47. if(ret != HDF_SUCCESS){
  48. HDF_LOGE("%s: set rst high fail!:%d", __func__, ret);
  49. return ret;
  50. }
  51. OsalMSleep(20);
  52. return HDF_SUCCESS;
  53. }
  54. /* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */
  55. staticintTpI2cReadWrite(structTpI2cDevice*tpDevice,unsignedint regAddr,
  56. unsignedchar*regData,unsignedint dataLen,uint8_t flag)
  57. {
  58. int index =0;
  59. unsignedchar regBuf[4]={0};
  60. struct I2cMsg msgs[2]={0};
  61. /* 单双字节寄存器长度适配 */
  62. if(tpDevice->regLen ==1){
  63. regBuf[index++]= regAddr &0xFF;
  64. }else{
  65. regBuf[index++]=(regAddr >>8)&0xFF;
  66. regBuf[index++]= regAddr &0xFF;
  67. }
  68. /* 填充I2cMsg消息结构 */
  69. msgs[0].addr = tpDevice->addr;
  70. msgs[0].flags =0;/* 标记为0,表示写入 */
  71. msgs[0].len = tpDevice->regLen;
  72. msgs[0].buf = regBuf;
  73. msgs[1].addr = tpDevice->addr;
  74. msgs[1].flags =(flag ==1)? I2C_FLAG_READ :0;/* 添加读标记位,表示读取 */
  75. msgs[1].len = dataLen;
  76. msgs[1].buf = regData;
  77. if(I2cTransfer(tpDevice->i2cHandle, msgs,2)!=2){
  78. HDF_LOGE("%s: i2c read err", __func__);
  79. return HDF_FAILURE;
  80. }
  81. return HDF_SUCCESS;
  82. }
  83. /* TP寄存器读函数 */
  84. staticinlineintTpI2cReadReg(structTpI2cDevice*tpDevice,unsignedint regAddr,
  85. unsignedchar*regData,unsignedint dataLen)
  86. {
  87. returnTpI2cReadWrite(tpDevice, regAddr, regData, dataLen,1);
  88. }
  89. /* TP寄存器写函数 */
  90. staticinlineintTpI2cWriteReg(structTpI2cDevice*tpDevice,unsignedint regAddr,
  91. unsignedchar*regData,unsignedint dataLen)
  92. {
  93. returnTpI2cReadWrite(tpDevice, regAddr, regData, dataLen,0);
  94. }
  95. /* I2C例程总入口 */
  96. staticint32_tTestCaseI2c(void)
  97. {
  98. int32_t i;
  99. int32_t ret;
  100. unsignedchar bufWrite[7]={0xFF,0xFF,0xFF,0xFF,0xA,0xB,0xC};
  101. unsignedchar bufRead[7]={0};
  102. staticstructTpI2cDevice tpDevice;
  103. /* IO管脚功能配置 */
  104. TpSocIoCfg();
  105. /* TP设备信息初始化 */
  106. tpDevice.rstGpio =3;
  107. tpDevice.busId =3;
  108. tpDevice.addr =0x38;
  109. tpDevice.regLen =1;
  110. tpDevice.i2cHandle = NULL;
  111. /* GPIO管脚初始化 */
  112. ret =TestCaseGpioInit(&tpDevice);
  113. if(ret != HDF_SUCCESS){
  114. HDF_LOGE("%s: gpio init fail!:%d", __func__, ret);
  115. return ret;
  116. }
  117. /* 打开I2C控制器 */
  118. tpDevice.i2cHandle = I2cOpen(tpDevice.busId);
  119. if(tpDevice.i2cHandle == NULL){
  120. HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId);
  121. return-1;
  122. }
  123. /* 向TP-IC的0xD5寄存器连续写7字节数据 */
  124. ret =TpI2cWriteReg(&tpDevice,0xD5, bufWrite,7);
  125. if(ret != HDF_SUCCESS){
  126. HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret);
  127. I2cClose(tpDevice.i2cHandle);
  128. return-1;
  129. }
  130. OsalMSleep(10);
  131. /* 从TP-IC的0xDO寄存器连续读7字节数据 */
  132. ret =TpI2cReadReg(&tpDevice,0xD5, bufRead,7);
  133. if(ret != HDF_SUCCESS){
  134. HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
  135. I2cClose(tpDevice.i2cHandle);
  136. return-1;
  137. }
  138. HDF_LOGE("%s: tp i2c write&read reg success!", __func__);
  139. for(i =0; i <7; i++){
  140. HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]);
  141. }
  142. /* 访问完毕关闭I2C控制器 */
  143. I2cClose(tpDevice.i2cHandle);
  144. return ret;
  145. }