ESP32 软件I2C

一、概述

        1.1 I2C简介

                I2C(Inter-Integrated Circuit)是一种串行通信总线,由飞利浦公司在1980年代为了让主机连接其它外设而定制的一种低速通信协议,目前广泛应用于手机、电脑、家电等嵌入式设备。

图1.0 典型的I2C总线(挂载多个从设备)

         1.2 电气特性

                I2C使用两根数据总线,一根是数据线(SDA),一根是时钟线(SCL),采用双向漏极开路,并使用电阻进行上拉,I2C允许比较大的工作电压范围,但一般采用3.3V或者5V。设备地址使用7位长度和10位长度。I2C 传输速率有不同的模式:

                ·标准模式:100Kbit/s

                ·快速模式:400Kbit/s

                ·高速模式:3.4Mbit/s

图1.1 I2C内部结构图

                 1.3 I2C 协议层  

                        1.3.1 I2C读写帧格式

 图1.2 I2C写一个字节数据

 图1.3 I2C读一个字节数据

                         1.3.2 I2C起始信号

                                当主机要与从机开始通信时需要发送起始信号,SCL线在高电平时,SDA线由高变为低。一般流程是拉高SCL线与SDA线保持4us,再拉低SDA线保持4us,最后拉低SCL。

图1.4 I2C起始信号

                         1.3.3 I2C停止信号

                                当主机要与从机结束通信时需要发送停止信号,SCL线在高电平时,SDA线由低变为高。一般流程是拉低SCL线和SDA线保持4us,再拉高SCL线和SDA线保持4us。

 图1.5 I2C停止信号

                         1.3.4 I2C应答信号

                                应答信号也相当于一位数据,SCL为高时,数据线拉低,表示为应答。

图1.6 I2C应答信号 

                         1.3.5 I2C非应答信号 

                                非应答信号也相当于一位数据,SCL为高时,数据线拉高,表示为非应答。

 图1.7 I2C非应答信号

                         1.3.6 I2C数据

                                数据的传输格式,高位先发,SCL为高时数据有效,SCL为低时数据变化。

 图1.8 一个字节数据传输示例

二、程序

        源文件

#include "bsp_iic.h"
#include "esp_log.h"
#include "unistd.h"

static const char *TAG = "I2C";

void I2cInit(void)
{
	const gpio_config_t   io_config = {
        .intr_type      = GPIO_INTR_DISABLE,
        .mode           = GPIO_MODE_OUTPUT,
        .pull_down_en   = GPIO_PULLDOWN_DISABLE,
        .pull_up_en     = GPIO_PULLUP_ENABLE,
        .pin_bit_mask   = (1ULL << I2C_SCL_PIN) 
                        | (1ULL << I2C_SDA_PIN) 
    };
    gpio_config(&io_config);
	I2C_SDA_HIGH;
	I2C_SCL_HIGH;
}

esp_err_t I2cSdaIn(void)
{
	const gpio_config_t   io_config = {
        .intr_type      = GPIO_INTR_DISABLE,
        .mode           = GPIO_MODE_INPUT,
        .pull_down_en   = GPIO_PULLDOWN_DISABLE,
        .pull_up_en     = GPIO_PULLUP_ENABLE,
        .pin_bit_mask   = (1ULL << I2C_SDA_PIN) 
    };
    return gpio_config(&io_config);
}

esp_err_t I2cSdaOut(void)
{
	const gpio_config_t   io_config = {
        .intr_type      = GPIO_INTR_DISABLE,
        .mode           = GPIO_MODE_OUTPUT,
        .pull_down_en   = GPIO_PULLDOWN_DISABLE,
        .pull_up_en     = GPIO_PULLUP_ENABLE,
        .pin_bit_mask   = (1ULL << I2C_SDA_PIN) 
    };
    return gpio_config(&io_config);
}


void I2cStart(void)
{
	I2cSdaOut();
	I2C_SDA_HIGH;
	I2C_SCL_HIGH;
	usleep(4);
	I2C_SDA_LOW;
	usleep(4);
	I2C_SCL_LOW;
}

void I2cStop(void)
{
	I2cSdaOut();
	I2C_SCL_LOW;
	I2C_SDA_LOW;
	usleep(4);
	I2C_SCL_HIGH;
	I2C_SDA_HIGH;
	usleep(4);
}

uint8_t I2cWaitAck(void)
{
	uint8_t ErrTime = 0;

	I2C_SDA_HIGH;
	usleep(1);
	I2cSdaIn();
	I2C_SCL_HIGH;
	usleep(1);
	while(I2C_SDA == 1)
	{
		ErrTime++;
		if(ErrTime > 200)
		{
			I2cStop();
			return 1;
		}
	}
	I2C_SCL_LOW;
	return 0;
}

void I2cAck(void)
{
	I2cSdaOut();
	I2C_SCL_LOW;
	I2C_SDA_LOW;
	usleep(2);
	I2C_SCL_HIGH;
	usleep(2);
	I2C_SCL_LOW;
}

void I2cNack(void)
{
	I2cSdaOut();
	I2C_SCL_LOW;
	I2C_SDA_HIGH;
	usleep(2);
	I2C_SCL_HIGH;
	usleep(2);
	I2C_SCL_LOW;
}

void I2cWriteByte(uint8_t Data)
{
    uint8_t i;

    I2cSdaOut();
    I2C_SCL_LOW;
    for(i = 0;i < 8;i++)
    {
		if((Data & 0x80) >> 7)
		{
			I2C_SDA_HIGH;
		}
		else
		{
			I2C_SDA_LOW;
		}
		Data <<= 1;
		usleep(2);
		I2C_SCL_HIGH;
		usleep(2);
		I2C_SCL_LOW;
		usleep(2);
    }
}

uint8_t I2cReadByte(uint8_t isAck)
{
	uint8_t i;
	uint8_t Data = 0x0;

	I2cSdaIn();

    for(i = 0;i < 8;i++)
	{
    	I2C_SCL_LOW;
    	usleep(2);
		I2C_SCL_HIGH;
		Data <<= 1;
        if(I2C_SDA == 1)
		{
        	Data++;
		}
        usleep(1);
    }
    if(isAck)
	{
    	I2cNack();
	}
    else
	{
		I2cAck();
	}
    return Data;
}

void EspI2cWriteByte(uint8_t dev_addr,uint8_t reg_addr,uint8_t write_data)
{
	I2cStart();
	I2cWriteByte((dev_addr << 1) | I2C_MASTER_WRITE);
	I2cWaitAck();
	I2cWriteByte(reg_addr);
	I2cWaitAck();
	I2cWriteByte(write_data);
	I2cWaitAck();
	I2cStop();
}

void EspI2cReadByte(uint8_t dev_addr,uint8_t reg_addr,uint8_t *read_data)
{
	I2cStart();
	I2cWriteByte((dev_addr << 1) | I2C_MASTER_WRITE);
	I2cWaitAck();
	I2cWriteByte(reg_addr);
	I2cWaitAck();

	I2cStart();
	I2cWriteByte((dev_addr << 1) | I2C_MASTER_READ);
	*read_data = I2cReadByte(NACK_VAL);
	I2cStop();
}

void EspI2cWriteBytes(uint8_t dev_addr,uint8_t reg_addr,uint8_t *write_data,uint8_t write_len)
{
	uint8_t i;

	I2cStart();

	I2cWriteByte((dev_addr << 1) | I2C_MASTER_WRITE);
	I2cWaitAck();

	I2cWriteByte(reg_addr);
	I2cWaitAck();

    for(i = 0;i < write_len;i++)
    {
		I2cWriteByte(write_data[i]);
		I2cWaitAck();
    }
	I2cStop();
}

void EspI2cReadBytes(uint8_t dev_addr,uint8_t reg_addr,uint8_t *read_data,uint8_t read_len)
{
    uint8_t i = 0;

	I2cStart();

	I2cWriteByte((dev_addr << 1) | I2C_MASTER_WRITE);
	I2cWaitAck();

	I2cWriteByte(reg_addr);
	I2cWaitAck();

	I2cStart();
	I2cWriteByte((dev_addr << 1) | I2C_MASTER_READ);
	I2cWaitAck();

	if(read_len > 1)
	{
		for(i = 0;i < read_len - 1;i++)
		{
			read_data[i] = I2cReadByte(ACK_VAL);
		}
	}
	read_data[i] = I2cReadByte(NACK_VAL);

	I2cStop();
}

void I2cDetect(void)
{
	uint8_t i;
	uint8_t j;
    uint8_t address;
	uint8_t ret = 0;

    printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\r\n");
    for(i = 0;i < 128;i += 16) 
	{
        printf("%02x: ", i);
        for (j = 0;j < 16;j++) 
		{
            fflush(stdout);
            address = i + j;

			I2cStart();
			I2cWriteByte((address << 1) | I2C_MASTER_WRITE);
			ret = I2cWaitAck();
			I2cStop();
			
            if(ret == 0) 
			{
                printf("%02x ",address);
            } 
			else 
			{
                printf("-- ");
            }
        }
        printf("\r\n");
    }
}

        头文件

#ifndef _BSP_IIC_H_
#define _BSP_IIC_H_

#include "sdkconfig.h"
#include "driver/gpio.h"
#include "driver/i2c.h"

#define ACK_VAL                 0x0        
#define NACK_VAL                0x1       
#define ACK_CHECK_EN            0x1     
#define ACK_CHECK_DIS           0x0                                                                                       

#define ESP32_GPIO_OUT_W1TS(gpio_num)       GPIO.out_w1ts =  (0x01 << gpio_num)                 //gpio_num:0 ~ 31    GPIO OUT HIGH
#define ESP32_GPIO_OUT_W1TC(gpio_num)       GPIO.out_w1tc = (0x01 << gpio_num)                  //gpio_num:0 ~ 31    GPIO OUT LOW

#define ESP32_GPIO_OUT1_W1TS(gpio_num)      GPIO.out1_w1ts.data =  (0x01 << (gpio_num - 32))    //gpio_num:32 ~ 39   GPIO OUT HIGH
#define ESP32_GPIO_OUT1_W1TC(gpio_num)      GPIO.out1_w1tc.data = (0x01 << (gpio_num - 32))     //gpio_num:32 ~ 39   GPIO OUT LOW

#define ESP32_GPIO_IN(gpio_num)             ((GPIO.in >> gpio_num) & 0x1)                        //gpio_num:0 ~ 31    GPIO IN VALUE
#define ESP32_GPIO_IN1(gpio_num)            ((GPIO.in1.data  >> gpio_num) & 0x1)                 //gpio_num:32 ~ 39   GPIO IN VALUE

#define GpioReadBit(gpio_num)	            ESP32_GPIO_IN(gpio_num)
                                            
#define GpioSetBit(gpio_num)			     if(gpio_num < 32)\
                                                ESP32_GPIO_OUT_W1TS(gpio_num);\
                                            else\
                                                ESP32_GPIO_OUT1_W1TS(gpio_num); 

#define GpioResetBit(gpio_num)		        if(gpio_num < 32)\
                                                ESP32_GPIO_OUT_W1TC(gpio_num);\
                                            else\
                                                ESP32_GPIO_OUT1_W1TC(gpio_num); 

#define I2C_SCL_PIN                         GPIO_NUM_4      
#define I2C_SDA_PIN                         GPIO_NUM_5 

#define I2C_SDA_HIGH                        GpioSetBit  (I2C_SDA_PIN)	  
#define I2C_SDA_LOW                         GpioResetBit(I2C_SDA_PIN)

#define I2C_SCL_HIGH                        GpioSetBit  (I2C_SCL_PIN)
#define I2C_SCL_LOW                         GpioResetBit(I2C_SCL_PIN)

#define I2C_SDA                             GpioReadBit (I2C_SDA_PIN)

// #define I2C_SDA				                gpio_get_level(I2C_SDA_PIN)

void I2cInit(void);

void I2cStart(void);

void I2cStop(void);

uint8_t I2cWaitAck(void);

void I2cAck(void);

void I2cNack(void);

void I2cWriteByte(uint8_t Data);

uint8_t I2cReadByte(uint8_t isAck);

void EspI2cWriteByte(uint8_t dev_addr,
                     uint8_t reg_addr,
                     uint8_t write_data);

void EspI2cReadByte(uint8_t dev_addr,
                    uint8_t reg_addr,
                    uint8_t *read_data);

void EspI2cWriteBytes(uint8_t dev_addr,
                      uint8_t reg_addr,
                      uint8_t *write_data,
                      uint8_t write_len);   

void EspI2cReadBytes(uint8_t dev_addr,
                     uint8_t reg_addr,
                     uint8_t *read_data,
                     uint8_t read_len);  
					 
void I2cDetect(void);                    

#endif
  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值