[技术问答] I2C_ReadMultiBytesOneReg 源码看不明白。

[复制链接]
 楼主| nbiot 发表于 2019-11-18 18:28 | 显示全部楼层 |阅读模式
I2C_ReadMultiBytesOneReg 源码看不明白。

这中间的执行流程是如何控制的吗?

  1. uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Rdata[], uint32_t u32rLen)
  2. {
  3.     uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
  4.     uint32_t u32rxLen = 0u;

  5.     I2C_START(i2c);                                                /* Send START */
  6.     while(u8Xfering && (u8Err == 0u))
  7.     {
  8.         I2C_WAIT_READY(i2c) {}
  9.         switch(I2C_GET_STATUS(i2c))
  10.         {
  11.             case 0x08u:
  12.                 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));      /* Write SLA+W to Register I2CDAT */
  13.                 u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
  14.                 break;
  15.             case 0x18u:                                             /* Slave Address ACK */
  16.                 I2C_SET_DATA(i2c, u8DataAddr);                     /* Write Lo byte address of register */
  17.                 break;
  18.             case 0x20u:                                             /* Slave Address NACK */
  19.             case 0x30u:                                             /* Master transmit data NACK */
  20.                 u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
  21.                 u8Err = 1u;
  22.                 break;
  23.             case 0x28u:
  24.                 u8Ctrl = I2C_CTL_STA_SI;                         /* Send repeat START */
  25.                 break;
  26.             case 0x10u:
  27.                 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
  28.                 u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
  29.                 break;
  30.             case 0x40u:                                             /* Slave Address ACK */
  31.                 u8Ctrl = I2C_CTL_SI_AA;                          /* Clear SI and set ACK */
  32.                 break;
  33.             case 0x48u:                                             /* Slave Address NACK */
  34.                 u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
  35.                 u8Err = 1u;
  36.                 break;
  37.             case 0x50u:
  38.                 au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
  39.                 if(u32rxLen < (u32rLen - 1u))
  40.                 {
  41.                     u8Ctrl = I2C_CTL_SI_AA;                      /* Clear SI and set ACK */
  42.                 }
  43.                 else
  44.                 {
  45.                     u8Ctrl = I2C_CTL_SI;                         /* Clear SI */
  46.                 }
  47.                 break;
  48.             case 0x58u:
  49.                 au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
  50.                 u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
  51.                 u8Xfering = 0u;
  52.                 break;
  53.             case 0x38u:                                             /* Arbitration Lost */
  54.             default:                                               /* Unknow status */
  55.                 u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
  56.                 u8Err = 1u;
  57.                 break;
  58.         }
  59.         I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
  60.     }
  61.     return u32rxLen;                                               /* Return bytes length that have been received */
  62. }
zhuotuzi 发表于 2019-11-18 20:15 | 显示全部楼层
不知道啊,看看手册怎么说这个功能的吧,一般不追究库函数怎么实现。
空中白云 发表于 2019-11-18 20:47 来自手机 | 显示全部楼层
这个是用芯片内部的i2c模块,每次操作都相当于一个命令,通过读写i2c模块的寄存器完成,优点是cpu占用小,缺点是出问题不好查找,现在的i2c设备的速度都很好,通过io操作也很快
 楼主| nbiot 发表于 2019-11-19 08:38 | 显示全部楼层
空中白云 发表于 2019-11-18 20:47
这个是用芯片内部的i2c模块,每次操作都相当于一个命令,通过读写i2c模块的寄存器完成,优点是cpu占用小, ...

我就是想用这个硬件IIC,不知有人理解它吗?知道如何修改吗?
玛尼玛尼哄 发表于 2019-11-19 13:35 | 显示全部楼层
我只会用I2C做个简单的。
jiekou001 发表于 2019-11-22 19:52 | 显示全部楼层
不知道谁写的,这段代码,很难懂的样子。
zhifeng 发表于 2019-11-25 08:24 | 显示全部楼层
I2c  驱动,厂家根本没考虑 出错处理?  比如:
#define I2C_WAIT_READY(i2c)     while(!((i2c)->CTL0 & I2C_CTL0_SI_Msk))

__STATIC_INLINE void I2C_STOP(I2C_T *i2c)
{

    (i2c)->CTL0 |= (I2C_CTL0_SI_Msk | I2C_CTL0_STO_Msk);
    while(i2c->CTL0 & I2C_CTL0_STO_Msk)
    {
    }
}

一旦出错,就死这里了
zhifeng 发表于 2019-11-25 08:29 | 显示全部楼层
官方的代码例子不敢恭维。都使用 中断了,主函数中还是死循环,不能将控制器交给cpu。不知开这个中断有何意义?
tianxj01 发表于 2019-11-25 10:09 | 显示全部楼层
zhifeng 发表于 2019-11-25 08:24
I2c  驱动,厂家根本没考虑 出错处理?  比如:
#define I2C_WAIT_READY(i2c)     while(!((i2c)->CTL0 & I2 ...

当年STM8的官方硬件,害死多少人?
最后基本上大家全部废弃官方库,直接编软IIC。毛病也是出在类似的问题上,我记得STM8的好像出在ACK上。
各家官方的这些硬件驱动函数,有问题的不在少数,用起来真的必须小心,各种测试,发现有莫名其妙的挂起,则动手修改之。
ayb_ice 发表于 2019-11-25 10:45 | 显示全部楼层
我从不用硬件IIC,SPI也基本不用硬件
manufact 发表于 2019-11-25 16:44 | 显示全部楼层
硬件IIC做不好的话很容易有坑在里面
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:QQ 2419286292

82

主题

181

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部