STM32 LL库 I2C的个人笔记

I2C一直是特别常用的总线,之前用八位机的时候有好多是用单片机模拟的I2C或者类I2C,I2C两跟线,数据线和时钟线,在这里不做I2C时序的介绍(STM32手册里有,以及一些I2C的EPROM都会有很详细的介绍),这里只是对程序的笔记

打开官方例程的I2C的工程,工程名字是I2C_OneBoard_Communication_PollingAndIT,他用了一块板子I2C3做主机,I2C1做从机,打开工程后会看到一下两个函数
在这里插入图片描述
在这里插入图片描述
从以上函数,可以知道,当设置好器件地址和传送的数据宽度以及模式后,它直接发送了一个数组的数据,但是基本的I2C的操作逻辑是,器件地址 ->寄存器地址->数据,所以要对改工程进行修改。

看看它从机`中断里是怎么写的:

void I2C1_EV_IRQHandler(void)
{
  /* Check ADDR flag value in ISR register */
  if(LL_I2C_IsActiveFlag_ADDR(I2C1))
  {
    /* Verify the Address Match with the OWN Slave address */
    if(LL_I2C_GetAddressMatchCode(I2C1) == SLAVE_OWN_ADDRESS)
    {
      /* Verify the transfer direction, a write direction, Slave enters receiver mode */
      if(LL_I2C_GetTransferDirection(I2C1) == LL_I2C_DIRECTION_WRITE)
      {
        /* Clear ADDR flag value in ISR register */
        LL_I2C_ClearFlag_ADDR(I2C1);

        /* Enable Receive Interrupt */
        LL_I2C_EnableIT_RX(I2C1);
      }
      else
      {
        /* Clear ADDR flag value in ISR register */
        LL_I2C_ClearFlag_ADDR(I2C1);

        /* Call Error function */
        Error_Callback();
      }
    }
    else
    {
      /* Clear ADDR flag value in ISR register */
      LL_I2C_ClearFlag_ADDR(I2C1);
        
      /* Call Error function */
      Error_Callback();
    }
  }
  /* Check RXNE flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_RXNE(I2C1))
  {
    /* Call function Slave Reception Callback */
    Slave_Reception_Callback();
  }
  /* Check STOP flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_STOP(I2C1))
  {
    /* End of Transfer */
    LL_I2C_ClearFlag_STOP(I2C1);
    
    /* Call function Slave Complete Callback */
    Slave_Complete_Callback();
  }
  else
  {
    /* Call Error function */
    Error_Callback();
  }
}


void Slave_Reception_Callback(void)
{
  /* Read character in Receive Data register.
  RXNE flag is cleared by reading data in RXDR register */
  aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
}


/*看完整个代码后会发现,会更加清晰的了解I2C的工作流程,并且它读到数据之后,直接送到了寄存器里,其实这样也是未尝不可的,但是要是
做Arduino或者树莓派的从机的话,最好还是符合常规的写法*/

修改回调函数代码,并且在每次进入中断判断地址后是写之后,清除ubReceiveIndex的值

void Slave_Reception_Callback(void)
{
	if(ubReceiveIndex == 0)
		ubReceiveIndex = LL_I2C_ReceiveData8(I2C1); 
	else
  		aReceiveBuffer[ubReceiveIndex] = LL_I2C_ReceiveData8(I2C1);
}

测试,并且在从机加入发数据的中断代码

从机中断代码

void I2C1_EV_IRQHandler(void)
{
  /* Check ADDR flag value in ISR register */
  if(LL_I2C_IsActiveFlag_ADDR(I2C1))
  {
    /* Verify the Address Match with the OWN Slave address */
    if(LL_I2C_GetAddressMatchCode(I2C1) == SLAVE_OWN_ADDRESS)
    {
      /* Verify the transfer direction, a write direction, Slave enters receiver mode */
      if(LL_I2C_GetTransferDirection(I2C1) == LL_I2C_DIRECTION_WRITE)
      {
        /* Clear ADDR flag value in ISR register */
		 ubReceiveIndex =0; 
        LL_I2C_ClearFlag_ADDR(I2C1);
        /* Enable Receive Interrupt */
        LL_I2C_EnableIT_RX(I2C1);
      }
      else
      {
        /* Clear ADDR flag value in ISR register */
        LL_I2C_ClearFlag_ADDR(I2C1);
		LL_I2C_ClearFlag_TXE(I2C1); 
		LL_I2C_EnableIT_TX(I2C1);
      }
    }
    else
    {
      /* Clear ADDR flag value in ISR register */
      LL_I2C_ClearFlag_ADDR(I2C1);
        
      /* Call Error function */
      Error_Callback();
    }
  }
  /* Check RXNE flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_TXIS(I2C1))
  {
	LL_I2C_TransmitData8(I2C1, aReceiveBuffer[ubReceiveIndex]);
  }	
  else if(LL_I2C_IsActiveFlag_RXNE(I2C1))
  {
    /* Call function Slave Reception Callback */
    Slave_Reception_Callback();
  }
  /* Check STOP flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_STOP(I2C1))
  {
    /* End of Transfer */
    LL_I2C_ClearFlag_STOP(I2C1);
    
    /* Call function Slave Complete Callback */
    Slave_Complete_Callback();
  }
  else
  {
    /* Call Error function */
    Error_Callback();
  }
}

主机代码

	/*在从机地址为0x01的寄存器里写0xff,并且把它读出来*/
	LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
	
	while(!LL_I2C_IsActiveFlag_TXIS(I2C3))
    { 
    }	
	LL_I2C_TransmitData8(I2C3,0x01);

	while(!LL_I2C_IsActiveFlag_TXIS(I2C3))
    { 
    }	
	LL_I2C_TransmitData8(I2C3,0xff);
		
	
	LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
	while(!LL_I2C_IsActiveFlag_TXIS(I2C3))
    { 
    }
	LL_I2C_TransmitData8(I2C3,0x01);
	
	LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND,LL_I2C_GENERATE_START_READ);
	while(!LL_I2C_IsActiveFlag_RXNE(I2C3))
	{		
	}
	test = LL_I2C_ReceiveData8(I2C3);

实验结果
STM32 LL库 I2C的个人笔记_第1张图片STM32 LL库 I2C的个人笔记_第2张图片

你可能感兴趣的:(单片机)