You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM Cortex-M3(GD32F130C8)I2C通信故障排查求助

GD32F130C8 与 MPU-6050 I2C 通信故障求助

我最近在做GD32F130C8(ARM Cortex-M3)和MPU-6050加速度计的I2C通信项目,用KEIL工具搭配GD32F1x0固件库开发,现在碰到了个头疼的问题:代码跑起来没有任何报错,但每秒周期性读取数据时,Accelerometer_X_High变量始终是0,完全读不到有效数据。

下面是我的硬件配置、关键代码和采集到的信号情况,想请教各位大佬:问题可能出在哪里?有哪些测试方法可以定位故障?


基础配置

  • 主设备:GD32F130C8
  • 从设备:MPU-6050加速度计
  • 通信总线:I2C0,引脚PB8(SCL)、PB9(SDA)

关键代码片段

地址定义

#define I2C_ACCELEROMETER_ADDRESS 0xD0 //( 0x68 + one bit)
#define I2C_OWN_ADDRESS 0x72

I2C引脚初始化

//Init I2C communication to accelerometer
// enable I2C0 clock
rcu_periph_clock_enable(RCU_I2C0);
// connect PB8 to I2C0_SCL
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8);
// connect PB9 to I2C0_SDA
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_9);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

I2C初始化函数

void I2C_Accelerometer_init(void){
 // configure I2C0 clock
 i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
 // configure I2C0 address
 i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_OWN_ADDRESS);
 // enable I2C0
 i2c_enable(I2C0);
 // enable acknowledge
 i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}

周期性读取数据的核心代码

这个函数由定时器每秒调用一次:

extern uint8_t Accelerometer_X_High;
//periodically called by timers in it.c
void GetAccelerometerData(void){
 uint8_t bytesToReadIndex=0;
 //WAKE UP ACCELEROMETER (6B 00)
 // wait until I2C bus is idle
 while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
 // send a start condition to I2C bus
 i2c_start_on_bus(I2C0);
 // wait until SBSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
 // send slave address to I2C bus
 i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER);
 // wait until ADDSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
 // clear ADDSEND bit
 i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
 // send a data byte
 i2c_data_transmit(I2C0,0x6B); //PWR MANAGEMENT
 // wait until the transmission data register is empty
 while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
 // send a data byte
 i2c_data_transmit(I2C0,0x00); //WAKE UP
 // wait until the transmission data register is empty
 while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
 // send a stop condition to I2C bus
 i2c_stop_on_bus(I2C0);
 while(I2C_CTL0(I2C0)&0x0200);

 //REQUEST ACELEROMETER DATA (3B )
 // wait until I2C bus is idle
 while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
 // send a start condition to I2C bus
 i2c_start_on_bus(I2C0);
 // wait until SBSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
 // send slave address to I2C bus
 i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_TRANSMITTER);
 // wait until ADDSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
 // clear ADDSEND bit
 i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
 // send a data byte
 i2c_data_transmit(I2C0,0x3B); //ACCELEROMETER REGISTER
 // wait until the transmission data register is empty
 while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
 // send a stop condition to I2C bus
 i2c_stop_on_bus(I2C0);
 while(I2C_CTL0(I2C0)&0x0200);

 //now reopen the bus to receive the reply
 // wait until I2C bus is idle
 while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
 // send a start condition to I2C bus
 i2c_start_on_bus(I2C0);
 // wait until SBSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
 // send slave address to I2C bus
 i2c_master_addressing(I2C0, I2C_ACCELEROMETER_ADDRESS, I2C_RECEIVER);
 // wait until ADDSEND bit is set
 while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
 // if we receive only one byte: reset ACKEN bit
 i2c_ack_config(I2C0, I2C_ACK_DISABLE);
 //clear ADDSEND bit
 i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
 // if we receive only one byte: send stop condition
 i2c_stop_on_bus(I2C0);
 /* wait until the RBNE bit is set */
 while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE));
 //read a data from I2C_DATA
 Accelerometer_X_High = i2c_data_receive(I2C0);
 // if we receive more bytes: send a stop condition to I2C bus
 //i2c_stop_on_bus(I2C0);
 while(I2C_CTL0(I2C0)&0x0200);
 // enable acknowledge
 i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}

示波器信号观察结果

我用示波器采集了I2C总线的信号,发现通信周期中存在异常尖峰,这些尖峰可能干扰了正常的时序同步。


想请教的问题

  1. 从代码或硬件配置上看,可能存在哪些问题导致读回的数据始终为0?
  2. 可以执行哪些具体的测试步骤来逐步定位故障点?

内容的提问来源于stack exchange,提问作者Gaucho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:59:01