day_day97 2022-07-03 23:48 采纳率: 100%
浏览 175
已结题

ESP32C3 I2C 无应答

问题遇到的现象和发生背景

我使用idf开发esp32c3,使用i2c外设时出现问题。I2C正常发送了出去,但从机没有应答。
我此前使用过nxp的lpc55s69进行过测试,并将这两次的波形使用逻辑分析仪采集出来,区别仅有ACK应答。读取数据的时候现象也是一样的,从机无法作出应答,但时序波形与lpc55s69下实验仅有ack部分有区别。
从机使用AS5600和ADXL345都测试过,现象如上一致。
引脚也更换过多个,包括4 5 6 8 9,都是如此。

实验使用的esp32c3为合宙版。后来又使用安可信的esp32(非c3),额外编写esp32工程,现象依然如此。
实验使用的idf为v4.4-release分支。开发环境ubuntu20.04+vscode+idf4.4

问题相关代码,请勿粘贴截图

初始化


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);
}

1-自己编写cmd

        // i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        // i2c_master_start(cmd);
        // i2c_master_write_byte(cmd, AS5600_I2C_ADDR << 1 | I2C_MASTER_WRITE, false);
        // i2c_master_write_byte(cmd, 0x00, false);
        // i2c_master_stop(cmd);
        // ret = i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS);
        // i2c_cmd_link_delete(cmd);

        // cmd = i2c_cmd_link_create();
        // vTaskDelay(50 / portTICK_PERIOD_MS);
        // i2c_master_start(cmd);
        // i2c_master_write_byte(cmd, AS5600_I2C_ADDR << 1 | I2C_MASTER_READ, false);
        // i2c_master_read_byte(cmd, data, false);
        // i2c_master_stop(cmd);
        // ret = i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS);
        // i2c_cmd_link_delete(cmd);

2-调用函数

        i2c_master_write_to_device(I2C_NUM_0, 0x1D, data, 1, 500 / portTICK_PERIOD_MS);

运行结果及报错内容

img

img

我的解答思路和尝试过的方法

基于以上情况,我只能怀疑是不是sda电平在接收ack的时候被主机钳住总线了?
毕竟合宙的板子似乎外部没有接任何器件了,尽只有我挂的adxl345

我想要达到的结果
  • 写回答

2条回答 默认 最新

  • day_day97 2022-07-14 23:27
    关注

    查出来了。代码没什么毛病,就是读的时候要用对应的宏设置应答:

    
            i2c_master_read_byte(cmd, data, I2C_MASTER_ACK);
            i2c_master_read_byte(cmd, &data[1], I2C_MASTER_LAST_NACK);
    

    之所以没有应答,对于adxl345时因为弄错了从机地址。
    对于as5600则大有名堂,as5600对上升沿要求很严格,数据手册里面限制到120ns。但经过示波器测量,esp32内部上拉带来的上升沿有10us。

    img

    img


    以上分别是成功读取的nxp开发板和esp32c3上升沿。

    将速度放缓到1K仍然不能读取:

    img

    经查询as5600数据手册后发现iic数据线需要上拉4.7K,猜测是因为as5600对上升沿有异常要求,所以靠外部上来来提升上升沿响应速度。
    一下是10K速度下读取的时序:
    内部上拉+失败-外部上拉+成功

    img

    img

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
  • 火星人不在地球 2022-07-04 09:36
    关注
    int i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t length, uint8_t data)
    {
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
        i2c_master_write(cmd, &data, length, ACK_CHECK_EN);
        i2c_master_stop(cmd);
    
        esp_err_t ret = i2c_master_cmd_begin(0, cmd, 10 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        return ret;
    }
    
    int i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t length, uint8_t *data)
    {
        if (length == 0)
        {
            return ESP_OK;
        }
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
        i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
    
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
        if (length > 1)
        {
            i2c_master_read(cmd, data, length - 1, ACK_VAL);
        }
        i2c_master_read_byte(cmd, data, NACK_VAL);
        i2c_master_stop(cmd);
        
        esp_err_t ret = i2c_master_cmd_begin(0, cmd, 10 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        return ret;
    }
    
    
    

    可以读取mpu6050 bmp180 hmc5883 这几个芯片,我觉得读adxl345应该也可以。然后这个虽然写了多数据但我都是读一位用的,一次读多位还没试过。参数名应该写的很明确,看不懂可以再问我。

    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 7月22日
  • 已采纳回答 7月14日
  • 创建了问题 7月3日

悬赏问题

  • ¥15 求一个智能家居控制的代码
  • ¥15 ad软件 pcb布线pcb规则约束编辑器where the object matpcb布线pcb规则约束编辑器where the object matchs怎么没有+15v只有no net
  • ¥15 虚拟机vmnet8 nat模式可以ping通主机,主机也能ping通虚拟机,但是vmnet8一直未识别怎么解决,其次诊断结果就是默认网关不可用
  • ¥20 求各位能用我能理解的话回答超级简单的一些问题
  • ¥15 yolov5双目识别输出坐标代码报错
  • ¥15 这个代码有什么语法错误
  • ¥15 给予STM32按键中断与串口通信
  • ¥15 使用QT实现can通信
  • ¥15 关于sp验证的一些东西,求告知如何解决,
  • ¥35 关于#javascript#的问题:但是我写的只能接码数字和字符,帮我写一个解码JS问题