野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 9486|回复: 2

库函数 I2C 例程重大 bug

[复制链接]
发表于 2017-4-25 09:40:21 | 显示全部楼层 |阅读模式
本帖最后由 国际哥 于 2017-4-25 09:40 编辑

在做作业“比较页写入和字节写入速度 ”时发现的问题——资料盘里固件库例程的程序应该是比视频中打的更为完善,然而在“等待 EEPROM 内部处理”的  I2C_EE_WaitEepromStandbyState() 函数上,固件库例程却比视频程序里同样功能的 Wait_for_EEPROM() 函数少了最后一句等待总线空闲的 while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_BUSY) == SET),直接导致连续调用 I2C_EE_ByteWrite 和 I2C_EE_WaitEepromStandbyState 函数连续写字节时只能写入一次,后面所有写操作都超时的错误

  1. // mian 函数中连续调用 I2C_EE_ByteWrite 函数写数据
  2. for (i = 0; i < 256; i++)  // 逐字节写入
  3. {
  4.            I2C_EE_ByteWrite(&I2c_Buf_Write[i], EEP_Firstpage+i);
  5.            I2C_EE_WaitEepromStandbyState();     
  6. }

复制代码


失败.png


  1. // bsp_i2c_ee.c
  2. void I2C_EE_WaitEepromStandbyState(void)      
  3. {
  4.   vu16 SR1_Tmp = 0;

  5.   do
  6.   {
  7.     /* Send START condition */
  8.     I2C_GenerateSTART(EEPROM_I2C, ENABLE);
  9.     /* Read EEPROM_I2C SR1 register */
  10.     SR1_Tmp = I2C_ReadRegister(EEPROM_I2C, I2C_Register_SR1);
  11.     /* Send EEPROM address for write */
  12.     I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  13.   }while(!(I2C_ReadRegister(EEPROM_I2C, I2C_Register_SR1) & 0x0002));

  14.   /* Clear AF flag */
  15.   I2C_ClearFlag(EEPROM_I2C, I2C_FLAG_AF);
  16.   /* STOP condition */   
  17.   I2C_GenerateSTOP(EEPROM_I2C, ENABLE);

  18.   while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_BUSY) == SET); //一定要加!!!总线空闲,执行下面的语句
  19. }

复制代码


而只要在 I2C_EE_WaitEepromStandbyState 函数最后加上 while 循环等待总线空闲即可解决。

把 I2C_EE_WaitEepromStandbyState 函数放在 I2C_EE_ByteWrite 函数体最前面即可实现外部循环调用 I2C_EE_ByteWrite 函数连续写字节。




  1. uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)
  2. {
  3.   I2C_EE_WaitEepromStandbyState();

  4.   // 原来的代码        
  5.   ...


  6. }
复制代码


  1. main 函数中直接循环调用 I2C_EE_ByteWrite 函数连续写字节
  2.   for (i = 0; i < 256; i++)
  3.    {
  4.            I2C_EE_ByteWrite(&I2c_Buf_Write[i], EEP_Firstpage+i);
  5.            //I2C_EE_WaitEepromStandbyState();     
  6.    }

复制代码



成功.png

其实视频里的程序都是好的,或许是精简考虑,固件库例程删减了看似不必要其实很重要的代码吧。
回复

使用道具 举报

 楼主| 发表于 2017-4-25 09:47:54 | 显示全部楼层
此外,程序逻辑上也稍微有点不严谨,判断是否操作成功是通过把 EEPROM 中的数据读出来与要写入的数据对比是否一致来实现,这就存在一个问题:如果 EEPROM 里原有的数据和我要写入的数据一样,即使此次写入失败的情况下也会提示成功。我改了一下程序,在定义数组时就把用语句 uint8_t I2c_Buf_Write[256] = {0}; 把所有元素赋值为 0,再把这一堆 0 写入 EEPROM 擦除原有数据,然后才进行真正的数据访问(读写),这样就排除了原有数据对结果的干扰。
回复 支持 反对

使用道具 举报

发表于 2017-4-26 16:53:35 | 显示全部楼层
正在学这个  等下看看
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-19 22:44 , Processed in 0.054630 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表