完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在尝试在 ESP32(无 -S3)芯片上使用相同的软件后,我在以前运行在 ESP32-S3 芯片上的功能软件中遇到奇怪的 I2C 超时。该软件相当简单,连接到 u-blox GNSS 芯片即可读取 UBX 导航消息。芯片的 I2C 接口公开了编号为 0xfd、0xfe 和 0xff 的寄存器。寄存器 0xfd 和 0xfe 包含一个 16 位整数,其中包含可从芯片内部缓冲区读取的字节数,并且从寄存器 0xff 多次读取可以访问实际的 UBX 消息。芯片具有“寄存器自动递增”功能,即如果选择一个寄存器后读取超过一个字节,则寄存器指针会自动递增,您将获得后面寄存器中的数据。如果寄存器指针已经达到 0xff,它会停留在 0xff。
删除所有错误检查,代码看起来或多或少是这样的: 代码:全选 // initialize the I2C bus with i2c_param_config and i2c_driver_install, // then in a loop, use the following code to read individual UBX messages uint8_t *buffer = ...; uint8_t reg = 0xfd; // write 0xfd to the chip (select register 0xfd) and read two bytes i2c_master_write_read_device(I2C_PORT, ZEDF9P_ADDR, ®, 1, buffer, 2, I2C_TIMEOUT); // buffer[0] now contains the value in register 0xfd and buffer[1] the value in register 0xfe, // the number of available bytes is big endian encoded uint16_t available = (buffer[0] << 8) | buffer[1]; if (available > 6) { // UBX messages are longer than 6 bytes // the register pointer is now at 0xff, so we can read actual data without requesting a specific register // first read the 6 byte UBX header: i2c_master_read_from_device(I2C_PORT, ZEDF9P_ADDR, buffer, 6, I2C_TIMEOUT); // buffer[0] and buffer[1] will now contain the UBX prefix 0xb562 // buffer[2] and buffer[3] will contain the message type (class and id) // buffer[4] and buffer[5] the (now little endian encoded) length of the actual message data: uint16_t length = buffer[4] | (buffer[5] << 8); // read the remaining part of the UBX message and two additional bytes with checksum data: i2c_master_read_from_device(I2C_PORT, ZEDF9P_ADDR, buffer + 6, length + 2, I2C_TIMEOUT); // the buffer should now contain one complete UBX message with header, payload data and checksum bytes } 正如所指出的,这段代码在 ESP-S3 芯片上运行时完美运行。在 ESP32 芯片上尝试代码后,读取和写入方法开始根据时序广泛返回 ESP_ERR_TIMEOUT,而不遵守 I2C_TIMEOUT 中提供的请求超时。即使是第一次调用 i2c_master_write_read_device(读取可用字节数)也可能因 ESP_ERR_TIMEOUT 而失败,但典型的流程如下所示:
尝试降低 I2C 总线速度解决了问题,但我必须降低到 20 kbps 才能进行通信。已经达到 30 kbps 时,通信经常失败。尝试以 100 甚至 400 kbps 的速度运行(就像我在 ESP-S3 上所做的那样)几乎总是会反复失败。浏览论坛,我发现有迹象表明 ESP32 的内部上拉电阻对于 I2C 总线来说可能太弱了,所以我尝试添加外部上拉电阻并在传递给 i2c_param_config 的配置中禁用内部电阻,但没有成功任何区别。 考虑到我可能有一个小故障,甚至可能在软件的其他地方,我使用 Wire 库抽象在 Arduino IDE 的一个小项目中重新实现了 I2C 通信的核心逻辑。该库简化了代码并为自己的错误留下了更少的空间,我实际上可以确认,当使用 Wire 库实现时,通信在 ESP32 上也按预期工作。 SP32 的 Wire 库的实现,我能发现的唯一明显相关的区别是在 esp32-hal-i2c.c 的函数 i2cInit 中,函数 i2c_set_timeout 是这样调用的: 代码:全选 i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT); 对于 ESP32,I2C_LL_MAX_TIMEOUT 通过多个定义转换为值 0xFFFFF。 将此函数调用添加到我的软件中也解决了那里的问题。我现在可以以 400 kbps(u-blox 芯片支持的最快速度)运行 I2C 总线,而不会遇到 ESP_ERR_TIMEOUT 错误的问题。 再次澄清一下:仅当代码在 ESP32 芯片上运行时才需要使用 i2c_set_timeout。当代码在 ESP32-S3 芯片上运行时,无需使用 i2c_set_timeout 即可运行。 由于此时文档非常薄弱,这里有两个问题: 使用 i2c_set_timeout 设置的超时与作为最后一个参数传递给其他读写函数的超时有什么区别?在 Wire 库中,传递给 i2c_set_timeout (0xFFFFF) 的值似乎转换为大约 13 毫秒(记录为 80 MHz 滴答数),传递给读/写函数的超时默认值设置为 50 毫秒。这对我来说没有明显的意义。 为什么i2c_set_timeout只需要在ESP32芯片上使用,而在ESP32-S3芯片上不需要?查看 Espressif 文档中链接的代码示例,我没有发现 i2c_set_timeout 函数的实际用法,而且我没有得到它应该是必需的印象。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
1906个成员聚集在这个小组
加入小组我的项目我做主,使用GN+Ninja来完成构建系统(VSCode开发RT106X)
36358 浏览 0 评论
NXP IMX8应用处理器快速入门必备:技巧、使用、设计指南
4395 浏览 0 评论
6050 浏览 1 评论
6763 浏览 0 评论
NXP i.MX6UL开发板(linux系统烧录+规格+硬件+模块移植)使用手册
4212 浏览 0 评论
619浏览 2评论
求助,S32G上Core M启动后如何让Core A在Flash指定位置加载uboot?
614浏览 2评论
ESP32-WROVER-IE + LAN8720以太网,GPIO0电压只有1.6v,无法正常进入spi flash boot模式如何解决?
605浏览 2评论
求分享适用于PN7160 Android的NFC工厂测试应用程序
694浏览 2评论
796浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 01:07 , Processed in 0.849183 second(s), Total 47, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号