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

STM32 F429ZI开发板I2C回环测试故障排查求助

STM32 F429ZI I2C主从通信故障排查

问题概述

使用STM32 F429ZI开发板进行I2C协议测试,配置I2C1为主机、I2C2为从机,但通信无法正常运行。代码卡在while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ))处,推测I2C2(从机)未生成ACK信号。当前使用MCU内部上拉电阻,询问是否需要改用外部上拉电阻。

故障代码

char receivedata;
#define SLAVE_ADDRESS 0x3D
char senddata = 0xAA; // 补充未定义的变量

void I2C1_Init(){
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);

    GPIO_InitTypeDef GPIOB_InitStruct = {
                .GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7,
                .GPIO_Mode = GPIO_Mode_AF,
                .GPIO_Speed = GPIO_Speed_50MHz,
                .GPIO_OType = GPIO_OType_OD,
                .GPIO_PuPd = GPIO_PuPd_UP
            };

    GPIO_Init(GPIOB, &GPIOB_InitStruct);

    I2C_InitTypeDef I2C1_InitStruct={
            .I2C_Ack=I2C_Ack_Enable,
            .I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit,
            .I2C_ClockSpeed=100000,
            .I2C_DutyCycle=I2C_DutyCycle_2,
            .I2C_Mode=I2C_Mode_I2C,
            .I2C_OwnAddress1=0x00,
    };

    I2C_Init(I2C1, &I2C1_InitStruct);
    I2C_Cmd(I2C1, ENABLE);

}

void I2C2_Init(){
    // 先配置NVIC分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

    GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_I2C2);
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_I2C2);

    GPIO_InitTypeDef GPIOF_InitStruct = {
                .GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1,
                .GPIO_Mode = GPIO_Mode_AF,
                .GPIO_Speed = GPIO_Speed_50MHz,
                .GPIO_OType = GPIO_OType_OD,
                .GPIO_PuPd = GPIO_PuPd_UP
            };

    GPIO_Init(GPIOF, &GPIOF_InitStruct);

    I2C_InitTypeDef I2C2_InitStruct={
            .I2C_Ack=I2C_Ack_Enable,
            .I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit,
            .I2C_ClockSpeed=100000,
            .I2C_DutyCycle=I2C_DutyCycle_2,
            .I2C_Mode=I2C_Mode_I2C,
            .I2C_OwnAddress1=SLAVE_ADDRESS,
    };

    I2C_Init(I2C2, &I2C2_InitStruct);
    I2C_Cmd(I2C2, ENABLE);

    I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);

    NVIC_InitTypeDef NVIC_InitStruct={
            .NVIC_IRQChannel=I2C2_EV_IRQn,
            .NVIC_IRQChannelCmd=ENABLE ,
            .NVIC_IRQChannelPreemptionPriority=1,
            .NVIC_IRQChannelSubPriority=1,
    };
    NVIC_Init(&NVIC_InitStruct);
}

void I2C1_start(){
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

    I2C_GenerateSTART(I2C1, ENABLE);

    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));


    I2C_Send7bitAddress(I2C1, (SLAVE_ADDRESS)<<1, I2C_Direction_Transmitter);

    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ));


}

// 修正拼写错误:sned -> send
void I2C1_send(char data){
    I2C_SendData(I2C1, data);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

void I2C2_EV_IRQHandler(){
    switch(I2C_GetLastEvent(I2C2)){

        case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
            // 地址匹配后无需额外操作,硬件自动发送ACK
            break;
        // 修正事件类型:从机接收字节的事件是RECEIVER_BYTE_RECEIVED
        case I2C_EVENT_SLAVE_RECEIVER_BYTE_RECEIVED:
            receivedata=I2C_ReceiveData(I2C2);
            break;
        default:
            break;
    }

}

int main(){
    I2C1_Init();
    I2C2_Init();
    while(1){
        I2C1_start();
        I2C1_send(senddata);
        I2C_GenerateSTOP(I2C1,ENABLE);
        // 增加延时,避免连续发送导致总线异常
        for(uint32_t i=0;i<1000000;i++);
    }
    return 0;
}

问题分析与解决建议

1. 代码逻辑错误

  • 中断事件类型错误:原代码中从机中断使用I2C_EVENT_SLAVE_BYTE_TRANSMITTED,这是从机发送字节完成的事件,但当前从机处于接收模式,应改为I2C_EVENT_SLAVE_RECEIVER_BYTE_RECEIVED,才能正确触发数据接收操作。
  • NVIC配置顺序错误:NVIC_PriorityGroupConfig必须在NVIC_Init之前调用,否则分组配置不生效,可能导致中断无法正常响应。
  • 变量未定义与拼写错误:senddata未定义,I2C1_sned拼写错误,这些会导致编译或运行异常。
  • 无发送间隔:主循环中连续发送I2C数据,未添加延时,可能导致总线状态异常。

2. 上拉电阻问题

内部上拉电阻阻值通常在20k~50kΩ之间,对于100kHz的低速I2C总线,短距离、轻负载场景下可以正常工作。但如果存在以下情况,建议更换为4.7kΩ外部上拉电阻:

  • PCB走线过长(超过1米)或布线干扰大;
  • 总线上挂载多个设备,负载较重;
  • 实测总线电平信号抖动大、上升沿过缓。

3. 硬件连接检查

确认I2C1与I2C2的总线引脚正确连接:

  • I2C1_SDA(PB6) ↔ I2C2_SDA(PF0)
  • I2C1_SCL(PB7) ↔ I2C2_SCL(PF1)

先修正代码中的逻辑错误,测试通信是否恢复;若仍无ACK信号,再尝试更换外部上拉电阻。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 01:30:59