今天项目中要加入e2prom,由于之前购买了野火拂晓电机开发板,因此直接参考了野火的源码,不过参考的是野火骄阳电机开发板 (路径为:A盘(资料盘)\1-程序源码_教程文档\1-[野火]《STM32 HAL库开发实战指南》(HAL库源码)【优先学习】\野火STM32F407IG骄阳_HAL例程_1103\13-I2C-读写EEPROM)中的例程(估计拂晓开发板的例程也是一样)。在过代码时发现一处问题,问题代码位于User\i2c\bsp_i2c_ee.c中,如下所示:
/**
* @brief 将缓冲区中的数据写到I2C EEPROM中
* @param
* @arg pBuffer:缓冲区指针
* @arg WriteAddr:写地址
* @arg NumByteToWrite:写的字节数
* @retval 无
*/
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddr % EEPROM_PAGESIZE;
count = EEPROM_PAGESIZE - Addr;
NumOfPage = NumByteToWrite / EEPROM_PAGESIZE;
NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
/* If WriteAddr is I2C_PageSize aligned */
if(Addr == 0)
{
/* If NumByteToWrite < I2C_PageSize */
if(NumOfPage == 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
/* If NumByteToWrite > I2C_PageSize */
else
{
while(NumOfPage--)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, EEPROM_PAGESIZE);
WriteAddr += EEPROM_PAGESIZE;
pBuffer += EEPROM_PAGESIZE;
}
if(NumOfSingle!=0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
/* If WriteAddr is not I2C_PageSize aligned */
else
{
/* If NumByteToWrite < I2C_PageSize */
if(NumOfPage== 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
/* If NumByteToWrite > I2C_PageSize */
else
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / EEPROM_PAGESIZE;
NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
if(count != 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
}
while(NumOfPage--)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, EEPROM_PAGESIZE);
WriteAddr += EEPROM_PAGESIZE;
pBuffer += EEPROM_PAGESIZE;
}
if(NumOfSingle != 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
出问题的代码是这一段:
else
{
/* If NumByteToWrite < I2C_PageSize */
if(NumOfPage== 0)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
……
}
这段代码的本意是,要写入的地址不在一个page的起始位置(偏移为0)的情况下,要先完成本页剩余字节的写入,再开始写入新的页。但如果按照以上代码,只是简单判断了是否要写入的字节在小于page size(对于24c02来说page size为8字节),也就是说是(0~7),如果是则直接写入。这就存在问题了,如果向地址为7的地方写入了2个字节,则按照此处的代码,就直接写入2个字节了,但由于页写是不能够跨页的,因此在地址7处写了1个字节这后,会回到0地址,继续写入剩下的1个字节,而并非到地址8写入剩下的1个字节。因此,这段例程代码是不正确的。应该改为:
else
{
/* If NumByteToWrite < I2C_PageSize */
if(NumByteToWrite <= count) <----
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
……
}
修改后代码的意思是,当要写入的字节数小于等于本页剩余的字节数时,先写入本次要写入的字节数。比如在地址7时,只能写入1个字节;在地址6时,最多写2个字节;在地址5时,最多写入3个字节……之后再写入整页的字节,如果还有剩余,再写入剩余的。
举例来说,在地址5处,写入15个字节。先写入3个字节,将偏移到调整到页对齐的8,再写入page size个字节(24c02为8),此时还剩余15-3-8=4个字节,再写入这4个字节。如此功能就正常了。
将意见和代码发给了野火原厂的技术人员,他们已经认可并进行了测试,对代码进行了修正。以下是聊天记录截图:
|