STM32F030F4裸机环境下I2C1无法正常启动问题求助(附代码)
解决STM32F030F4 I2C1 SDA无法正常工作的问题
我帮你排查了代码里的几个关键问题,这些大概率是导致SDA端口异常的核心原因,咱们一步步来修正:
1. 最关键的错误:外设时钟未正确使能
你的RCC配置完全没打开GPIOA和I2C1的时钟,这会导致这两个外设完全无法工作:
- GPIOA时钟:
RCC->AHBENR = 0x200000;这个值对应的是DMA1的时钟位(bit21),而GPIOA的时钟使能位是AHBENR的bit17,对应值为0x00020000(即1 << 17)。 - I2C1时钟:
RCC->APB1ENR = 0x4040;这个值开启的是USART2和SPI2的时钟,I2C1的时钟使能位是APB1ENR的bit21,对应值为0x2000000(即1 << 21)。
建议用|=操作来置位时钟位,避免直接赋值关闭其他外设的时钟,修正后的RCC配置:
// 开启GPIOA时钟 RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // 开启I2C1时钟 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
(如果你的开发环境没有定义RCC_AHBENR_GPIOAEN这些宏,直接用数值也可以:RCC->AHBENR |= 0x00020000; 和 RCC->APB1ENR |= 0x2000000;)
2. I2C配置的潜在问题
(1)CR2寄存器的FREQ字段需匹配总线时钟
I2C1->CR2 = 0x307001c; 里的FREQ字段(CR2的bit5~bit0)设置为0x30,对应48MHz的APB1总线时钟。你需要确保你的系统时钟配置确实让APB1运行在48MHz,否则TIMINGR的时序参数会不匹配,导致I2C通信时序错误。
(2)TXDR赋值超出寄存器范围
I2C1->TXDR = 0x111; 中,TXDR是8位寄存器,0x111是9位数据,会被自动截断为0x11。如果你要发送的是8位数据,请改为8位值,比如0x11。
(3)标准的I2C主发送流程
你的启动流程有点简略,正确的主模式发送步骤应该是:
// 设置从机地址(7位地址的话,SADD是地址左移1位,写模式末位为0) I2C1->CR2 = (0x1C << 1); // 对应你原来的0x1c,这里假设是7位地址写模式 // 设置要发送的字节数 I2C1->CR2 |= (7 << 16); // NBYTES=7,对应你原来的0x7 // 启动传输 I2C1->CR2 |= I2C_CR2_START; // 等待发送中断标志,然后发送数据 while(!(I2C1->ISR & I2C_ISR_TXIS)){} I2C1->TXDR = 0x11; // 改为8位数据 // 后续循环发送剩余字节,直到传输完成
3. 其他验证点
- 确认你的I2C总线上接了合适的上拉电阻(一般是4.7kΩ~10kΩ),STM32内部上下拉可能不足以驱动总线;
- 用示波器观察SCL和SDA引脚的波形,先确认时钟使能后GPIO是否有电平变化,再检查I2C启动后的时序是否符合标准。
内容的提问来源于stack exchange,提问作者peyman khalili
相关产品推荐
相关产品推荐

