• I2C协议


    I2C协议解析

    基本概述

    I2C是一种串行总线,使用主从架构。

    • 只需要SCL(串行时钟线)和SDA(串行数据线)两条总线,两条线都需要上拉电阻
    • 所有组件之间都存在简单的主从关系,连接到总线的每个设备均可以通过唯一地址进行软件寻址
    • 最大设备数无限制,最大从机数理论上是127(7位地址数据)

    传输协议

    在这里插入图片描述
    开始信号、7个地址位、1个读写位、1个应答位、8个数据位、1个应答位、结束信号
    开始条件和停止条件
    在这里插入图片描述

    • 开始条件:SCL为高时,拉低SDA
    • 停止条件:SCL为高时,拉高SDA
      当主设备发送开始条件信号之后,所有从机设备即使处于睡眠模式,也会变为活动状态,并等待接收地址位
      数据传输
      在这里插入图片描述
      在这里插入图片描述

    传输格式

    • 传输的数据总共有8位,由发送方设置,先发送数据的高地址,发送完8位数据后,接收方在第9个时钟会紧跟一个ACK位,成功接收为0,否则保持为1。以此往复,直到数据完全传输为止。
    • 谁发送数据谁就驱动SDA线,由于上拉电阻的存在,默认是高电平,谁驱动谁就拉低SDA的电平
    • 发送数据时,SDA的电平在SCL的低电平处变化,在高电平时接接收方读取数据
    • ACK为高时,会引起主设备发生重启或者停止

    软件模拟I2C协议

    Bool Panel_i2c_Start( void )
    {
        Set_Panel_I2C_SDA();
        Set_Panel_I2C_SCL();
        Panel_i2c_Delay();
        if( Panel_I2C_SDALo() || Panel_I2C_SCLLo() )
            return FALSE;
        Clr_Panel_I2C_SDA();
        Panel_i2c_Delay();
        Clr_Panel_I2C_SCL();
        Panel_i2c_Delay();
        return TRUE;
    }
    
    Bool Panel_i2c_SendByte( BYTE value )
    {
        BYTE i;
        Bool result;
    
        for( i = 0; i < 8; i++ ) // Send data via i2c pin
        {
            if( value & BIT7 )
             Set_Panel_I2C_SDA();
            else
             Clr_Panel_I2C_SDA();
            Panel_i2c_Delay();
            Set_Panel_I2C_SCL();
            Panel_i2c_Delay();
            value <<= 1;
            Clr_Panel_I2C_SCL();
        }
        Set_Panel_I2C_SDA();
        Panel_i2c_Delay();
        result = Panel_Wait_i2C_Ack();
        Set_Panel_I2C_SCL();
        Panel_i2c_Delay();
        Clr_Panel_I2C_SCL();
        Panel_i2c_Delay();
        Clr_Panel_I2C_SDA();
    
        return result;
    }
    
    Bool Panel_Wait_i2C_Ack( void )
    {
        BYTE i;
        for( i = 0; i < 5; i++ )
        {
            if( Panel_I2C_SDALo() )
                return TRUE;
            Panel_i2c_Delay();
        }
    
        if( Panel_I2C_SDALo() )
            return TRUE;
        else
            return FALSE;
    }
    
    void Panel_i2c_Stop( void )
    {
        // SCL=L, SDA=L, Stop condition.
        Clr_Panel_I2C_SCL();
        Clr_Panel_I2C_SDA();
        Panel_i2c_Delay();
        Set_Panel_I2C_SCL();
        Panel_i2c_Delay();
        Set_Panel_I2C_SDA();
        Panel_i2c_Delay();
    }
    
    • 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
    Bool Panel_i2c_AccessStart(BYTE SlaveAdr, Panel_I2cIoTransType trans_t)
    {
        BYTE Dummy; // loop dummy
    
        if (trans_t == PANEL_I2C_TRANS_READ) // check i2c read or write
            SlaveAdr = PANEL_I2C_DEVICE_ADR_READ(SlaveAdr); // read
        else
            SlaveAdr = PANEL_I2C_DEVICE_ADR_WRITE(SlaveAdr); // write
    
        Dummy = PANEL_I2C_ACCESS_DUMMY_TIME;
        while (Dummy--)
        {
            if (Panel_i2c_Start() == FALSE)
            {
                Panel_i2c_Stop();
                continue;
            }
    
            if (Panel_i2c_SendByte(SlaveAdr) == TRUE) // check acknowledge
                return TRUE;
    
            Panel_i2c_Stop();
    
            ForceDelayNVRAM(1);
        }
    
        return FALSE;
    }
    
    
    • 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
    void i2cBurstWriteBytes(BYTE SlaveAdr, BYTE *pBuf, BYTE bufLen)
    {
        BYTE Dummy; // loop dummy
        Dummy = I2C_ACCESS_DUMMY_TIME;
        whlie(Dummy--)
        {
            if(Panel_i2c_AccessStart(SlaveAdr, PANEL_I2C_TRANS_WRITE) == FALS)
                continue;
            whlie(buflen--)
            {
                Panel_i2c_SendByte(*pBuf); // send byte
                pBuf++; // next byte pointer
            }
            break;
        }
        Panel_i2c_Stop();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    时钟同步和仲裁

  • 相关阅读:
    不花冤枉钱~希喂、小米、霍尼韦尔宠物空气净化器性价比之战!
    如何成为一名全职创作者——程序员篇
    小程序中如何设置所服务地区的时区
    78. 子集、90. 子集 II、491. 递增子序列
    AIGC|从革新内容创作到社会共识建立,迎接全新技术维度
    Scrum框架中的Sprint
    KaiwuDB 受邀亮相 2023 中国国际“软博会”
    用于 Python 降维的主成分分析
    【网络安全】Docker部署DVWA靶机环境
    夺走的第一份工作竟是OpenAI CEO?
  • 原文地址:https://blog.csdn.net/weixin_45093118/article/details/126467374