I2C Tools Example

[中文]

Note

This document is automatically translated using AI. Please excuse any detailed errors. The official English version is still in progress.

Example Description

This example demonstrates how to initialize and configure the I2C interface, and operate the I2C bus through Console REPL: send commands to the simulated slave in the command line environment, such as reading the value of a specified register, to verify the correctness of I2C bus communication and peripheral interaction.

The example consists of two files:

  • i2ctools_example_main.c: Contains the example entry, used to initialize the I2C bus, start Console REPL, etc.

  • cmd_i2ctools: Contains command registration, used to implement specific I2C command operations, including reading and writing simulated slave registers.

Console REPL

Console REPL (Read–Eval–Print Loop) is a real-time interactive debugging and control interface for embedded systems, which can execute input commands in real time and return results. In the ESP-IDF example, the professional features of Console REPL include:

  • Interactive execution: Allows users to enter commands in the terminal, and the system parses and executes them in real time.

  • Real-time feedback: The command execution results are output in real time, which is convenient for developers to observe the peripheral status and debug the program.

  • Extendable command registration: Supports registering custom command interfaces, such as I2C, SPI, GPIO operation commands, to achieve flexible control of hardware peripherals.

  • Hardware verification and debugging: Provides a means to directly access peripheral registers and bus interfaces, which is convenient for quickly verifying hardware connections and function implementation.

However, it should be noted that command line operations will not automatically recognize device types or register meanings, and users need to confirm register addresses and data formats themselves. For more information, refer to Console Terminal.

Running Method

The complete code of the example can be found in I2C Tools Example. The configuration instructions before running, corresponding GPIO pins, related commands, and build and burn processes can be found in the README.md file in the example directory.

If you need to customize the FAT file system mount path, you can view the Macro Definition/Global Variable Description section and modify the relevant definitions.

Header File Description

The header files used in this example cover system tools, file systems, command line parsing, I2C drivers, and log recording modules, providing support for console tool development, command parsing, I2C communication, and file operations.

The header files are classified by function as follows:

  1. System Tools: Provide standard input and output, string processing, memory management, configuration macro support, FAT file system operation, and log printing functions.

#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_vfs_fat.h"
#include "esp_log.h"

Note

  • sdkconfig.h is used to read the configuration macros generated by the build system, and is only used in the i2ctools_example_main.c file.

  • esp_vfs_fat.h provides FAT file system mount and file operation interfaces, and is only used in the i2ctools_example_main.c file.

  1. Command Line Parsing and Console: Provide command parsing, registration, and interactive console functions.

#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "cmd_system.h"
#include "cmd_i2ctools.h"

Note

  • argtable3/argtable3.h is used to provide command line argument parsing functionality, only used in the cmd_i2ctools.c file.

  • cmd_system.h is used to encapsulate system command registration, only used in the i2ctools_example_main.c file.

  • cmd_i2ctools.h is used to encapsulate I2C tool command registration, only used in the i2ctools_example_main.c file.

  1. I2C Driver: Provides initialization, read/write operations, and resource release functionality in I2C master mode.

#include "driver/i2c_master.h"

Macro Definition/Global Variable Description

The macro definitions and global variables in this example are mainly used to configure the pins, port number, communication frequency, and timeout time of the I2C master, and provide a bus handle for subsequent read/write operations.

They are categorized by function as follows:

  1. I2C Master Configuration: Defined in i2ctools_example_main.c

  • Use configuration macros to define the GPIO pin numbers used by the I2C clock line (SCL) and data line (SDA). In the example, the clock line corresponds to GPIO 4; the data line corresponds to GPIO 5.

static gpio_num_t i2c_gpio_sda = CONFIG_EXAMPLE_I2C_MASTER_SDA;
static gpio_num_t i2c_gpio_scl = CONFIG_EXAMPLE_I2C_MASTER_SCL;
  • Define the port number used by I2C, this example uses I2C_NUM_0, i.e., I2C0 hardware peripheral.

static i2c_port_t i2c_port = I2C_NUM_0;
  1. History Record Storage: Defined in i2ctools_example_main.c

  • When the CONFIG_EXAMPLE_STORE_HISTORY configuration item is enabled, the example will mount the file system and save the command history to a specified file.

#if CONFIG_EXAMPLE_STORE_HISTORY
#define MOUNT_PATH "/data"                        // Mount path
#define HISTORY_PATH MOUNT_PATH "/history.txt"    // History record file path
  1. I2C Communication Parameters: Defined in cmd_i2ctools.c

  • Define the timeout time (ms) for I2C operations. If the operation is not completed within the specified time, a timeout error is returned.

#define I2C_TOOL_TIMEOUT_VALUE_MS (50)
  • Define the I2C communication frequency, set to 100 kHz in the example.

static uint32_t i2c_frequency = 100 * 1000;
  1. I2C Bus Handle: Defined in cmd_i2ctools.c

  • Define the I2C master bus handle, used to save the valid handle returned after successfully creating the bus, for subsequent operations.

i2c_master_bus_handle_t tool_bus_handle;

Note

  • Configuration macros start with CONFIG_, which are automatically generated by the ESP-IDF build system based on the menuconfig settings and saved in the sdkconfig file.

  • When defining GPIO pins, use configuration macros instead of directly writing pin numbers, which allows for flexible modification of pins at compile time without modifying the source code, facilitating project expansion and management.

  • If you want to modify the pins used, just modify the menuconfig and rebuild/compile the example, and it will automatically update, no need to manually change the code.

Task Function Description

In order to interact and debug with I2C bus devices through the command line, this example mainly includes command registration and implementation and auxiliary initialization functions.

Note

The following functions are all defined in cmd_i2ctools.c, used to implement specific I2C operation commands (such as configuring I2C, scanning devices, reading registers, writing registers, dumping registers, etc.) and registered to the console. Users can directly execute these operations through the command line.

Command Registration and Implementation

Command registration function: Used to register console commands to the ESP-IDF console system.

  1. Build a command line parameter structure to set what information the user needs to provide and the format of the information when entering commands in the console.

  • Call arg_int0() to define an optional integer parameter, which can appear 0 or 1 time in the command.

  • Call arg_int1() to define a required integer parameter, which must appear only once in the command.

  • Call arg_intn() to define an integer parameter that appears a specified number of times. Users can customize the minimum and maximum number of times this parameter appears in the command.

  • Call arg_end() to define the parameter end flag. Passing a parameter indicates the maximum number of parsing errors that can be recorded.

The parameter definition of arg_intn() is as follows:

Parameter explanation

Input parameter

Parameter function

Parameter description

shortopts

Short option string

Single-character command line option, can be NULL to indicate not using short options.

longopts

Long option string

Multi-character command line option, can be NULL to indicate not using long options.

datatype

Data type description

String used to generate help information

mincount

Minimum occurrence

The minimum number of times this parameter appears in the command line. Usually 0 or 1.

maxcount

Maximum occurrence

The maximum number of times this parameter appears in the command line.

glossary

Parameter description text

Description text used to generate help information, explaining the function of the parameter.

Note

Both arg_int0() and arg_int1() are implemented based on arg_intn(), which fixed the minimum and maximum occurrences. Therefore, there is no need to pass in the mincount and maxcount parameters when calling, to simplify the calling in common scenarios.

  1. Build the command registration structure esp_console_cmd_t, used to specify the command name, callback function, help information, and parameter structure.

Structure members

Structure member

Member function

Member description

command

Command name

The command name entered by the user in the console.

help

Command information

Briefly describes the purpose of the command, which can be displayed by entering help in the console.

hint

Command hint (optional)

Used to provide parameter format hints.

func

Callback function

The function pointer called when the command is triggered.

argtable

Command parameter structure

Points to the parameter structure, used to parse the parameters entered by the user.

func_w_context

Callback function with context

Used when the callback function needs to access external context, such as needing to pass in additional structures or states.

context

Context pointer

Points to any user-defined data structure, passed into func_w_context, accessible in the callback function.

Note

  • func and func_w_context are mutually exclusive, only one needs to be registered for the callback.

  • context is only valid when using func_w_context, it can carry additional data or state required for command execution.

  • Through this mechanism, the command callback function can be executed independently, or access external state, achieving more flexible command handling.

  1. Call esp_console_cmd_register() to register the command, making it usable in the console. For further explanation and parameter passing, refer to Console Terminal API.

Register Callback Function: Called when the user inputs a command, reads the values in the parameter structure and performs the corresponding operation.

Parameter Explanation

Input Parameter

Parameter Function

Parameter Description

argc

Number of command line parameters

Passed in by the system, indicating the number of parameters in the argv array.

argv

Command line parameter array

Passed in by the system, containing the command name and the various options and values input by the user.

Change I2C Bus Configuration

Define Parameter Structure

i2cconfig_args is a command line parameter structure used to define and save the parameters provided by the user when entering the i2cconfig command in the console.

Structure Members

Input Parameter

Parameter Function

Parameter Description

port

I2C port number

Used to parse the --port option, indicating the I2C port to be configured.

freq

I2C communication frequency

Used to parse the --freq option, indicating the configured communication frequency, in Hz.

sda

I2C data line pin

Used to parse the --sda option, indicating the GPIO number used by SDA.

scl

I2C clock line pin

Used to parse the --scl option, indicating the GPIO number used by SCL.

end

Parameter end flag

Used to mark the end of the parameter list and save parsing error information.

Register Command

register_i2cconfig() is used to register the i2cconfig command in the ESP-IDF console, allowing users to dynamically modify the I2C bus parameter configuration (port number, frequency, and SDA/SCL pins) through the command line.

  1. Define the command line parameter structure, i.e., the input structure of the command:

  • Optional parameters: port and freq.

  • Required parameters: sda and scl.

  • Allows recording of up to 2 parsing errors.

  1. Build the esp_console_cmd_t structure.

  2. Register the command.

Implement Command

do_i2cconfig_cmd() is a callback handler, used to modify the I2C bus configuration, including port number, communication frequency, SDA/SCL pins, and reinitialize the I2C master bus. It is suitable for scenarios where the I2C port or pin needs to be adjusted during operation.

The execution logic of this function is as follows:

  1. Parse command line parameters:

  • Call arg_parse() to parse command line parameters and store the parameters in the i2cconfig_args structure.

  • If there is an error in parsing the command line parameters, call arg_print_errors() to output error information and return directly.

  1. Define variables:

  • Define the variable i2c_port as I2C_NUM_0, indicating that I2C controller 0 is used by default.

  • Define the variables i2c_gpio_sda and i2c_gpio_scl to save the GPIO numbers used by the I2C data line and clock line. The initial value is 0, and it will be updated to the actual pin number according to the command line parameters or default configuration.

  1. Judge/Update parameters

  • Determine whether the user has specified the port parameter. If specified, call i2c_get_port() to verify the port number validity and update i2c_port.

  • Determine whether the user has specified the freq parameter. If specified, update the global I2C communication frequency i2c_frequency to the specified frequency.

  • Update the variables i2c_gpio_sda and i2c_gpio_scl according to the user-specified sda and scl parameters.

  1. Update the bus

  • Call i2c_del_master_bus() to delete the existing I2C bus to ensure that there will be no conflict when reinitializing. For further introduction and parameter explanation, please refer to I2C Interface.

  • Reconfigure and initialize the I2C bus according to the specified port number, SDA/SCL pins, and other parameters configure and initialize I2C bus.

Verify I2C Port

i2c_get_port() is used to verify whether the I2C port number provided by the user is valid, and returns the corresponding i2c_port_t type port handle to ensure that the subsequent I2C operations use the correct port.

Parameter Explanation

Input Parameter

Parameter Function

Parameter Description

port

User-specified I2C port number

Used to select the I2C controller to operate.

i2c_port

Output port handle pointer

Used to save the verified I2C port number, subsequent I2C operations will use this handle.

The execution logic of this function is as follows:

  1. Check whether the input I2C port number is within the correct range. If the port number is invalid, print an error log and return ESP_FAIL.

  2. If the port number is valid, point the input pointer i2c_port to the corresponding port number, and return ESP_OK to indicate that the port verification has passed.

Detect Slave Device

Register Command

register_i2cdetect() is used to register the i2cdetect command in the ESP-IDF console.

  1. Build the esp_console_cmd_t structure.

  2. Register the command.

Note

This command does not require additional parameters, so there is no need to define a parameter structure.

Implement Command

do_i2cdetect_cmd() is a callback handler, used to scan all devices on the specified I2C bus, helping users quickly detect which slave devices are connected on the bus.

The execution logic of this function is as follows:

  1. Define a variable address to save the currently scanned I2C slave address.

  2. Build a table of slave device addresses:

  • Print the table header, used to display the offset of 16 columns of addresses.

  • The outer loop traverses the I2C address space in rows of 16 addresses and prints the starting address of the current row.

  • The inner loop traverses the 16 addresses in each row:

    • Call i2c_master_probe() to detect whether there is a device response at the corresponding address. For further introduction and parameter explanation, refer to I2C Interface.

    • Print the result according to the return value:

      • ESP_OK: The slave device responds, print the device address.

      • ESP_ERR_TIMEOUT: The bus is occupied or unresponsive, print UU.

      • Others, such as no device detected, print --.

Get I2C Slave Data

Define Parameter Structure

i2cget_args is a command-line parameter structure, used to define and save the parameters provided by the user when entering the i2cget command in the console.

Structure Members

Input Parameter

Parameter Function

Parameter Description

chip_address

Device Address

The address of the slave device from which data needs to be obtained.

register_address

Register Address

Specifies the data of a particular register to be obtained.

data_length

Data Length

The length of the data to be obtained.

end

Parameter End Flag

Used to mark the end of the parameter list and save parsing error information.

Register Command

register_i2cget() is used to register the i2cget command in the ESP-IDF console, allowing users to dynamically obtain data from a specified register of a specified device through the command line.

  1. Define the command-line parameter structure, i.e., the input structure of the command:

  • Optional parameters: register_address and data_length.

  • Required parameter: chip_address.

  • Allows recording of up to 1 parsing error.

  1. Build the esp_console_cmd_t structure.

  2. Register the command.

Implement Command

do_i2cget_cmd() is a callback handler, used to obtain data from a specified register of a specified device.

The execution logic of this function is as follows:

  1. Parse command-line parameters:

  • Call arg_parse() to parse command-line parameters and store the parameters in the i2cget_args structure.

  • If parsing command-line parameters fails, call arg_print_errors() to output error information and return directly.

  1. Judge/Update Parameters

  • Save the user-specified chip_address parameter to chip_addr.

  • Determine whether the user has specified the register_address parameter. If specified, update the register address data_addr to the specified address, otherwise default to -1.

  • Determine whether the user has specified the data_length parameter. If specified, update the data length len to the specified length, otherwise default to 1.

  1. Add device to bus

  2. Perform read operation

  • Apply for a dynamic memory buffer data of length len for the data to be received.

  • I2C master writes then reads. The parameter description of i2c_master_transmit_receive() can refer to I2C interface.

  • Print the result according to the return value:

    • ESP_OK: Loop print the read data, 16 bytes per line.

    • ESP_ERR_TIMEOUT: Indicates that the bus is busy, print Bus is busy.

    • Others, print Read failed.

  1. Release resources

  • Release the receive buffer.

  • Call i2c_master_bus_rm_device() to remove the device and return the execution result. For further introduction and parameter description, please refer to I2C interface.

Write data to I2C slave

Define parameter structure

i2cset_args is a command line parameter structure used to define and save the parameters provided by the user when entering the i2cset command in the console.

Structure members

Input parameter

Parameter function

Parameter description

chip_address

Device address

The address of the slave device that needs to get data.

register_address

Register address

Specify the data of a specific register.

data

Write data

The data to be written to the slave.

end

Parameter end flag

Used to mark the end of the parameter list and save parsing error information.

Register command

register_i2cset() is used to register the i2cset command in the ESP-IDF console, allowing users to dynamically write data to the specified register of the specified device through the command line.

  1. Define the command line parameter structure, that is, the input structure of the command:

  • Optional parameter: register_address.

  • Required parameter: chip_address.

  • Specified times parameter:data, at least 0 data to write, up to 256 data to write.

  • Allow up to 2 parsing errors to be recorded.

  1. Build esp_console_cmd_t structure.

  2. Register command.

Implement command

do_i2cset_cmd() is a callback processing function, used to write data to the specified register of the specified device.

The execution logic of this function is as follows:

  1. Parse command line arguments:

  • Call arg_parse() to parse command line arguments and store the parameters in the i2cset_args structure.

  • If there is an error in parsing the command line arguments, call arg_print_errors() to output the error information and return directly.

  1. Judge/Update parameters

  • Save the user-specified chip_address parameter to chip_addr.

  • Determine whether the user has specified the register_address parameter. If specified, update the register address data_addr to the specified address, otherwise default to 0.

  • Get the length of the data that the user needs to write to the slave, and save it to len.

  1. Add device to bus

  2. Execute write operation

  • Apply for a dynamic memory buffer data of length len + 1 for the data to be written.

  • Store the target register address data_addr in the 0th byte of the buffer as the first data to be sent.

  • Copy the user’s input data to the buffer in a loop, starting to fill from data[1].

  • I2C Master Write. The parameter description of i2c_master_transmit() can refer to I2C Interface.

  • Print the result according to the return value:

    • ESP_OK: Indicates successful writing, print Write OK.

    • ESP_ERR_TIMEOUT: Indicates that the bus is busy, print Bus is busy.

    • Others, print Write failed.

  1. Release resources

  • Release the receive buffer.

  • Call i2c_master_bus_rm_device() to remove the device and return the execution result.

Scan I2C Slave Register

Define parameter structure

i2cdump_args is a command line parameter structure used to define and save the parameters provided by the user when entering the i2cdump command in the console.

Structure members

Input parameter

Parameter function

Parameter description

chip_address

Device address

The address of the slave device that needs to get data.

size

Read data width

Indicates how many bytes to read at a time, supporting 1, 2 or 4 bytes.

end

Parameter end flag

Used to mark the end of the parameter list and save parsing error information.

Register command

do_i2cdump_cmd() is used to register the i2cdump command in the ESP-IDF console, allowing users to dynamically scan and print the values of the internal registers of the I2C slave device through the command line, helping users quickly check the device register status.

  1. Define the command line parameter structure, that is, the input structure of the command:

  • Optional parameter: size.

  • Required parameter: chip_address.

  • Allows recording up to 1 parsing error.

  1. Build the esp_console_cmd_t structure.

  2. Register command.

Implement command

do_i2cdump_cmd() is a callback handler, used to scan and print the values of internal registers in the I2C slave device.

The execution logic of this function is as follows:

  1. Parse command line arguments:

  • Call arg_parse() to parse command line arguments and store the parameters in the i2cset_args structure.

  • If there is an error in parsing the command line arguments, call arg_print_errors() to output the error information and return directly.

  1. Judge/Update parameters

  • Save the user-specified chip_address parameter to chip_addr.

  • Determine whether the user has written the size parameter. If written, update the data width size to the specified width, otherwise default to 1.

  • Determine whether the data width specified by the user is valid (only accepts 1, 2, and 4 bytes).

  1. Add device to bus

  2. Scan registers

  • Define buffer variables:

    • data_addr: Temporarily save the register address to be accessed currently.

    • data[4]: Store the data read back from the device, supporting up to 4 bytes.

    • block[16]: Store a row (16 registers) of data for subsequent ASCII visual printing.

  • Print the header, including the hexadecimal data column and ASCII character display column.

  • The outer loop scans the registers of the slave device in rows of 16 registers and prints the starting address of the current row.

  • The inner loop traverses the 16 registers in each row:

    • Calculate the current register address.

    • I2C master write then read register data. The parameter description of i2c_master_transmit_receive() can refer to I2C interface.

    • Print the result according to the return value:

      • ESP_OK: Print the hexadecimal value of the data and save it to block[].

      • Others, such as data acquisition failure or no data in the current register, print xx and set block[] to -1 to indicate invalid.

  • Traverse block[16] to complete ASCII visual output.

  1. Remove the slave device

  • Call i2c_master_bus_rm_device() to remove the device and return the execution result.

Register all commands at once

register_i2ctools() is a general entry function. By calling this function, all I2C commands can be registered to the ESP-IDF console at once, without the need for individual registration.

Note

The following function is defined in i2ctools_example_main.c and is effective when the CONFIG_EXAMPLE_STORE_HISTORY configuration item is enabled.

Store command history

initialize_filesystem() is used to initialize and mount the FAT file system on the SPI Flash, so as to store command history or other files in the example.

  1. Define the handle variable wl_handle for managing the file system access on the SPI Flash.

  2. Construct the mount configuration structure esp_vfs_fat_mount_config_t. For a description of the structure members, refer to FAT File System.

  • Allow up to 4 files to be opened at the same time.

  • If the mount fails, automatically format the SPI Flash and create a file system.

  1. Call esp_vfs_fat_spiflash_mount_rw_wl() to mount the FAT file system to the MOUNT_PATH directory and use the storage partition. For further introduction and parameter description, refer to FAT File System.

  • If the mount is successful, save the file system handle for subsequent access.

  • If the mount fails, print an error log and return, do not continue subsequent operations.

Main Function Description

This example demonstrates how to interact with I2C bus devices using I2C tool commands in the ESP-IDF console environment, including I2C bus initialization, command registration, and console REPL environment configuration.

The execution logic is as follows:

  1. Configure REPL:

  • Define the console REPL handle repl.

  • Initialize the esp_console_repl_config_t structure with the default configuration ESP_CONSOLE_REPL_CONFIG_DEFAULT(). For a description of the structure members, refer to Console Terminal.

  • Set the prompt prompt to prompt the user to enter commands.

  1. Initialize the file system:

  • When CONFIG_EXAMPLE_STORE_HISTORY is enabled, call initialize_filesystem() to mount the FAT file system, which is used to save console history commands.

  • Set the history record save path to HISTORY_PATH.

  1. Determine and initialize the REPL environment through conditional compilation.

  2. Configure and initialize the I2C bus.

  3. Call register_i2ctools() to register I2C tool commands.

  4. Print the command usage steps to guide users on how to operate the I2C bus and devices through console commands.

  5. Call esp_console_start_repl(), enter the interactive command line, and wait for the user to enter commands. For further introduction and parameter description, refer to Console Terminal.