打印
[技术问答]

I2C_ReadMultiBytesOneReg 源码看不明白。

[复制链接]
997|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nbiot|  楼主 | 2019-11-18 18:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2C_ReadMultiBytesOneReg 源码看不明白。

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

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

    I2C_START(i2c);                                                /* Send START */
    while(u8Xfering && (u8Err == 0u))
    {
        I2C_WAIT_READY(i2c) {}
        switch(I2C_GET_STATUS(i2c))
        {
            case 0x08u:
                I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));      /* Write SLA+W to Register I2CDAT */
                u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
                break;
            case 0x18u:                                             /* Slave Address ACK */
                I2C_SET_DATA(i2c, u8DataAddr);                     /* Write Lo byte address of register */
                break;
            case 0x20u:                                             /* Slave Address NACK */
            case 0x30u:                                             /* Master transmit data NACK */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;
            case 0x28u:
                u8Ctrl = I2C_CTL_STA_SI;                         /* Send repeat START */
                break;
            case 0x10u:
                I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
                u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
                break;
            case 0x40u:                                             /* Slave Address ACK */
                u8Ctrl = I2C_CTL_SI_AA;                          /* Clear SI and set ACK */
                break;
            case 0x48u:                                             /* Slave Address NACK */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;
            case 0x50u:
                au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
                if(u32rxLen < (u32rLen - 1u))
                {
                    u8Ctrl = I2C_CTL_SI_AA;                      /* Clear SI and set ACK */
                }
                else
                {
                    u8Ctrl = I2C_CTL_SI;                         /* Clear SI */
                }
                break;
            case 0x58u:
                au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Xfering = 0u;
                break;
            case 0x38u:                                             /* Arbitration Lost */
            default:                                               /* Unknow status */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;
        }
        I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
    }
    return u32rxLen;                                               /* Return bytes length that have been received */
}

使用特权

评论回复
沙发
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,不知有人理解它吗?知道如何修改吗?

使用特权

评论回复
5
玛尼玛尼哄| | 2019-11-19 13:35 | 只看该作者
我只会用I2C做个简单的。

使用特权

评论回复
6
jiekou001| | 2019-11-22 19:52 | 只看该作者
不知道谁写的,这段代码,很难懂的样子。

使用特权

评论回复
7
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)
    {
    }
}

一旦出错,就死这里了

使用特权

评论回复
8
zhifeng| | 2019-11-25 08:29 | 只看该作者
官方的代码例子不敢恭维。都使用 中断了,主函数中还是死循环,不能将控制器交给cpu。不知开这个中断有何意义?

使用特权

评论回复
9
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上。
各家官方的这些硬件驱动函数,有问题的不在少数,用起来真的必须小心,各种测试,发现有莫名其妙的挂起,则动手修改之。

使用特权

评论回复
10
ayb_ice| | 2019-11-25 10:45 | 只看该作者
我从不用硬件IIC,SPI也基本不用硬件

使用特权

评论回复
11
manufact| | 2019-11-25 16:44 | 只看该作者
硬件IIC做不好的话很容易有坑在里面

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:QQ 2419286292

82

主题

181

帖子

3

粉丝