单片机驱动-软件模拟I2C

一、数据格式

  1、读数据:

  2、写数据:

二、I2C时序图

  1、读写时序图:

 

三、软件实现

  1、开始

  在SCL处于高电平的状态时,SDA产生一个下降沿信号;

/*
 *@brief i2c Start
 *@author Mr.W
 *@date 2020-8-3
 */
static void i2c_start(void)
{
    I2C_SDA_SET;
    i2c_delay(5);
    I2C_SCL_SET;
    i2c_delay(5);
    I2C_SDA_CLR;
    i2c_delay(5);
    I2C_SCL_CLR;
    i2c_delay(5);
}

  2、停止

  在SCL处于高电平的状态时,SDA产生一个上升沿信号;

/*
 *@brief i2c Stop
 *@author Mr.W
 *@date 2020-8-3
 */
static void i2c_stop(void)
{
    I2C_SCL_CLR;
    i2c_delay(5);
    I2C_SDA_CLR;
    i2c_delay(5);
    I2C_SCL_SET;
    i2c_delay(5);
    I2C_SDA_SET;
    i2c_delay(5);
}

  3、等待响应信号

  如果等到响应信号SDA电平信号由高电平变成低电平,否则未等到响应信号;

/*
 *@brief i2c Wait Acknowledge
 *@author Mr.W
 *@date 2020-8-3
 */
static uint8_t i2c_wait_ack(void)
{
    I2C_SDA_SET;
    i2c_delay(5);
    I2C_SCL_SET;
    i2c_delay(5);
    if(I2C_PIN_SDA)
    {
        i2c_stop();
        return 0;
    }
    I2C_SCL_CLR;
    return  1; 
}

  4、发送响应

/*
 *@brief i2c Send Acknowledge
 *@author Mr.W
 *@date 2020-8-3
 */
static void i2c_send_ack(void)
{
    I2C_SDA_CLR;
    i2c_delay(5);
    I2C_SCL_SET;
    i2c_delay(5);
    I2C_SCL_CLR;    
}

  5、发送未响应

/*
 *@brief i2c Send No Acknowledge
 *@author Mr.W
 *@date 2020-8-3
 */
static void i2c_send_noack(void)
{
    I2C_SDA_SET;
    i2c_delay(5);
    I2C_SCL_SET;
    i2c_delay(5);
    I2C_SCL_CLR;    
}

  6、发送数据

  发送一个字节数据;

/*
 *@brief i2c Send Data
 *@author Mr.W
 *@date 2020-8-3
 */
static void i2c_send_data(uint8_t data)
{
    uint8_t i = 8;
    
    while(i--)
    {
        I2C_SCL_CLR;
        i2c_delay(10);
        if(data & 0x80)
        {
            I2C_SDA_SET;
        }         
        else
        {
            I2C_SDA_CLR;
        }
        
        i2c_delay(5);
        data <<= 1;
        I2C_SCL_SET;
        i2c_delay(5);
        I2C_SCL_CLR;
        i2c_delay(5);
    }    
}

  7、接收数据

  接收一个字节数据;

/*
 *@brief i2c Receive Data
 *@author Mr.W
 *@date 2020-8-3
 */
static uint8_t i2c_receive_data(void)
{
    uint8_t i = 8;
    uint8_t data = 0;
    
    I2C_SDA_SET;
    while(i--)
    {
        data <<= 1;
        I2C_SCL_CLR;
        i2c_delay(5);
        I2C_SCL_SET;
        i2c_delay(5);
        if(I2C_PIN_SDA) 
            data |= 0x01;
    }
    I2C_SCL_CLR;
    
    return data;    
}

  8、读多个数据

/*
 *@brief Read Data
 *@author Mr.W
 *@date 2020-8-3
 */
uint8_t ReadNByte(uint8_t sla, uint16_t suba, uint8_t *pdata, uint16_t num)
{
    uint8_t i;
    
    i2c_start();
    i2c_send_data(sla);
    if(i2c_wait_ack() == 0)
    {
        i2c_stop();
        return 0;
    }
    i2c_send_data(suba);
    if(i2c_wait_ack() == 0)
    {
        i2c_stop();
        return 0;
    }
    
    i2c_start();
    i2c_send_data(sla|0x01);
    if(i2c_wait_ack() == 0)
    {
        i2c_stop();
        return 0;
    }
    for(i = 0; i < num; i++)
    {
        *pdata++ = i2c_receive_data();
        if(i < (num - 1))
            i2c_send_ack();
    }
    i2c_send_noack();
    i2c_stop();
    
    return 1;    
}

  9、写多个数据

/*
 *@brief Write Data
 *@author Mr.W
 *@date 2020-8-3
 */
uint8_t WriteNByte(uint8_t sla, uint16_t suba, uint8_t *pdata, uint16_t num)
{
    uint8_t i;
    
    i2c_start();
    i2c_send_data(sla);
    if(i2c_wait_ack() == 0)
    {
        i2c_stop();
        return 0;
    }
    i2c_send_data(suba);
    if(i2c_wait_ack() == 0)
    {
        i2c_stop();
        return 0;
    }

    for(i = 0; i < num; i++)
    {
        i2c_send_data(*pdata++);
        if(i2c_wait_ack() == 0)
        {
            i2c_stop();
            return 0;
        }
    }
    i2c_stop();
    
    return 1;
}

#end

原文地址:https://www.cnblogs.com/wenhao-Web/p/13434533.html