硬汉嵌入式论坛

 找回密码
 立即注册
查看: 558|回复: 8
收起左侧

[I2C] STM32H7硬件I2C的监听功能

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106840
QQ
发表于 2023-8-21 10:15:14 | 显示全部楼层 |阅读模式


反应到硬件I2C上,实际就是个地址匹配中断

[C] 纯文本查看 复制代码
/**
  * @brief  Enable the Address listen mode with Interrupt.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c)
{
  if (hi2c->State == HAL_I2C_STATE_READY)
  {
    hi2c->State = HAL_I2C_STATE_LISTEN;
    hi2c->XferISR = I2C_Slave_ISR_IT;

    /* Enable the Address Match interrupt */
    I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

/**
  * @brief  Disable the Address listen mode with Interrupt.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c)
{
  /* Declaration of tmp to prevent undefined behavior of volatile usage */
  uint32_t tmp;

  /* Disable Address listen mode only if a transfer is not ongoing */
  if (hi2c->State == HAL_I2C_STATE_LISTEN)
  {
    tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK;
    hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode);
    hi2c->State = HAL_I2C_STATE_READY;
    hi2c->Mode = HAL_I2C_MODE_NONE;
    hi2c->XferISR = NULL;

    /* Disable the Address Match interrupt */
    I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

回复

使用道具 举报

3

主题

96

回帖

105

积分

初级会员

积分
105
发表于 2023-8-21 11:08:08 | 显示全部楼层
休眠的时候可以使用吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106840
QQ
 楼主| 发表于 2023-8-21 11:11:29 | 显示全部楼层
2859932063 发表于 2023-8-21 11:08
休眠的时候可以使用吗?

I2C有个地址匹配时从停止模式唤醒的功能,就是类似的用法。
回复

使用道具 举报

3

主题

96

回帖

105

积分

初级会员

积分
105
发表于 2023-8-21 11:30:54 | 显示全部楼层
eric2013 发表于 2023-8-21 11:11
I2C有个地址匹配时从停止模式唤醒的功能,就是类似的用法。

硬汉大神,我还是想问问我使用寄存器PC0点灯的问题
         *(volatile unsigned int*) (0x58024400+0xE0)=(1<<2);//RCC->AHB4ENR->GPIOC
         *(volatile unsigned int*) 0x58020800|=(0x01<<0);//GPIOC->MODEL-> 01 ->通用输出
         *(volatile unsigned int*) 0x58020814&=~(1<<0);//ODR  
使用上面的方式我初始化了时钟,端口模式,还有ODR,看手册是对了的,但是点不亮。后面我测了一下,时钟使能是对的,ODR也是对的。但是MODEL的寄存器让我发现一个很奇怪的点。上面的寄存器点不了。但是把代码改成      
  *(volatile unsigned int*) (0x58024400+0xE0)=(1<<2);//RCC->AHB4ENR->GPIOC
   *(volatile unsigned int*) 0x58020800&=(0x01<<0);//GPIOC->MODEL-> 01 ->通用输出
不使用ODR的寄存器的情况下还是能把PC0点亮,这是我非常疑惑的点,想问问硬汉大神
回复

使用道具 举报

3

主题

96

回帖

105

积分

初级会员

积分
105
发表于 2023-8-21 11:35:30 | 显示全部楼层
eric2013 发表于 2023-8-21 11:11
I2C有个地址匹配时从停止模式唤醒的功能,就是类似的用法。

说错了,应该是        
*(volatile unsigned int*) (0x58024400+0xE0)=(1<<2);//RCC->AHB4ENR->GPIOC
*(volatile unsigned int*) 0x58020800&=~(0x01<<0);//GPIOC->MODEL-> 01 ->通用输出

为什么这样就可以直接让PC0输出低电平。手册中是01才是通用输出
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106840
QQ
 楼主| 发表于 2023-8-21 11:45:59 | 显示全部楼层
2859932063 发表于 2023-8-21 11:30
硬汉大神,我还是想问问我使用寄存器PC0点灯的问题
         *(volatile unsigned int*) (0x58024400+0x ...

这个不是很简单的吗,还没有搞定。。。

我分享个写法。
回复

使用道具 举报

3

主题

96

回帖

105

积分

初级会员

积分
105
发表于 2023-8-21 11:58:48 | 显示全部楼层
eric2013 发表于 2023-8-21 11:45
这个不是很简单的吗,还没有搞定。。。

我分享个写法。

好的,谢谢硬汉大神
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106840
QQ
 楼主| 发表于 2023-8-21 13:06:56 | 显示全部楼层
2859932063 发表于 2023-8-21 11:58
好的,谢谢硬汉大神

=========配置=============================
        *((__IO uint32_t*)0x580244e0)|= 0x00000004; // 时钟

        tmp = *((__IO uint32_t*)0x58020808);
        tmp &= ~0x00000003;
        tmp |= 0x00000002;
        *((__IO uint32_t*)0x58020808) = tmp;   //速度

        tmp = *((__IO uint32_t*)0x58020804) ;
        tmp &= ~0x00000001;
        tmp |= 0x00000000;
        *((__IO uint32_t*)0x58020804) = tmp;   //推挽

        tmp = *((__IO uint32_t*)0x5802080c);
        tmp &= ~0x00000003;
        tmp |= 0x00000001;
        *((__IO uint32_t*)0x5802080c) = tmp;   //上拉

        tmp = *((__IO uint32_t*)0x58020800);
        tmp &= ~0x00000003;
        tmp |= 0x00000001;
        *((__IO uint32_t*)0x58020800) = tmp;   //模式


============翻转=============
        *((__IO uint32_t*)0x58020818) = 1 << 0;
         HAL_Delay(10);
        *((__IO uint32_t*)0x58020818) = 1 << 16;

      HAL_Delay(10);

=========================


回复

使用道具 举报

3

主题

96

回帖

105

积分

初级会员

积分
105
发表于 2023-8-21 13:46:31 | 显示全部楼层
eric2013 发表于 2023-8-21 13:06
=========配置=============================
        *((__IO uint32_t*)0x580244e0)|= 0x00000004; // ...

感谢硬汉大神
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-7 07:43 , Processed in 0.193020 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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