[其他ST产品] 关于STM32的IIC跟EEPROM通信为什么卡死在while

[复制链接]
1644|17
 楼主| csv7k1 发表于 2023-6-28 20:48 | 显示全部楼层 |阅读模式
关于STM32的IIC跟EEPROM通信为什么卡死在while(I2C_CheckEvent)的EV6事件还有为什么检测的是标志位及其怎样写等待写入操作完成函数问题跟解决方法

我们在写IIC跟EEPROM 通信的时候,会遇到读不出来的一个问题
实际上这是EEPROM这时候还在写入数据,然后我们的STM32的执行速度过快,然后就会卡死在while中
为什么会卡死在这个地方呢,
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); 而不是起始信号的地方?我们这里就有疑问了,明明前面还有一个检测应答啊,为什么这里没卡死


 楼主| csv7k1 发表于 2023-6-28 20:49 | 显示全部楼层
while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);
为什么在这卡死了呢。
91717649c2c3fa1304.png

大家看这个图,一开始是起始信号,然后紧接着是EV5事件,我们用while判断了这个事件,EV5事件代表的是SR1寄存器的位置1,这里肯定是没问题的,因为他判断的是32是否发送出去起始信号了,我们发送了,自然肯定是没毛病的。
 楼主| csv7k1 发表于 2023-6-28 20:51 | 显示全部楼层
第二个我们发送的地址,然后判断了EV6事件,然后程序在这个while中卡死,这是为什么呢,实际上是因为EEPROM在这个时候还在写入数据,我们发送了这个地址过去,然后没有产生应答,所以在这里出现了问题。
所以我们要解决的问题就是,让数据写入以后才继续读取,最简单的放大是写一个延时函数
上代码
  1.    void SysTick_Init_ms(uint16_t x)
  2. {
  3.          uint32_t i;
  4.     for(i=0;i<=x;i++);
  5. }

  6. int  main()
  7. {

  8.       USART_Configer();
  9.           printf("这是一个IIC通讯实验\n");
  10.           I2C_EEPROM_Configer();  
  11.           I2C_EEPROM_Write_Byte(11 , 0x52);
  12.           SysTick_Init_ms(0xffff);
  13.           I2C_EEPROM_Write_Byte(12 , 0x55);
  14.           EEPROM_WaitForWriteEnd();
  15.        
  16.           I2C_EEPROM_Read_Byte( 11, readData,2 );  
  17.           printf("\r\n接收到数据为0x%x\r\n",readData[0]);
  18.          while(1)
  19.          {
  20.          }
  21. }```
  22. 可以看到我们采取一个延时是没毛病的,这里我就不上结果的图了

  23. 第二个解决方法就是我们检测写入完成没有
  24.   void EEPROM_WaitForWriteEnd(void)
  25. {
  26.        
  27.         do
  28.         {
  29.                 //产生起始信号
  30.                 I2C_GenerateSTART(EEPROM_I2C,ENABLE);
  31.                
  32.                 while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_SB) == RESET);
  33.                
  34.                 //EV5事件被检测到,发送设备地址
  35.                 I2C_Send7bitAddress(EEPROM_I2C,0XA0,I2C_Direction_Transmitter);
  36.         }  
  37.         while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_ADDR) == RESET );

  38.         //EEPROM内部时序完成传输完成
  39.         I2C_GenerateSTOP(EEPROM_I2C,ENABLE);       
  40. }
  41. 或者把这段代码写到读取函数中
  42.    do
  43.         {
  44.                 //产生起始信号
  45.         I2C_GenerateSTART(EEPROM_I2C,ENABLE);
  46.                
  47.                 while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_SB) == RESET);
  48.        
  49.         //EV5事件被检测到,发送设备地址
  50.                 I2C_Send7bitAddress(EEPROM_I2C,0XA0,I2C_Direction_Transmitter);
  51.         }  
  52.         while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_ADDR) == RESET );
  53. I2C_GenerateSTOP(EEPROM_I2C,ENABLE);       
  54.        
  55.        
  56.   I2C_GenerateSTART(EEPROM_I2C,ENABLE);  //产生起始信号
  57.        
  58.         while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); //检测EV5
  59.        
  60.   I2C_Send7bitAddress(EEPROM_I2C,0XA0,I2C_Direction_Transmitter);  //发送设备地址
  61.        
  62.         while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);  //检查EV6
  63.        
  64.   I2C_SendData(EEPROM_I2C,addr);  //发送到EEPROM哪一个位地址
  65.        
  66.   while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR);

  67.        
  68.         //第二次
  69.         I2C_GenerateSTART(EEPROM_I2C,ENABLE);  
  70.        
  71.         while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
  72.        
  73.   I2C_Send7bitAddress(EEPROM_I2C,0XA0,I2C_Direction_Receiver);

  74.         while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)==ERROR);
  75.        
  76.         while(num)
  77.         {
  78.                  if(num==1)
  79.                  {
  80.                  I2C_AcknowledgeConfig (EEPROM_I2C,DISABLE);
  81.                  }
  82.                          while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);//检测EV7事件
  83.            *data=I2C_ReceiveData(EEPROM_I2C);
  84.                  
  85.                  data++;
  86.                  num--;
  87.         }
  88.        
  89.                 //数据传输完成
  90.         I2C_GenerateSTOP(EEPROM_I2C,ENABLE);       
  91.        
  92.         //重新配置ACK使能,以便下次通讯
  93.         I2C_AcknowledgeConfig (EEPROM_I2C,ENABLE);
  94. }
  95. 大家可能还会好奇为什么我们写一个停止信号,因为我们写了一个起始信号然后检测事件,发送地址,检测事件,我们要遵循I2C的,所以我们要发送结束信号,然后判断成功了以后,我们再重新发送起始信号等等操作

  96. 还有为什么要检测标志位,而不是检测事件呢,
  97. while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_SB) == RESET);

  98. while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_ADDR) == RESET );

  99.   这个经过我的Debug调试,如果写检测事件,就会在写入函数卡死,具体我也没去仔细看,总之使用flag就不会出现问题
  100.   大家也知道32跟EEPROM通信是有一些小问题的, 所以这里就不要去深究为什么判断标志位了

星辰大海不退缩 发表于 2023-6-30 13:08 | 显示全部楼层
卡死肯定是置1了,而且没有复位掉所以一直循环,程序逻辑上的判断应该还有问题
小小蚂蚁举千斤 发表于 2023-6-30 14:51 | 显示全部楼层
楼主还是确认一下卡死的原因吧,理论上分析可能没问题,还得理论结合实际
Undshing 发表于 2023-7-1 22:51 | 显示全部楼层
查一下是不是程序写的有问题
backlugin 发表于 2023-7-5 10:34 | 显示全部楼层
需要更详细地分析程序和硬件环境,包括查看寄存器状态、信号波形以及相关的配置等
elsaflower 发表于 2023-7-5 11:46 | 显示全部楼层
确认所使用的引脚、电平转换电路等硬件连接是否正确。
maudlu 发表于 2023-7-5 15:16 | 显示全部楼层
IIC的短延时是非常重要的              
eefas 发表于 2023-7-5 15:27 | 显示全部楼层
通信从机应答缺失 ?              
AloneKaven 发表于 2023-7-5 18:15 | 显示全部楼层
是不是标志位的问题啊?
saservice 发表于 2023-7-5 22:16 | 显示全部楼层
确配置I2C控制器并使能相应的时钟。
wangdezhi 发表于 2023-7-6 11:35 | 显示全部楼层
在while循环内,可以判断状态寄存器的标志位来检测通信是否完成,并设置适当的超时时间,如果超过预定时间仍未完成,则跳出循环。
maqianqu 发表于 2023-7-6 11:41 | 显示全部楼层
IIC的应答出现死循环导致的无法初始化
kkzz 发表于 2023-7-6 12:00 | 显示全部楼层
I2C通信设置超时机制,以避免无限等待。
mikewalpole 发表于 2023-7-6 15:57 | 显示全部楼层
如果总线被其他设备锁定或者存在通信冲突,可能导致卡死现象。
hearstnorman323 发表于 2023-7-6 16:18 | 显示全部楼层
以通过其他方式(例如示波器)验证设备的响应和数据传输情况。
Jacquetry 发表于 2023-7-6 23:11 | 显示全部楼层
没收到应答信号吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

72

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部