1. modify i2c_set_pin function
2. update example comments and other minor changes 3. rename API: i2c_cmd_link_create/i2c_cmd_link_delete (+4 squashed commits) Squashed commits: [2e0ac3e] 1. coding style: add one space after condition key words. 2. modify i2c.h, use gpio_num_t instead of int, improve comments of return values 3. add i2c index in index.rst 4. add readme for i2c example [4991d92] update i2c.doc [88b672e] driver: i2c 1. add mux and spin lock to run in a thread-safe way. 2. modify example code [4eb15fe] driver: i2c code 1. add i2c master code 2. add i2c slave code 3. add i2c example code 4. add DRAM_ATTR for I2C array
This commit is contained in:
parent
370cf5493f
commit
9c7cc86793
10 changed files with 1983 additions and 3 deletions
1037
components/driver/i2c.c
Normal file
1037
components/driver/i2c.c
Normal file
File diff suppressed because it is too large
Load diff
514
components/driver/include/driver/i2c.h
Normal file
514
components/driver/include/driver/i2c.h
Normal file
|
@ -0,0 +1,514 @@
|
||||||
|
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef _DRIVER_I2C_H_
|
||||||
|
#define _DRIVER_I2C_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <esp_types.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "freertos/xtensa_api.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/ringbuf.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
#define I2C_APB_CLK_FREQ APB_CLK_FREQ /*!< I2C source clock is APB clock, 80MHz */
|
||||||
|
#define I2C_FIFO_LEN (32) /*!< I2C hardware fifo length */
|
||||||
|
typedef enum{
|
||||||
|
I2C_MODE_SLAVE = 0, /*!< I2C slave mode */
|
||||||
|
I2C_MODE_MASTER, /*!< I2C master mode */
|
||||||
|
I2C_MODE_MAX,
|
||||||
|
}i2c_mode_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_MASTER_WRITE = 0, /*!< I2C write data */
|
||||||
|
I2C_MASTER_READ, /*!< I2C read data */
|
||||||
|
} i2c_rw_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_DATA_MODE_MSB_FIRST = 0, /*!< I2C data msb first */
|
||||||
|
I2C_DATA_MODE_LSB_FIRST = 1, /*!< I2C data lsb first */
|
||||||
|
I2C_DATA_MODE_MAX
|
||||||
|
} i2c_trans_mode_t;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
I2C_CMD_RESTART = 0, /*!<I2C restart command */
|
||||||
|
I2C_CMD_WRITE, /*!<I2C write command */
|
||||||
|
I2C_CMD_READ, /*!<I2C read command */
|
||||||
|
I2C_CMD_STOP, /*!<I2C stop command */
|
||||||
|
I2C_CMD_END /*!<I2C end command */
|
||||||
|
}i2c_opmode_t;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
I2C_NUM_0 = 0, /*!< I2C port 0 */
|
||||||
|
I2C_NUM_1 , /*!< I2C port 1 */
|
||||||
|
I2C_NUM_MAX
|
||||||
|
} i2c_port_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_ADDR_BIT_7 = 0, /*!< I2C 7bit address for slave mode */
|
||||||
|
I2C_ADDR_BIT_10, /*!< I2C 10bit address for slave mode */
|
||||||
|
I2C_ADDR_BIT_MAX,
|
||||||
|
} i2c_addr_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C initialization parameters
|
||||||
|
*/
|
||||||
|
typedef struct{
|
||||||
|
i2c_mode_t mode; /*!< I2C mode */
|
||||||
|
gpio_num_t sda_io_num; /*!< GPIO number for I2C sda signal */
|
||||||
|
gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/
|
||||||
|
gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */
|
||||||
|
gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
|
||||||
|
} master;
|
||||||
|
struct {
|
||||||
|
uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */
|
||||||
|
uint16_t slave_addr; /*!< I2C address for slave mode */
|
||||||
|
} slave;
|
||||||
|
|
||||||
|
};
|
||||||
|
}i2c_config_t;
|
||||||
|
|
||||||
|
typedef void* i2c_cmd_handle_t; /*!< I2C command handle */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C driver install
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param mode I2C mode( master or slave )
|
||||||
|
* @param slv_rx_buf_len receiving buffer size for slave mode
|
||||||
|
* @note
|
||||||
|
* Only slave mode will use this value, driver will ignore this value in master mode.
|
||||||
|
* @param slv_tx_buf_len sending buffer size for slave mode
|
||||||
|
* @note
|
||||||
|
* Only slave mode will use this value, driver will ignore this value in master mode.
|
||||||
|
* @param 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.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
* - ESP_FAIL Driver install error
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C driver delete
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_driver_delete(i2c_port_t i2c_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C parameter initialization
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param i2c_conf pointer to I2C parameter settings
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_param_config(i2c_port_t i2c_num, i2c_config_t* i2c_conf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reset I2C tx hardware fifo
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reset I2C rx fifo
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C isr handler register
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param fn isr handler function
|
||||||
|
* @param arg parameter for isr handler function
|
||||||
|
* @param 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.
|
||||||
|
* @param handle handle return from esp_intr_alloc.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_isr_register(i2c_port_t i2c_num, void (*fn)(void*), void * arg, int intr_alloc_flags, intr_handle_t *handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief to delete and free I2C isr.
|
||||||
|
*
|
||||||
|
* @param handle handle of isr.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_isr_free(intr_handle_t handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure GPIO signal for I2C sck and sda
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param sda_io_num GPIO number for I2C sda signal
|
||||||
|
* @param scl_io_num GPIO number for I2C scl signal
|
||||||
|
* @param sda_pullup_en Whether to enable the internal pullup for sda pin
|
||||||
|
* @param scl_pullup_en Whether to enable the internal pullup for scl pin
|
||||||
|
* @param mode I2C mode
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_pin(i2c_port_t i2c_num, gpio_num_t sda_io_num, gpio_num_t scl_io_num,
|
||||||
|
gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create and init I2C command link
|
||||||
|
* @note
|
||||||
|
* Before we build I2C command link, we need to call i2c_cmd_link_create() to create
|
||||||
|
* a command link.
|
||||||
|
* After we finish sending the commands, we need to call i2c_cmd_link_delete() to
|
||||||
|
* release and return the resources.
|
||||||
|
*
|
||||||
|
* @return i2c command link handler
|
||||||
|
*/
|
||||||
|
i2c_cmd_handle_t i2c_cmd_link_create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free I2C command link
|
||||||
|
* @note
|
||||||
|
* Before we build I2C command link, we need to call i2c_cmd_link_create() to create
|
||||||
|
* a command link.
|
||||||
|
* After we finish sending the commands, we need to call i2c_cmd_link_delete() to
|
||||||
|
* release and return the resources.
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C command handle
|
||||||
|
*/
|
||||||
|
void i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to generate a start signal
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to write one byte to I2C bus
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
* @param data I2C one byte command to write to bus
|
||||||
|
* @param ack_en enable ack check for master
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to write buffer to I2C bus
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
* @param data data to send
|
||||||
|
* @param data_len data length
|
||||||
|
* @param ack_en enable ack check for master
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, bool ack_en);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to read one byte from I2C bus
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
* @param data pointer accept the data byte
|
||||||
|
* @param ack ack value for read command
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, int ack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to read data from I2C bus
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
* @param data data buffer to accept the data from bus
|
||||||
|
* @param data_len read data length
|
||||||
|
* @param ack ack value for read command
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t data_len, int ack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue command for I2C master to generate a stop signal
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
* Call i2c_master_cmd_begin() to send all queued commands
|
||||||
|
*
|
||||||
|
* @param cmd_handle I2C cmd link
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C master send queued commands.
|
||||||
|
* This function will trigger sending all queued commands.
|
||||||
|
* The task will be blocked until all the commands have been sent out.
|
||||||
|
* The I2C APIs are not thread-safe, if you want to use one I2C port in different tasks,
|
||||||
|
* you need to take care of the multi-thread issue.
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C master mode
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param cmd_handle I2C command handler
|
||||||
|
* @param ticks_to_wait maximum wait ticks.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
* - ESP_FAIL Sending command error, slave doesn'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.
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, portBASE_TYPE ticks_to_wait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C slave write data to internal ringbuffer, when tx fifo empty, isr will fill the hardware
|
||||||
|
* fifo from the internal ringbuffer
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C slave mode
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param data data pointer to write into internal buffer
|
||||||
|
* @param size data size
|
||||||
|
* @param ticks_to_wait Maximum waiting ticks
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_FAIL(-1) Parameter error
|
||||||
|
* - Others(>=0) The number of data bytes that pushed to the I2C slave buffer.
|
||||||
|
*/
|
||||||
|
int i2c_slave_write_buffer(i2c_port_t i2c_num, uint8_t* data, int size, portBASE_TYPE ticks_to_wait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief I2C slave read data from internal buffer. When I2C slave receive data, isr will copy received data
|
||||||
|
* from hardware rx fifo to internal ringbuffer. Then users can read from internal ringbuffer.
|
||||||
|
* @note
|
||||||
|
* Only call this function in I2C slave mode
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param data data pointer to write into internal buffer
|
||||||
|
* @param max_size Maximum data size to read
|
||||||
|
* @param ticks_to_wait Maximum waiting ticks
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_FAIL(-1) Parameter error
|
||||||
|
* - Others(>=0) The number of data bytes that read from I2C slave buffer.
|
||||||
|
*/
|
||||||
|
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, portBASE_TYPE ticks_to_wait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set I2C master clock period
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param high_period clock cycle number during SCL is high level, high_period is a 14 bit value
|
||||||
|
* @param low_period clock cycle number during SCL is low level, low_period is a 14 bit value
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get I2C master clock period
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param high_period pointer to get clock cycle number during SCL is high level, will get a 14 bit value
|
||||||
|
* @param low_period pointer to get clock cycle number during SCL is low level, will get a 14 bit value
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2s_get_period(i2c_port_t i2c_num, int* high_period, int* low_period);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set I2C master start signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param setup_time clock number between the falling-edge of SDA and rising-edge of SCL for start mark, it's a 10-bit value.
|
||||||
|
* @param hold_time clock num between the falling-edge of SDA and falling-edge of SCL for start mark, it's a 10-bit value.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get I2C master start signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param setup_time pointer to get setup time
|
||||||
|
* @param hold_time pointer to get hold time
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set I2C master stop signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param setup_time clock num between the rising-edge of SCL and the rising-edge of SDA, it's a 10-bit value.
|
||||||
|
* @param hold_time clock number after the STOP bit's rising-edge, it's a 14-bit value.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get I2C master stop signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param setup_time pointer to get setup time.
|
||||||
|
* @param hold_time pointer to get hold time.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int* setup_time, int* hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set I2C data signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param sample_time clock number I2C used to sample data on SDA after the rising-edge of SCL, it's a 10-bit value
|
||||||
|
* @param hold_time clock number I2C used to hold the data after the falling-edge of SCL, it's a 10-bit value
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get I2C data signal timing
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param sample_time pointer to get sample time
|
||||||
|
* @param hold_time pointer to get hold time
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int* sample_time, int* hold_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set I2C data transfer mode
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param tx_trans_mode I2C sending data mode
|
||||||
|
* @param rx_trans_mode I2C receving data mode
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get I2C data transfer mode
|
||||||
|
*
|
||||||
|
* @param i2c_num I2C port number
|
||||||
|
* @param tx_trans_mode pointer to get I2C sending data mode
|
||||||
|
* @param rx_trans_mode pointer to get I2C receiving data mode
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Success
|
||||||
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_DRIVER_I2C_H_*/
|
|
@ -261,6 +261,8 @@
|
||||||
#define I2C_RXFIFO_FULL_THRHD_V 0x1F
|
#define I2C_RXFIFO_FULL_THRHD_V 0x1F
|
||||||
#define I2C_RXFIFO_FULL_THRHD_S 0
|
#define I2C_RXFIFO_FULL_THRHD_S 0
|
||||||
|
|
||||||
|
#define I2C_DATA_APB_REG(i) (0x60013000 + (i) * 0x14000 + 0x001c)
|
||||||
|
|
||||||
#define I2C_DATA_REG(i) (REG_I2C_BASE(i) + 0x001c)
|
#define I2C_DATA_REG(i) (REG_I2C_BASE(i) + 0x001c)
|
||||||
/* I2C_FIFO_RDATA : RO ;bitpos:[7:0] ;default: 8'b0 ; */
|
/* I2C_FIFO_RDATA : RO ;bitpos:[7:0] ;default: 8'b0 ; */
|
||||||
/*description: The register represent the byte data read from rxfifo when use apb fifo access*/
|
/*description: The register represent the byte data read from rxfifo when use apb fifo access*/
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
typedef volatile struct {
|
typedef volatile struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t scl_low_period:14; /*This register is used to configure the low level width of SCL clock.*/
|
uint32_t period:14; /*This register is used to configure the low level width of SCL clock.*/
|
||||||
uint32_t reserved14: 18;
|
uint32_t reserved14: 18;
|
||||||
};
|
};
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
@ -58,7 +58,7 @@ typedef volatile struct {
|
||||||
} status_reg;
|
} status_reg;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t tout: 20; /*This register is used to configure the max clock number of receiving a data.*/
|
uint32_t tout: 20; /*This register is used to configure the max clock number of receiving a data, unit: APB clock cycle.*/
|
||||||
uint32_t reserved20:12;
|
uint32_t reserved20:12;
|
||||||
};
|
};
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
@ -282,7 +282,7 @@ typedef volatile struct {
|
||||||
uint32_t reserved_f4;
|
uint32_t reserved_f4;
|
||||||
uint32_t date; /**/
|
uint32_t date; /**/
|
||||||
uint32_t reserved_fc;
|
uint32_t reserved_fc;
|
||||||
uint32_t fifo_start_addr; /*This the start address for ram when use apb nonfifo access.*/
|
uint32_t ram_data[32]; /*This the start address for ram when use apb nonfifo access.*/
|
||||||
} i2c_dev_t;
|
} i2c_dev_t;
|
||||||
extern i2c_dev_t I2C0;
|
extern i2c_dev_t I2C0;
|
||||||
extern i2c_dev_t I2C1;
|
extern i2c_dev_t I2C1;
|
||||||
|
|
82
docs/api/i2c.rst
Normal file
82
docs/api/i2c.rst
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
I2C
|
||||||
|
===========
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
ESP32 has two I2C controllers which can be set as master mode or slave mode.
|
||||||
|
|
||||||
|
Application Example
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
I2C master and slave example: `examples/18_i2c <https://github.com/espressif/esp-idf/tree/master/examples/18_i2c>`_.
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Header Files
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
* `driver/include/driver/i2c.h <https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/i2c.h>`_
|
||||||
|
|
||||||
|
Macros
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
.. doxygendefine:: I2C_APB_CLK_FREQ
|
||||||
|
.. doxygendefine:: I2C_FIFO_LEN
|
||||||
|
|
||||||
|
Type Definitions
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. doxygentypedef:: i2c_cmd_handle_t
|
||||||
|
|
||||||
|
Enumerations
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. doxygenenum:: i2c_mode_t
|
||||||
|
.. doxygenenum:: i2c_rw_t
|
||||||
|
.. doxygenenum:: i2c_trans_mode_t
|
||||||
|
.. doxygenenum:: i2c_opmode_t
|
||||||
|
.. doxygenenum:: i2c_port_t
|
||||||
|
.. doxygenenum:: i2c_addr_mode_t
|
||||||
|
|
||||||
|
Structures
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
.. doxygenstruct:: i2c_config_t
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
Functions
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
.. doxygenfunction:: i2c_driver_install
|
||||||
|
.. doxygenfunction:: i2c_driver_delete
|
||||||
|
.. doxygenfunction:: i2c_param_config
|
||||||
|
.. doxygenfunction:: i2c_reset_tx_fifo
|
||||||
|
.. doxygenfunction:: i2c_reset_rx_fifo
|
||||||
|
.. doxygenfunction:: i2c_isr_register
|
||||||
|
.. doxygenfunction:: i2c_isr_free
|
||||||
|
.. doxygenfunction:: i2c_set_pin
|
||||||
|
.. doxygenfunction:: i2c_master_start
|
||||||
|
.. doxygenfunction:: i2c_master_write_byte
|
||||||
|
.. doxygenfunction:: i2c_master_write
|
||||||
|
.. doxygenfunction:: i2c_master_read_byte
|
||||||
|
.. doxygenfunction:: i2c_master_read
|
||||||
|
.. doxygenfunction:: i2c_master_stop
|
||||||
|
.. doxygenfunction:: i2c_master_cmd_begin
|
||||||
|
.. doxygenfunction:: i2c_slave_write_buffer
|
||||||
|
.. doxygenfunction:: i2c_slave_read
|
||||||
|
.. doxygenfunction:: i2c_set_period
|
||||||
|
.. doxygenfunction:: i2s_get_period
|
||||||
|
.. doxygenfunction:: i2c_set_start_timing
|
||||||
|
.. doxygenfunction:: i2c_get_start_timing
|
||||||
|
.. doxygenfunction:: i2c_set_stop_timing
|
||||||
|
.. doxygenfunction:: i2c_get_stop_timing
|
||||||
|
.. doxygenfunction:: i2c_set_data_timing
|
||||||
|
.. doxygenfunction:: i2c_get_data_timing
|
||||||
|
.. doxygenfunction:: i2c_set_data_mode
|
||||||
|
.. doxygenfunction:: i2c_get_data_mode
|
||||||
|
.. doxygenfunction:: i2c_cmd_link_create
|
||||||
|
.. doxygenfunction:: i2c_cmd_link_delete
|
||||||
|
|
|
@ -107,6 +107,7 @@ Contents:
|
||||||
LED Control <api/ledc>
|
LED Control <api/ledc>
|
||||||
Remote Control <api/rmt>
|
Remote Control <api/rmt>
|
||||||
Timer <api/timer>
|
Timer <api/timer>
|
||||||
|
I2C <api/i2c>
|
||||||
Pulse Counter <api/pcnt>
|
Pulse Counter <api/pcnt>
|
||||||
Sigma-delta Modulation <api/sigmadelta>
|
Sigma-delta Modulation <api/sigmadelta>
|
||||||
SPI Flash and Partition APIs <api/spi_flash>
|
SPI Flash and Partition APIs <api/spi_flash>
|
||||||
|
|
9
examples/18_i2c/Makefile
Normal file
9
examples/18_i2c/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||||
|
# project subdirectory.
|
||||||
|
#
|
||||||
|
|
||||||
|
PROJECT_NAME := i2c
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
29
examples/18_i2c/README.md
Normal file
29
examples/18_i2c/README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# I2C Example
|
||||||
|
|
||||||
|
|
||||||
|
* This example will show you how to use I2C module by running two tasks on i2c bus:
|
||||||
|
|
||||||
|
* read external i2c sensor, here we use a BH1750 light sensor(GY-30 module) for instance.
|
||||||
|
* Use one I2C port(master mode) to read or write the other I2C port(slave mode) on one ESP32 chip.
|
||||||
|
|
||||||
|
* Pin assignment:
|
||||||
|
|
||||||
|
* slave :
|
||||||
|
* GPIO25 is assigned as the data signal of i2c slave port
|
||||||
|
* GPIO26 is assigned as the clock signal of i2c slave port
|
||||||
|
* master:
|
||||||
|
* GPIO18 is assigned as the data signal of i2c master port
|
||||||
|
* GPIO19 is assigned as the clock signal of i2c master port
|
||||||
|
|
||||||
|
* Connection:
|
||||||
|
|
||||||
|
* connect GPIO18 with GPIO25
|
||||||
|
* connect GPIO19 with GPIO26
|
||||||
|
* connect sda/scl of sensor with GPIO18/GPIO19
|
||||||
|
* no need to add external pull-up resistors, driver will enable internal pull-up resistors.
|
||||||
|
|
||||||
|
* Test items:
|
||||||
|
|
||||||
|
* read the sensor data, if connected.
|
||||||
|
* i2c master(ESP32) will write data to i2c slave(ESP32).
|
||||||
|
* i2c master(ESP32) will read data from i2c slave(ESP32).
|
3
examples/18_i2c/main/component.mk
Normal file
3
examples/18_i2c/main/component.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#
|
||||||
|
# Main Makefile. This is basically the same as a component makefile.
|
||||||
|
#
|
303
examples/18_i2c/main/i2c_test.c
Normal file
303
examples/18_i2c/main/i2c_test.c
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
/* i2c - Example
|
||||||
|
|
||||||
|
For other examples please check:
|
||||||
|
https://github.com/espressif/esp-idf/tree/master/examples
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEST CODE BRIEF
|
||||||
|
*
|
||||||
|
* This example will show you how to use I2C module by running two tasks on i2c bus:
|
||||||
|
*
|
||||||
|
* - read external i2c sensor, here we use a BH1750 light sensor(GY-30 module) for instance.
|
||||||
|
* - Use one I2C port(master mode) to read or write the other I2C port(slave mode) on one ESP32 chip.
|
||||||
|
*
|
||||||
|
* Pin assignment:
|
||||||
|
*
|
||||||
|
* - slave :
|
||||||
|
* GPIO25 is assigned as the data signal of i2c slave port
|
||||||
|
* GPIO26 is assigned as the clock signal of i2c slave port
|
||||||
|
* - master:
|
||||||
|
* GPIO18 is assigned as the data signal of i2c master port
|
||||||
|
* GPIO19 is assigned as the clock signal of i2c master port
|
||||||
|
*
|
||||||
|
* Connection:
|
||||||
|
*
|
||||||
|
* - connect GPIO18 with GPIO25
|
||||||
|
* - connect GPIO19 with GPIO26
|
||||||
|
* - connect sda/scl of sensor with GPIO18/GPIO19
|
||||||
|
* - no need to add external pull-up resistors, driver will enable internal pull-up resistors.
|
||||||
|
*
|
||||||
|
* Test items:
|
||||||
|
*
|
||||||
|
* - read the sensor data, if connected.
|
||||||
|
* - i2c master(ESP32) will write data to i2c slave(ESP32).
|
||||||
|
* - i2c master(ESP32) will read data from i2c slave(ESP32).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
|
||||||
|
#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
|
||||||
|
#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
|
||||||
|
|
||||||
|
#define I2C_SLAVE_SCL_IO 26 /*!<gpio number for i2c slave clock */
|
||||||
|
#define I2C_SLAVE_SDA_IO 25 /*!<gpio number for i2c slave data */
|
||||||
|
#define I2C_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
|
||||||
|
#define I2C_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
|
||||||
|
#define I2C_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
|
||||||
|
|
||||||
|
#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
|
||||||
|
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
|
||||||
|
#define I2C_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
|
||||||
|
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
||||||
|
|
||||||
|
#define BH1750_SENSOR_ADDR 0x23 /*!< slave address for BH1750 sensor */
|
||||||
|
#define BH1750_CMD_START 0x23 /*!< Command to set measure mode */
|
||||||
|
#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
|
||||||
|
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||||
|
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||||
|
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||||
|
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||||
|
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||||
|
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||||
|
|
||||||
|
xSemaphoreHandle print_mux;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief test code to read esp-i2c-slave
|
||||||
|
* We need to fill the buffer of esp slave device, then master can read them out.
|
||||||
|
*
|
||||||
|
* _______________________________________________________________________________________
|
||||||
|
* | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop |
|
||||||
|
* --------|--------------------------|----------------------|--------------------|------|
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t* data_rd, size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||||
|
if (size > 1) {
|
||||||
|
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
|
||||||
|
}
|
||||||
|
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test code to write esp-i2c-slave
|
||||||
|
* Master device write data to slave(both esp32),
|
||||||
|
* the data will be stored in slave buffer.
|
||||||
|
* We can read them out from slave buffer.
|
||||||
|
*
|
||||||
|
* ___________________________________________________________________
|
||||||
|
* | start | slave_addr + wr_bit + ack | write n bytes + ack | stop |
|
||||||
|
* --------|---------------------------|----------------------|------|
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t* data_wr, size_t size)
|
||||||
|
{
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN);
|
||||||
|
i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief test code to write esp-i2c-slave
|
||||||
|
*
|
||||||
|
* 1. set mode
|
||||||
|
* _________________________________________________________________
|
||||||
|
* | start | slave_addr + wr_bit + ack | write 1 byte + ack | stop |
|
||||||
|
* --------|---------------------------|---------------------|------|
|
||||||
|
* 2. wait more than 24 ms
|
||||||
|
* 3. read data
|
||||||
|
* ______________________________________________________________________________________
|
||||||
|
* | start | slave_addr + rd_bit + ack | read 1 byte + ack | read 1 byte + nack | stop |
|
||||||
|
* --------|---------------------------|--------------------|--------------------|------|
|
||||||
|
*/
|
||||||
|
esp_err_t i2c_master_sensor_test(i2c_port_t i2c_num, uint8_t* data_h, uint8_t* data_l)
|
||||||
|
{
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||||
|
i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
int ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
if (ret == ESP_FAIL) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
vTaskDelay(30 / portTICK_RATE_MS);
|
||||||
|
|
||||||
|
cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
|
||||||
|
i2c_master_read_byte(cmd, data_h, ACK_VAL);
|
||||||
|
i2c_master_read_byte(cmd, data_l, NACK_VAL);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
if (ret == ESP_FAIL) {
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief i2c master initialization
|
||||||
|
*/
|
||||||
|
void i2c_master_init()
|
||||||
|
{
|
||||||
|
int i2c_master_port = I2C_MASTER_NUM;
|
||||||
|
i2c_config_t conf;
|
||||||
|
conf.mode = I2C_MODE_MASTER;
|
||||||
|
conf.sda_io_num = I2C_MASTER_SDA_IO;
|
||||||
|
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf.scl_io_num = I2C_MASTER_SCL_IO;
|
||||||
|
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
||||||
|
i2c_param_config(i2c_master_port, &conf);
|
||||||
|
i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief i2c slave initialization
|
||||||
|
*/
|
||||||
|
void i2c_slave_init()
|
||||||
|
{
|
||||||
|
int i2c_slave_port = I2C_SLAVE_NUM;
|
||||||
|
i2c_config_t conf_slave;
|
||||||
|
conf_slave.sda_io_num = I2C_SLAVE_SDA_IO;
|
||||||
|
conf_slave.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf_slave.scl_io_num = I2C_SLAVE_SCL_IO;
|
||||||
|
conf_slave.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
|
conf_slave.mode = I2C_MODE_SLAVE;
|
||||||
|
conf_slave.slave.addr_10bit_en = 0;
|
||||||
|
conf_slave.slave.slave_addr = ESP_SLAVE_ADDR;
|
||||||
|
i2c_param_config(i2c_slave_port, &conf_slave);
|
||||||
|
i2c_driver_install(i2c_slave_port, conf_slave.mode, I2C_SLAVE_RX_BUF_LEN, I2C_SLAVE_TX_BUF_LEN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief test function to show buffer
|
||||||
|
*/
|
||||||
|
void disp_buf(uint8_t* buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
printf("%02x ", buf[i]);
|
||||||
|
if (( i + 1 ) % 16 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_test_task(void* arg)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int ret;
|
||||||
|
uint32_t task_idx = (uint32_t) arg;
|
||||||
|
uint8_t* data = (uint8_t*) malloc(DATA_LENGTH);
|
||||||
|
uint8_t* data_wr = (uint8_t*) malloc(DATA_LENGTH);
|
||||||
|
uint8_t* data_rd = (uint8_t*) malloc(DATA_LENGTH);
|
||||||
|
uint8_t sensor_data_h, sensor_data_l;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = i2c_master_sensor_test( I2C_MASTER_NUM, &sensor_data_h, &sensor_data_l);
|
||||||
|
xSemaphoreTake(print_mux, portMAX_DELAY);
|
||||||
|
printf("*******************\n");
|
||||||
|
printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx);
|
||||||
|
printf("*******************\n");
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
printf("data_h: %02x\n", sensor_data_h);
|
||||||
|
printf("data_l: %02x\n", sensor_data_l);
|
||||||
|
printf("sensor val: %f\n", ( sensor_data_h << 8 | sensor_data_l ) / 1.2);
|
||||||
|
} else {
|
||||||
|
printf("No ack, sensor not connected...skip...\n");
|
||||||
|
}
|
||||||
|
xSemaphoreGive(print_mux);
|
||||||
|
vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS);
|
||||||
|
|
||||||
|
//---------------------------------------------------
|
||||||
|
for (i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data[i] = i;
|
||||||
|
}
|
||||||
|
size_t d_size = i2c_slave_write_buffer(I2C_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
||||||
|
if (d_size == 0) {
|
||||||
|
printf("i2c slave tx buffer full\n");
|
||||||
|
ret = i2c_master_read_slave(I2C_MASTER_NUM, data_rd, DATA_LENGTH);
|
||||||
|
} else {
|
||||||
|
ret = i2c_master_read_slave(I2C_MASTER_NUM, data_rd, RW_TEST_LENGTH);
|
||||||
|
}
|
||||||
|
xSemaphoreTake(print_mux, portMAX_DELAY);
|
||||||
|
printf("*******************\n");
|
||||||
|
printf("TASK[%d] MASTER READ FROM SLAVE\n", task_idx);
|
||||||
|
printf("*******************\n");
|
||||||
|
printf("====TASK[%d] Slave buffer data ====\n", task_idx);
|
||||||
|
disp_buf(data, d_size);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
printf("====TASK[%d] Master read ====\n", task_idx);
|
||||||
|
disp_buf(data_rd, d_size);
|
||||||
|
} else {
|
||||||
|
printf("Master read slave error, IO not connected...\n");
|
||||||
|
}
|
||||||
|
xSemaphoreGive(print_mux);
|
||||||
|
vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS);
|
||||||
|
//---------------------------------------------------
|
||||||
|
int size;
|
||||||
|
for (i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = i + 10;
|
||||||
|
}
|
||||||
|
//we need to fill the slave buffer so that master can read later
|
||||||
|
ret = i2c_master_write_slave( I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
size = i2c_slave_read_buffer( I2C_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
||||||
|
}
|
||||||
|
xSemaphoreTake(print_mux, portMAX_DELAY);
|
||||||
|
printf("*******************\n");
|
||||||
|
printf("TASK[%d] MASTER WRITE TO SLAVE\n", task_idx);
|
||||||
|
printf("*******************\n");
|
||||||
|
printf("----TASK[%d] Master write ----\n", task_idx);
|
||||||
|
disp_buf(data_wr, RW_TEST_LENGTH);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
printf("----TASK[%d] Slave read: [%d] bytes ----\n", task_idx, size);
|
||||||
|
disp_buf(data, size);
|
||||||
|
} else {
|
||||||
|
printf("TASK[%d] Master write slave error, IO not connected....\n", task_idx);
|
||||||
|
}
|
||||||
|
xSemaphoreGive(print_mux);
|
||||||
|
vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
print_mux = xSemaphoreCreateMutex();
|
||||||
|
i2c_slave_init();
|
||||||
|
i2c_master_init();
|
||||||
|
|
||||||
|
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void* ) 0, 10, NULL);
|
||||||
|
xTaskCreate(i2c_test_task, "i2c_test_task_1", 1024 * 2, (void* ) 1, 10, NULL);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue