STM32作为I2C从机与Jetson AGX通信故障排查求助
STM32 I2C从机与Jetson AGX通信故障排查
需求
将STM32 MCU作为I2C从机连接到Jetson AGX,实现Jetson通过i2cdetect、i2cset、i2cget命令扫描总线并完成寄存器读写操作。
硬件连接
采用STM32 NUCLEO-G071RB开发板作为I2C从机,接线如下:
- STM32 GND ↔ Jetson AGX 40针引脚9
- STM32 SCL(PB8) ↔ Jetson AGX 40针引脚5
- STM32 SDA(PB9) ↔ Jetson AGX 40针引脚3
软件配置
Jetson端
运行JetPack 4.6.0(Ubuntu 18.04),使用系统默认I2C驱动。
STM32端(STMCube IDE)
- I2C1配置:PB8设为SCL、PB9设为SDA,均启用内部上拉,通信速度100 KHz
- 从机地址设为0x20(7位地址)
- 初始化代码:
static void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.Timing = 0x00303D5B; hi2c1.Init.OwnAddress1 = 40; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } /** Configure Analogue filter */ if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) { Error_Handler(); } /** Configure Digital filter */ if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ }
- main循环逻辑(轮询模式):
switch (hi2c1.State) { case HAL_I2C_STATE_READY: /*!< Peripheral Initialized and ready for use */ status = HAL_I2C_Slave_Receive(&hi2c1, buf, 2, 1000); if (status == HAL_OK) status = HAL_I2C_Slave_Transmit(&hi2c1, buf, 2, 1000); break; };
问题现象
- 初始因电平不匹配(非3.3V),STM32所有I2C操作均应答失败
- 调整为3.3V电平后,STM32报告I2C状态为READY,但
HAL_I2C_Slave_Receive中等待ADDR标志置位的I2C_WaitOnFlagUntilTimeout函数超时失败 - Jetson端执行
sudo i2cdetect -y -r 8扫描总线,无任何设备响应
排查思路
1. 地址配置错误(核心疑点)
代码中hi2c1.Init.OwnAddress1 = 40是十进制值,对应十六进制0x28,但需求中从机地址是0x20(十进制32)。Jetson扫描的是0x20,而STM32监听的是0x28,必然无法匹配。需修改为:
hi2c1.Init.OwnAddress1 = 32; // 对应7位地址0x20
2. 硬件层面验证
- 信号检测:用示波器抓取SCL/SDA引脚波形,确认Jetson发送的起始信号、地址帧是否正常到达STM32
- 上拉电阻:STM32内部上拉可能不足,若接线距离较长或负载较大,需在SCL/SDA与3.3V之间添加10K~47K的外部上拉电阻
- 共地检查:确保STM32与Jetson的GND连接牢固,共地是I2C通信的必要条件
3. STM32 I2C配置优化
- 中断模式替代轮询:轮询模式在while循环中可能存在响应延迟,改用中断回调模式更可靠:
static uint8_t rx_done = 1; uint8_t buf[2]; HAL_StatusTypeDef status; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); while (1) { if (hi2c1.State == HAL_I2C_STATE_READY && rx_done) { rx_done = 0; status = HAL_I2C_Slave_Receive_IT(&hi2c1, buf, 2); } } } void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) { if (hi2c->Instance == I2C1) { // 接收完成后立即准备发送 HAL_I2C_Slave_Transmit_IT(&hi2c1, buf, 2); } } void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) { if (hi2c->Instance == I2C1) { // 发送完成,允许下一次接收 rx_done = 1; } } - 引脚复用确认:检查PB8/PB9是否被其他外设占用,确保CubeIDE中已正确配置为I2C功能
- 时钟拉伸:确认
NoStretchMode设为I2C_NOSTRETCH_DISABLE(代码中已正确设置),时钟拉伸是从机同步主机的关键
4. Jetson端配置验证
- 总线号确认:执行
i2cdetect -l列出所有I2C总线,确认总线8对应40针的I2C接口 - 速率匹配:将Jetson的I2C总线速率强制设为100KHz,与STM32匹配:
echo 100000 | sudo tee /sys/class/i2c-adapter/i2c-8/device/i2c-8/rate - 扫描模式调整:改用普通扫描模式(去掉
-r参数):sudo i2cdetect -y 8
5. 调试手段
- STM32寄存器调试:用调试器查看I2C的
SR1、SR2寄存器,确认ADDR标志是否被置位,或是否存在AF(应答失败)、BUSY(总线忙)等错误标志 - Jetson日志排查:执行
dmesg | grep i2c查看系统日志,确认是否有I2C通信的错误提示
内容的提问来源于stack exchange,提问作者Moti
相关产品推荐
相关产品推荐

