stm32f030的i2c(eeprom)调试分享
之前在调试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 = 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);
}
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);
}
}
}
}
谢谢楼主,i2c让很多工程师发愁;P bucuo:):):) 很的很详细 晚上好!谢谢楼主分享。 在i2c上花时间比读学前班的时间长,从4位MCU、8位MCU、16位MCU、32位MCU、MPU。 本帖最后由 alisa123 于 2017-8-11 10:42 编辑
samhong 发表于 2017-8-10 21:49
在i2c上花时间比读学前班的时间长,从4位MCU、8位MCU、16位MCU、32位MCU、MPU。
我也花了很长时间,:handshake:handshake 您好楼主,我最近也在调试IIC,但是按着还是卡在 while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS) == RESET); 来试试楼主代码。多谢。 非常有用的文章
另外补充一句
注意第三个参数 ‘2’
I2C_TransferHandling(I2C1, driver_Addr, 2, I2C_Reload_Mode, I2C_Generate_Start_Write);
// 发一个控制字节加上 发两个字节地址 谢谢分享
页:
[1]