I haven't checked for the slowing clock speed, but I got mine to work with the following code. It's nothing perfect, but I don't miss anything. Occasionally I still get stuck on the i2c line, but I just monitor that and reset as necessary.
Code: Select all
void initI2C() {
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_SDA;
conf.scl_io_num = I2C_SCL;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = 100000;
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_1, &conf));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_1, I2C_MODE_MASTER, 0, 0, 0));
}
/**
* @brief Reads a register of a specified MCP32017
*/
void mcp23017_local_read(uint8_t MCP23017_ADDRESS, uint8_t* data_h){
i2c_cmd_handler = i2c_cmd_link_create();
i2c_master_start(i2c_cmd_handler);
i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(i2c_cmd_handler, data_h, NACK_VAL);
i2c_master_stop(i2c_cmd_handler);
int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);
// printf("ret:%d-%d\n", ret, ESP_ERR_TIMEOUT);
i2c_cmd_link_delete(i2c_cmd_handler);
if (ret != 0) {
send_dump_write();
printf("ERROR\n");
}
}
/**
* @brief Write a value to a register of a specified MCP32017
*/
void mcp23017_local_write(uint8_t MCP23017_ADDRESS, uint8_t command){
vTaskDelay(30 / portTICK_RATE_MS);
i2c_cmd_handler = i2c_cmd_link_create();
i2c_master_start(i2c_cmd_handler);
i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(i2c_cmd_handler, command, ACK_CHECK_EN);// Access IODIRB
i2c_master_stop(i2c_cmd_handler);
int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd_handler);
if (ret == ESP_FAIL) {
printf("ERROR\n");
}
}
/**
* @brief Writes two values to a register of a specified MCP32017
*/
void mcp23017_duel_write(uint8_t MCP23017_ADDRESS, uint8_t command, uint8_t command2){
i2c_cmd_handler = i2c_cmd_link_create();
i2c_master_start(i2c_cmd_handler);
i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(i2c_cmd_handler, command, ACK_CHECK_EN);// Access IODIRB
i2c_master_write_byte(i2c_cmd_handler, command2, ACK_CHECK_EN);// Write Register
i2c_master_stop(i2c_cmd_handler);
int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(i2c_cmd_handler);
if (ret == ESP_FAIL) {
printf("ERROR\n");
}
}
/**
* @brief Reads the value of the register of the specified MCP23017
*/
uint8_t mcp23017_read(uint8_t MCP23017_ADDRESS, uint8_t command){
uint8_t data_h;
mcp23017_local_write(MCP23017_ADDRESS, command);
vTaskDelay(30 / portTICK_RATE_MS);
mcp23017_local_read(MCP23017_ADDRESS, &data_h);
vTaskDelay(30 / portTICK_RATE_MS);
return data_h;
}