之前在调试stm32的i2c花了很长时间,由于项目时间催的紧,硬件的i2c没能调试好,最后项目中采用了软件模拟的方式,由于软件等待时间CPU的效率有点低,后面自己花时间最终调通了硬件i2c,调试中自己的两点注意:1,调试i2c外接的器件接好一定要核对Ok(否则,后续努力也没用);2,要弄清i2c通信原理,多参考前人的经验。现在分享代码如下: void sReadI2C(INT8U* lubData,INT16U luwI2CAddr,INT8U lubDataLen) //从指定地址读取指定长度的数据 { INT8U i; // 等待总线空闲 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); I2C_TransferHandling(I2C1,EepromAddr,1,I2C_SoftEnd_Mode,I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS) == RESET); I2C_SendData(I2C1,luwI2CAddr); while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TC) == RESET); I2C_TransferHandling(I2C1,EepromAddr,lubDataLen,I2C_AutoEnd_Mode,I2C_Generate_Start_Read); for(i=0;i<lubDataLen;i++) { while(I2C_GetFlagStatus(I2C1,I2C_FLAG_RXNE) == RESET); lubData[i] = I2C_ReceiveData(I2C1); } while(I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF) == RESET); I2C_ClearFlag(I2C1, I2C_ICR_STOPCF); } //从指定地址开始写指定个数的数据 void I2C_uWriteData(INT8U *WriteBuf,INT16U WriteAddr,INT8U WriteLen) { INT8U i; // 等待总线空闲 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); I2C_TransferHandling(I2C1,EepromAddr,1,I2C_Reload_Mode,I2C_Generate_Start_Write); while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS) == RESET); I2C_SendData(I2C1,WriteAddr); while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TCR) == RESET); I2C_TransferHandling(I2C1,EepromAddr,WriteLen,I2C_AutoEnd_Mode,I2C_No_StartStop); for(i=0;i<WriteLen;i++) { while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS) == RESET); I2C_SendData(I2C1, WriteBuf[i]); } while(I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF) == RESET); I2C_ClearFlag(I2C1, I2C_ICR_STOPCF); } //eeprom不能跨页连续写数据,对跨页写的数据进行处理 void sWriteI2C(INT8U* lubData,INT16U luwI2CAddr,INT8U lubDataLen) { INT16U NumOfPage = 0,NumOfSingle = 0,Addr = 0; INT16U count = 0; Addr = luwI2CAddr % 16; count = 16 - Addr; NumOfPage = lubDataLen / 16; NumOfSingle = lubDataLen % 16; while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)); if(Addr == 0) { if(NumOfPage == 0) { I2C_uWriteData(lubData,luwI2CAddr,NumOfSingle); I2c_delayms(5); } else { while(NumOfPage--) { I2C_uWriteData(lubData,luwI2CAddr,16); I2c_delayms(5); luwI2CAddr += 16; lubData += 16; } if(NumOfSingle!=0) { I2C_uWriteData(lubData,luwI2CAddr,NumOfSingle); I2c_delayms(5); } } } else { if(NumOfPage== 0) { if (lubDataLen > count) { /* Write the data contained in same page */ I2C_uWriteData(lubData,luwI2CAddr,count); I2c_delayms(5); /* Write the remaining data in the following page */ I2C_uWriteData((INT8U*)(lubData + count),luwI2CAddr + count,lubDataLen - count); I2c_delayms(5); } else { I2C_uWriteData(lubData,luwI2CAddr,NumOfSingle); I2c_delayms(5); } } else { lubDataLen -= count; NumOfPage = lubDataLen / 16; NumOfSingle = lubDataLen % 16; if(count != 0) { I2C_uWriteData(lubData,luwI2CAddr,count); I2c_delayms(5); luwI2CAddr += count; lubData += count; } while(NumOfPage--) { I2C_uWriteData(lubData,luwI2CAddr,16); I2c_delayms(5); luwI2CAddr += 16; lubData += 16; } if(NumOfSingle != 0) { I2C_uWriteData(lubData,luwI2CAddr,NumOfSingle); I2c_delayms(5); } } } } |
【MCU实战经验】STM32F030芯片极限超频测试
【STM32F0开发日志】+STM32F030 修改官方提供的例程
【STM32F030开发日志/评测/笔记】+(2)STM32F0处理器I2C实例(...
STM32F030F4核心板自己整理的几个程序可以当模板参考(Keil MDK...
CubeMX之STM32F0 UART DMA接收的bug
【STM32F0开发日志】STM32F030 TIM3 4路PWM 输出
STM32F030F4P6 PWM输出呼吸灯
【实战经验】STM32F030低温下RTC不工作
STM32F042Nucleo Mbed PWM+L298N驱动12V直流电机
[STM32F072 Nucleo]开发笔记(三) 修改USB代码用于游戏方向盘
我也花了很长时间,
另外补充一句
注意第三个参数 ‘2’
I2C_TransferHandling(I2C1, driver_Addr, 2, I2C_Reload_Mode, I2C_Generate_Start_Write);
// 发一个控制字节加上 发两个字节地址