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
相关产品推荐
相关产品推荐

