你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 HAL_I2C_Slave 从模式 为什么SCL会莫名拉低

[复制链接]
vrxiaochouyu 提问时间:2018-9-10 12:30 /
本帖最后由 vrxiaochouyu 于 2018-9-11 15:18 编辑

现象:
1,有时有应答,有时没有应答。(具体情况是,开机第一次显示未应答,然后报超时错误。第二次直接卡死,如图所示。等了15分钟之后报了遇忙错误。第三次,就真的卡死了。SLC一直为低,程序一点反应都没有)
2,有应答时,写入时时钟不见了。把主设备复位之后,SCL还是低的。为什么会把SCL拉低呢?

i2c即当主又当从。
做主的时候是给E2写数据,已经实现了,没出问题,可以排除硬件问题。

做从的时候是从芯片(另外一个芯片,该设备没有从模式)接收数据。难道是主从需要切换设置(轮巡代码里有设置模式啊)?还是因为STM32自身I2C BUG所致(从网上找了修改HAL_I2C_MspInit函数BUG的代码,然并卵)?
I2C.JPG

(更新)已从下面这篇文章解决卡死问题(并未根除,还偶尔卡死,但是概率低了很多)。但是还是没有应答。
解决STM32 I2C接口死锁在BUSY状态的方法讨论
然后波形是这样(PS:超时改为1,如果超时为100,依然是卡死)
i2c2.JPG
如果超时改为0,会是这样。这个后边的两个脉冲是怎么来的,难道是强制结束?
i2c1.JPG
我又使了地址全为0,还是一样。
123.JPG


(更新)已解决地址问题,原因是I2C信号太快了。读的信号是从第二个脉冲才开始的,所以永远都是错的。但还是有卡死问题。经常SCL就莫名的拉低了。貌似是和最开始差不多。最后截止的时候不应该给应答信号。但是应该如何解决呢?
OK.JPG

“6,当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。”难道和这个有关?

(更新)已解决,但是很崩溃。STM32一直在发应答。不发停止。如果size小于主机发的数量,就会卡死。只有遇到主机发停止,才会停止。自己不会停止。收不到停止就一直等啊等,就卡死了。 231.JPG


static void MX_I2C2_Init(void)
{


hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 100000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0xa0;//地址是A0
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;//这里应该如何设置?
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}


}



temp=UserRxBufferFS[i+1];//USB接收指令
HAL_UART_Transmit(&huart2,(uint8_t *)&temp,1,1000);//UART发送指令


if( HAL_I2C_Slave_Receive(&hi2c2, i2cdata, 10, 100)== HAL_OK); //i2c接收数据


while( CDC_Transmit_FS(i2cdata,10) != USBD_OK );//USB返回数据





















我自己又写了一个模拟的I2C从设备。有时报地址错误(a0变为4B),有时地址对了,但是没有给应答信号(报09错误,即没有收到第10个SLC)。求大神指正。int   I2C_slave()
{   
    GPIO_InitTypeDef GPIO_InitStruct;
    uint32_t   i,j=0;
    uint8_t   data, temp,stop;
      //I2C_SDA_1;      //释放SDA
   //SDA设为输入

    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   i=0;
   while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==1)
   { i++; if (i >=0xffff) {i=0;return 3;};};//start

     for  ( i=0; i<8; i++ )
     {
     while  (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
             { i++;if (i >=0xffff) {i=0;return 4;}; };   

       while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
               {i++;if (i >=0xffff) {i=0;return 5;};};

         temp=  HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
           data=data<<1;
      data=data|temp;
     }
     if( data!=0xa0)
     {if (data==0)return 15;
       else
       {
    return data;//ID
       }

     };

    GPIO_InitStruct.Pin = GPIO_PIN_7;                        //SDA设为输出
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  while  (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
             { i++;if (i >=0xffff) {i=0;return 6;}; };   

      I2C_SDA_0;//ack
        while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
               {i++;if (i >=0xffff) {i=0;return 7;};};
            while  (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
             { i++;if (i >=0xffff) {i=0;return 8;}; };   

          GPIO_InitStruct.Pin =GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
   // GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


  while(1)  
  {
          while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
               {i++;if (i >=0xffff) {i=0;return 9;};};

          temp=  HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
          if (temp==0)
          {
              while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
                 {i++;if (i >=0xffff) {i=0;return 10;};};
                stop=  HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
              if (stop==1){return 0;}//stop
          }
     data=data<<1;
      data=data|temp;
         for  ( i=0; i<7; i++ )
     {

       while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
               {i++;if (i >=0xffff) {i=0;return 11;};};

         temp=  HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
           data=data<<1;
      data=data|temp;
       while  (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
             { i++;if (i >=0xffff) {i=0;return 12;}; };   

     }

     i2cdata[j] =data;
     j++;
     if(j>63)return 2;//over
        GPIO_InitStruct.Pin = GPIO_PIN_7;                                           //SDA设为输出
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
      I2C_SDA_0;                                                                             //ack

        while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
               {i++;if (i >=0xffff) {i=0;return 13;};};
            while  (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==1)
             { i++;if (i >=0xffff) {i=0;return 14;}; };   

          GPIO_InitStruct.Pin =GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
   // GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


  }

}



























收藏 评论11 发布时间:2018-9-10 12:30

举报

11个回答
vrxiaochouyu 回答时间:2018-9-10 12:37:26
这个I2C口,又当主又当从,主的时候是给E2烧写。从的时候是被动接收芯片给发的数据。
wenyangzeng 回答时间:2018-9-10 12:54:18
IIC从设备的时钟由主设备提供

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

MrJiu 回答时间:2018-9-10 13:44:14
楼上说的完全OK,从机只有被动,时钟都是主发起的!!!

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

vrxiaochouyu 回答时间:2018-9-10 14:02:21
wenyangzeng 发表于 2018-9-10 12:54
IIC从设备的时钟由主设备提供

问题有歧义,稍作了更改。问题应该是,时钟后来怎么没了。写地址的时候还在,为什么写数据的时候就没了。
vrxiaochouyu 回答时间:2018-9-10 14:03:37
MrJiu 发表于 2018-9-10 13:44
楼上说的完全OK,从机只有被动,时钟都是主发起的!!!

问题的重点不在于谁发的时钟,而在于时钟怎么自己没了。SCL被强制拉低了。程序卡死了。
MrJiu 回答时间:2018-9-10 14:41:51
vrxiaochouyu 发表于 2018-9-10 14:03
问题的重点不在于谁发的时钟,而在于时钟怎么自己没了。SCL被强制拉低了。程序卡死了。 ...

SCL被强制拉低,有可能是从机。。。因为从机的scl的IO口配置必须是高阻态输入,也就是说,不能拉低。。。否则主机也没法输出高电平!!!
vrxiaochouyu 回答时间:2018-9-10 14:44:21
MrJiu 发表于 2018-9-10 14:41
SCL被强制拉低,有可能是从机。。。因为从机的scl的IO口配置必须是高阻态输入,也就是说,不能拉低。。。 ...

那么是代码哪里的问题,如何解决呢?用的是CUBE生成的代码呢
wenyangzeng 回答时间:2018-9-10 15:05:51
vrxiaochouyu 发表于 2018-9-10 14:02
问题有歧义,稍作了更改。问题应该是,时钟后来怎么没了。写地址的时候还在,为什么写数据的时候就没了。 ...

那应该是从设备的应答信号失败,主设备接收不到应答信号,自然没有读操作,时钟消失。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

MrJiu 回答时间:2018-9-10 15:53:03
vrxiaochouyu 发表于 2018-9-10 14:44
那么是代码哪里的问题,如何解决呢?用的是CUBE生成的代码呢

我一般不用ST的硬I2C。。。也没搞过I2C从机模式!!!如果是用Cube生成的代码,应该说配置是没问题的。。。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

yue_viper 回答时间:2018-9-10 17:31:38
E2是什么芯片啊?
vrxiaochouyu 回答时间:2018-9-11 09:58:21
wenyangzeng 发表于 2018-9-10 15:05
那应该是从设备的应答信号失败,主设备接收不到应答信号,自然没有读操作,时钟消失。 ...

但是从逻辑分析仪上看,已经给了应答信号了

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版