小言_互联网的博客

I2C 主从模式切换 总结 IPMB

347人阅读  评论(0)

 

项目健康管理模块IPMB,针对协议要求对I2C总结上的节点设备,每一个可以作为主设备去访问从设备的信息。

 

作为发起者,上电启动后主节点为主模式,发起请求消息;从节点在接收到主节点发送的请求消息后,主节点转换为从模式,从节点转换为主模式。从节点发送消息到目的节点,完成通信过程。

 

此协议遵循SMBUS协议。

 

项目基于stm32 设计完成IPMB健康管理,关键点在于主从模式的切换,首先要挂接中断,当为主模式时,关接收中断;当为从模式时打开中断。代码实现如下所示:

I2C配置实现:

void I2C1_Configuration(void)
{
  I2C_InitTypeDef I2C_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    I2C_DeInit(I2C1);
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = I2C1_Slave_Address;                           //�ӻ���ַ
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;
    I2C_Init(I2C1, &I2C_InitStructure);

    
    NVIC_InitStructure.NVIC_IRQChannel                   = I2C1_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                 //�����ȼ�
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, ENABLE);   //ʹ���ж�
  I2C_Cmd(I2C1, ENABLE);                                             //ʹ��I2C
}

中断函数实现:

void I2C1_EV_IRQHandler(void)
{

  __IO uint32_t SR1Register =0;
  __IO uint32_t SR2Register =0;

  Recvmark = 1;

  SR1Register = I2C1->SR1;
  SR2Register = I2C1->SR2;
	
  /* I2C1�Ǵӻ�(MSL = 0) */
  if((SR2Register &0x0001) != 0x0001)
  {
    /* �����ѷ�����ַ(ADDR = 1: EV1) */
    if((SR1Register & 0x0002) == 0x0002)
    {
      /* �����־��׼���������� */
      SR1Register = 0;
      SR2Register = 0;
			
	  Rx_Idx_IIC1=0;
	  Tx_Idx_IIC1=0;
    }
		
    /* ��������(RXNE = 1: EV2) */
    if((SR1Register & 0x0040) == 0x0040)
    {
      Buffer_Rx_IIC1[Rx_Idx_IIC1++] = I2C1->DR;
      SR1Register = 0;
      SR2Register = 0;
    }
    /* ��⵽ֹͣ����(STOPF =1: EV4) */
    if(( SR1Register & 0x0010) == 0x0010)
    {
      I2C1->CR1 |= 0x0001;
      SR1Register = 0;
      SR2Register = 0;
      Flag_RcvOK_IIC1 = 1; 			
    }
		
	/* ��������(TxE = 1: EV3) */
    if((SR1Register & 0x0080) == 0x0080)
    {
	  I2C1->DR = Response_Message[Tx_Idx_IIC1++];	
      SR1Register = 0;
      SR2Register = 0;
    }
    /* ��⵽��Ӧ��(AF =1: EV3-2) */
    if(( SR1Register & 0x0400) == 0x0400)
    {
			I2C1->SR1 &= 0xFDFF;
      SR1Register = 0;
      SR2Register = 0;		
    }		
  }
	
}

 

开关中断操作:主发送之前关闭中断,从接收时打开中断。

I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, ENABLE);  //使能中断

I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, DISABLE); //关闭中断

一般设计中,对于总线主模式,数据发送为抢占总线的操作,主模式在执行完总线发送需求后自动切换为从模式。

I2C允许多主站模式,数据发送采用总线竞争发送。


转载:https://blog.csdn.net/m0_37585897/article/details/102571901
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场