美文网首页
模拟I2C驱动

模拟I2C驱动

作者: WilliamChou | 来源:发表于2023-02-05 13:58 被阅读0次

    基于具体平台实现基础接口

    void delay(void)
    {
        // TO-DO: delay
        // volatile uint32_t count = 5U;
        // while(count > 0)
        // {
        //     count--;
        // }
    }
    
    #define SW_I2C_DELAY()          delay()
    
    #define SW_SW_I2C_SCL_INIT()    //TO-DO: scl pin init
    #define SW_I2C_SCL_IN()         //TO-DO: set scl pin as input
    #define SW_I2C_SCL_OUT()        //TO-DO: set scl pin as output
    #define SW_I2C_SCL_H()          //TO-DO: set scl pin to high
    #define SW_I2C_SCL_L()          //TO-DO: set scl pin to low
    
    #define SW_SW_I2C_SDA_INIT()    //TO-DO: sda pin init
    #define SW_I2C_SDA_IN()         //TO-DO: set sda pin as input
    #define SW_I2C_SDA_OUT()        //TO-DO: set sda pin as output
    #define SW_I2C_SDA_H()          //TO-DO: set sda pin to high
    #define SW_I2C_SDA_L()          //TO-DO: set sda pin to low
    #define SW_I2C_SDA_IS_H()       //TO-DO: get sda pin level
    

    I2C基础时序实现

    void sw_i2c_init(void)
    {
        SW_SW_I2C_SDA_INIT();
        SW_SW_I2C_SCL_INIT();
    
        SW_I2C_SCL_OUT();
        SW_I2C_SDA_OUT();
    
        SW_I2C_SCL_H();
        SW_I2C_SDA_H(); 
    }
    
    void sw_i2c_start(void)
    {
        SW_I2C_SDA_OUT(); 
        SW_I2C_SCL_OUT();
    
        SW_I2C_SDA_H(); 
        SW_I2C_SCL_H();
        SW_I2C_DELAY();
    
        SW_I2C_SDA_L();
        SW_I2C_DELAY();
        SW_I2C_SCL_L();
    }
    
    void sw_i2c_stop(void)
    {
        SW_I2C_SDA_OUT();
    
        SW_I2C_SDA_L();
        SW_I2C_DELAY();
    
        SW_I2C_SCL_H();
        SW_I2C_DELAY();
    
        SW_I2C_SDA_H();
    }
    
    void sw_i2c_tx_ack(void)
    {
        SW_I2C_SDA_OUT();
    
        SW_I2C_SDA_L();
        SW_I2C_DELAY();
    
        SW_I2C_SCL_H();
        SW_I2C_DELAY();
    
        SW_I2C_SCL_L();
    }
    
    void sw_i2c_tx_nack(void)
    {
        SW_I2C_SDA_OUT();
    
        SW_I2C_SDA_H();
        SW_I2C_DELAY();
    
        SW_I2C_SCL_H();
        SW_I2C_DELAY();
    
        SW_I2C_SCL_L();
    }
    
    uint8_t sw_i2c_rx_ack(void)
    {
        uint8_t ret = 0;
    
        SW_I2C_SDA_IN();    
        SW_I2C_DELAY();
    
        SW_I2C_SCL_H();
        SW_I2C_DELAY();
    
        if (!SW_I2C_SDA_IS_H()) {
            ret = 1;
        }
    
        SW_I2C_SCL_L();
    
        return ret;
    }
    
    void sw_i2c_tx_byte(uint8_t dat)
    {
        uint8_t i = 0;
        uint8_t temp = dat;
    
        SW_I2C_SDA_OUT();
    
        for (i = 0; i < 8; i++) 
        {
            if (temp & 0x80) 
            {
                SW_I2C_SDA_H();
            } 
            else 
            {
                SW_I2C_SDA_L();
            }
            SW_I2C_DELAY();
    
            SW_I2C_SCL_H();
            SW_I2C_DELAY();
    
            SW_I2C_SCL_L();
            temp <<= 1;
        }
    }
    
    uint8_t sw_i2c_rx_byte(void)
    {
        uint8_t i = 0;
        uint8_t dat = 0;
    
        SW_I2C_SDA_IN();
    
        for (i = 0; i < 8; i++) 
        {
            SW_I2C_DELAY();
    
            SW_I2C_SCL_H();
            SW_I2C_DELAY();
            dat <<= 1;
            if (SW_I2C_SDA_IS_H()) 
            {
                dat |= 0x01;
            }
    
            SW_I2C_SCL_L();
        }
    
        return dat;
    }
    

    示例

    根据slave的i2c时序要求,实现读写接口示例如下:

    void sw_i2c_write(uint8_t device_addr, uint16_t reg_addr, uint8_t dat[], uint8_t len)
    {
        uint8_t i = 0;
    
        sw_i2c_start();
        sw_i2c_tx_byte(device_addr & 0xFE);
        sw_i2c_rx_ack();
        sw_i2c_tx_byte((uint8_t)(reg_addr >> 8));
        sw_i2c_rx_ack();
        sw_i2c_tx_byte((uint8_t)(reg_addr & 0xff));
        sw_i2c_rx_ack();
        for(i = 0; i < len; i++)
        {
            sw_i2c_tx_byte(dat[i]);
            sw_i2c_rx_ack();
        }
        sw_i2c_stop();
    }
    
    void sw_i2c_read(uint8_t device_addr, uint16_t reg_addr, uint8_t dat[], uint8_t len)
    {
        uint8_t i = 0;
    
        sw_i2c_start();
        sw_i2c_tx_byte(device_addr & 0xFE);
        sw_i2c_rx_ack();
        sw_i2c_tx_byte((uint8_t)(reg_addr >> 8));
        sw_i2c_rx_ack();
        sw_i2c_tx_byte((uint8_t)(reg_addr & 0xff));
        sw_i2c_rx_ack();
    
        sw_i2c_start();
        sw_i2c_tx_byte(device_addr | 0x01);
        sw_i2c_rx_ack();
        for(i = 0; i < len; i++)
        {
            dat[i] = sw_i2c_rx_byte();
            if(i == (len-1))
            {
                sw_i2c_tx_nack();
            }
            else
            {
                sw_i2c_tx_ack();
            }
        }
        sw_i2c_stop();
    }
    

    相关文章

      网友评论

          本文标题:模拟I2C驱动

          本文链接:https://www.haomeiwen.com/subject/qxaahdtx.html