使用ESP-IDF新i2c_master.h库与OV7670通信时出现硬件NACK错误
driver/i2c_master.h读取OV7670寄存器时出现硬件NACK错误 我正在编写程序通过I2C(SCCB)读取OV7670摄像头模块的寄存器值。使用旧版driver/i2c.h库时代码可成功执行并读取寄存器值,但使用新版driver/i2c_master.h库时出现硬件NACK错误。
使用的SCCB函数
static i2c_master_bus_handle_t bus_handle = NULL; static i2c_master_dev_handle_t dev_handle = NULL; void sccb_init() { // Configure I2C bus i2c_master_bus_config_t bus_cfg = { .clk_source = I2C_CLK_SRC_DEFAULT, .i2c_port = 0, // I2C_NUM_0 .scl_io_num = I2C_MASTER_SCL_IO, .sda_io_num = I2C_MASTER_SDA_IO, .glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true, }; ESP_ERROR_CHECK(i2c_new_master_bus(&bus_cfg, &bus_handle)); // Configure SCCB device (OV7670 default address: 0x21 for write) i2c_device_config_t dev_cfg = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = 0x21, // OV7670 SCCB address .scl_speed_hz = I2C_MASTER_FREQ_HZ, }; ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); } esp_err_t sccb_write(uint8_t reg, uint8_t data) { uint8_t write_buf[2] = {reg, data}; return i2c_master_transmit(dev_handle, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); } esp_err_t sccb_read(uint8_t reg, uint8_t *data) { // Write register address first esp_err_t ret = i2c_master_transmit(dev_handle, ®, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); if (ret != ESP_OK) return ret; // Read data from register return i2c_master_receive(dev_handle, data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); } // UART functions
app_main函数
sccb_init(); ESP_LOGI(TAG, "SCCB initialized"); uart_init(); ESP_LOGI(TAG, "UART initialized"); while (1) { // Send data to PC uart_write_bytes(UART_PORT, tx_data, strlen(tx_data)); // Read data from PC (if available) int len = uart_read_bytes(UART_PORT, rx_data, BUF_SIZE, 1000 / portTICK_PERIOD_MS); if (len > 0) { rx_data[len] = '\0'; printf("Received: %s\n", rx_data); uint32_t regi = atoi(rx_data); if (regi > 255) { ESP_LOGI(TAG, "Register value out of range"); continue; } uint8_t reg = (uint8_t)regi; uint8_t data; vTaskDelay(100 / portTICK_PERIOD_MS); sccb_write(0x12, 0x80); // Reset COM7 vTaskDelay(100 / portTICK_PERIOD_MS); if (sccb_read(reg, &data) == ESP_OK) { ESP_LOGI(TAG, "Read from register 0x%02X: 0x%02X", reg, data); } else { ESP_LOGE(TAG, "Failed to read from register 0x%02X", reg); } } vTaskDelay(1000 / portTICK_PERIOD_MS); }
ESP32日志输出
I (298) main_task: Calling app_main()
D (298) i2c.coI (298) SCCB: UART initialized
Received: 12
E (7598) i2c.master: I2C hardware NACK detected
E (7598) i2c.master: I2C transaction unexpected nack detected
E (7598) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (7598) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (7708) i2c.master: I2C hardware NACK detected
E (7708) i2c.master: I2C transaction unexpected nack detected
E (7708) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (7708) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (7718) SCCB: Failed to read from register 0x0C
内容的提问来源于stack exchange,提问作者Hamim Mahmud

