2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ESP32学習 platformIo+ESPIDF "I2C master"通信

Last updated at Posted at 2024-03-11

ESP-IDF I2C driver master mode

IMG_4436.JPG
(左)I2C 16bits IOExpander MCP23017, (右)I2C 8bits IOexpander PCF8574
I2Cdriverの動作確認で、使用しました。
MCP23017初期値.png
I2C経由で、MCP23017のレジスタを読み込んで、シリアル出力。

<参照>

環境
VScode+platformIO
platform = espressif32
board = my_esp32dev
framework = espidf
※ボードは、esp32devを修正した自作JSONファイル。

I2C driver API関数

I2C driver 初期化API

esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
Configure an I2C bus with the given configuration.

Parameters
i2c_num – I2C port to configure
i2c_conf – Pointer to the I2C configuration

Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error

I2C driver ドライバーインストールAPI

esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode,
size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags)
Install an I2C driver.

Parameters
i2c_num – I2C port number
mode – I2C mode (either master or slave).
slv_rx_buf_len – Receiving buffer size. Only slave mode will use this value, it is ignored in master mode.
slv_tx_buf_len – Sending buffer size. Only slave mode will use this value, it is ignored in master mode.
intr_alloc_flags – Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.

Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
ESP_FAIL Driver installation error

I2C master 書き込みAPI

esp_err_t i2c_master_write_to_device(i2c_port_t i2c_num, uint8_t device_address, const uint8_t *write_buffer, size_t write_size, TickType_t ticks_to_wait)
Perform a write to a device connected to a particular I2C port. This function is a wrapper to i2c_master_start(), i2c_master_write(), i2c_master_read(), etc… It shall only be called in I2C master mode.

Parameters
i2c_num – I2C port number to perform the transfer on
device_address – I2C device’s 7-bit address
write_buffer – Bytes to send on the bus
write_size – Size, in bytes, of the write buffer
ticks_to_wait – Maximum ticks to wait before issuing a timeout.

Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
ESP_FAIL Sending command error, slave hasn’t ACK the transfer.
ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
ESP_ERR_TIMEOUT Operation timeout because the bus is busy.

I2C driver リスタート読み出しAPI

esp_err_t i2c_master_write_read_device(i2c_port_t i2c_num, uint8_t device_address, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, TickType_t ticks_to_wait)

Perform a write followed by a read to a device on the I2C bus. A repeated start signal is used between the write and read, thus, the bus is not released until the two transactions are finished. This function is a wrapper to i2c_master_start(), i2c_master_write(), i2c_master_read(), etc… It shall only be called in I2C master mode.

Parameters
i2c_num – I2C port number to perform the transfer on
device_address – I2C device’s 7-bit address
write_buffer – Bytes to send on the bus
write_size – Size, in bytes, of the write buffer
read_buffer – Buffer to store the bytes received on the bus
read_size – Size, in bytes, of the read buffer
ticks_to_wait – Maximum ticks to wait before issuing a timeout.

Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
ESP_FAIL Sending command error, slave hasn’t ACK the transfer.
ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
ESP_ERR_TIMEOUT Operation timeout because the bus is busy.

kconfig.projbuild
menu "Example Configuration"

    config I2C_MASTER_SCL
        int "SCL_GPIO_Num"
        range 0 39
        default 19
        help 
            GPIO number for I2C Master clock line.

    config I2C_MASTER_SDA
        int "SDA_GPIO_Num"
        range 0 39
        default 18
        help
            GPIO number for I2C Master data line.

    config GPIO_OUTPUT_0
        int "GPIO output pin 0"
        range 0 39
        default 32
        help
            GPIO pin number to be used as GPIO_OUTPUT_IO_0.

    config GPIO_OUTPUT_1
        int "GPIO output pin 1"
        range 0 39
        default 33
        help
            GPIO pin number to be used as GPIO_OUTPUT_IO_1.

    config GPIO_INPUT_0
        int "GPIO input pin 0"
        range 0 39
        default 34
        help
            GPIO pin number to be used as GPIO_INPUT_IO_0.

    config GPIO_INPUT_1
        int "GPIO input pin 1"
        range 0 39
        default 35
        help
            GPIO pin number to be used as GPIO_INPUT_IO_1.

endmenu
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "sdkconfig.h"
#include "esp_log.h"

static const char *TAG = "i2c_simple-example";

#define PCF8574_ADDRESS             0x25
#define MCP23017_ADDRESS            0x26
#define I2C_MASTER_SCL_IO           CONFIG_I2C_MASTER_SCL
#define I2C_MASTER_SDA_IO           CONFIG_I2C_MASTER_SDA
#define I2C_MASTER_NUM              0
#define I2C_MASTER_FREQ_HZ          400000
#define I2C_MASTER_TX_BUF_DISABLE   0
#define I2C_MASTER_RX_BUF_DISABLE   0
#define I2C_MASTER_TIMEOUT_MS       1000


void mcp23017_init(uint8_t _add);
void mcp23017_write(uint8_t add, uint8_t reg, uint8_t data);
uint8_t mcp23017_read(uint8_t add, uint8_t reg);

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = 
    {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE,0);

}



void app_main()
{
    int ret;
    uint8_t txBuf[2];
    uint8_t data[2];

    //I2C0 initialize
    ESP_ERROR_CHECK(i2c_master_init());
    //i2cDevice MCP23017 initialize
    mcp23017_init(MCP23017_ADDRESS);
    for(int i=0; i<=0x0A; i++)
    {        
        i2c_master_write_read_device(I2C_MASTER_NUM,MCP23017_ADDRESS, &i, 1, data, 1, I2C_MASTER_TIMEOUT_MS/portTICK_PERIOD_MS);
        printf("[%02X]:%X\n", i,data[0]);
    }

    for(int i=0x10; i<=0x1A; i++)
    {        
        i2c_master_write_read_device(I2C_MASTER_NUM,MCP23017_ADDRESS, &i, 1, data, 1, I2C_MASTER_TIMEOUT_MS/portTICK_PERIOD_MS);
        printf("[%02X]:%X\n", i,data[0]);
    }

    //LED点滅
    while(1)
    {
        uint8_t write_buf = 0x55;
        ret = i2c_master_write_to_device(I2C_MASTER_NUM, PCF8574_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
        mcp23017_write(MCP23017_ADDRESS,0x0A,0xAA);
        mcp23017_write(MCP23017_ADDRESS,0x1A,0xAA);
        vTaskDelay(500/portTICK_PERIOD_MS);

        write_buf = 0xAA;
        ret = i2c_master_write_to_device(I2C_MASTER_NUM, PCF8574_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
        mcp23017_write(MCP23017_ADDRESS,0x0A,0x55);
        mcp23017_write(MCP23017_ADDRESS,0x1A,0x55);
        vTaskDelay(500/portTICK_PERIOD_MS);
    }
}


/// @brief MCP23017 16bits IOexpander initializing
/// @param add I2C slave address
void mcp23017_init(uint8_t add)
{
    uint8_t write_buf[2] = {0x05,0xA8};
    uint8_t readbuf;

    //Control Register(0x05) Check @BANK = 1
    i2c_master_write_read_device(I2C_MASTER_NUM, MCP23017_ADDRESS,
                &write_buf,1,&readbuf,1,I2C_MASTER_TIMEOUT_MS/ portTICK_PERIOD_MS);
    
    if(readbuf!=0xA8)
    {//BANK == 0
        printf("[05]:%X\n",readbuf);
        write_buf[0]=0x0A;
        write_buf[1]=0xA8;

        i2c_master_write_to_device(I2C_MASTER_NUM, MCP23017_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    }

    //PORTA IO direction
    write_buf[0]=0x00;
    write_buf[1]=0x00;
    i2c_master_write_to_device(I2C_MASTER_NUM, MCP23017_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    //PORTB IO direction
    write_buf[0]=0x10;
    write_buf[1]=0x00;
    i2c_master_write_to_device(I2C_MASTER_NUM, MCP23017_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

/// @brief MCP23017 I2C 16bits IOexpander Write the register
/// @param add i2c Slave address
/// @param reg mcp23017 regster address
/// @param data writing data
void mcp23017_write(uint8_t add, uint8_t reg, uint8_t data)
{
    uint8_t write_buf[2];
    write_buf[0]=reg;
    write_buf[1]=data;
    i2c_master_write_to_device(I2C_MASTER_NUM, MCP23017_ADDRESS, &write_buf, sizeof(write_buf), 
                                            I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

IMG_4437.JPG

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?