LL库实现I2C硬件从机

1,我这里是还是使用CubeMX直接生成代码,其实也没啥好说的,直接看配置。

LL库实现I2C硬件从机_第1张图片

然后在ProjectManager里面设置为LL库即可。

2,添加中断使能函数,因为我这里是用中断收发的,所以需要使能,后续所有的操做都在中断里面,主函数while里面啥也不用写。

中断函数:

int ubReceiveIndex=0;
int ubSendIndex=0;
uint8_t aReceiveBuffer[10] = {0};

void I2C1_IRQHandler(void)
{
  /* USER CODE BEGIN I2C1_IRQn 0 */
	int addr = 0;
  if(LL_I2C_IsActiveFlag_ADDR(I2C1))
  {
    /* Verify the Address Match with the OWN Slave address */
		addr = LL_I2C_GetAddressMatchCode(I2C1);
		printf("addr:%x\r\n",addr);
    if(addr == SLAVE_ADDR)
    {
      /* 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);
        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 */
			goto iic_bus_error;
    }
  }
  /* Check TXIS flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_TXIS(I2C1))
  {
    LL_I2C_TransmitData8(I2C1, aReceiveBuffer[ubSendIndex++]);
    printf("TXIS:%x\t%x\r\n",aReceiveBuffer[ubSendIndex],aReceiveBuffer[ubSendIndex]);
  } 
	/* Check TXE flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_TXE(I2C1))
  {
    LL_I2C_TransmitData8(I2C1, aReceiveBuffer[ubSendIndex++]);
    printf("TXE:%x\t%x\r\n",aReceiveBuffer[ubSendIndex],aReceiveBuffer[ubSendIndex]);
  }
  /* Check NACK flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_NACK(I2C1))
  {
		LL_I2C_ClearFlag_NACK(I2C1);
		printf("NACK\r\n");
  }
  /* Check RXNE flag value in ISR register */
  else if(LL_I2C_IsActiveFlag_RXNE(I2C1))
  {
    /* Call function Slave Reception Callback */
		uint8_t recvData = LL_I2C_ReceiveData8(I2C1);
		printf("ubReceiveIndex:%x,LL_I2C_ReceiveData8:%x\r\n",ubReceiveIndex,recvData);
		/* Read character in Receive Data register. RXNE flag is cleared by reading data in RXDR register */
		aReceiveBuffer[ubReceiveIndex++] = recvData;
  }
  /* 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 */
    ubReceiveIndex =0; 
    ubSendIndex = 0;
  }
  else
  {
    /* Call Error function */
iic_bus_error:		
		printf("Error_Callback:");
		LL_I2C_DeInit(I2C1);
		MX_I2C1_Init();
		LL_I2C_EnableIT_RX(I2C1);
		LL_I2C_EnableIT_TX(I2C1);
		LL_I2C_EnableIT_ADDR(I2C1);
		LL_I2C_EnableIT_STOP(I2C1);
		LL_I2C_EnableIT_ERR(I2C1);
  }
	
  /* USER CODE END I2C1_IRQn 0 */

  /* USER CODE BEGIN I2C1_IRQn 1 */

  /* USER CODE END I2C1_IRQn 1 */
}

3,然后我们同样生成一个主机测试程序,为了简单这里我直接使用hal库,然后在while里面调用发送以及接受即可。

uint8_t reg_addr = 0;
uint8_t buf[10] = {0};
  
while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(HAL_I2C_Master_Transmit(&hi2c1, 0x55, buf, sizeof(buf), 1000) != HAL_OK)
		{
			HAL_Delay(2000);
		}
		HAL_Delay(1000);
		
		if(HAL_I2C_Master_Receive(&hi2c1, 0x55, buf, sizeof(buf), 1000) != HAL_OK)
		{
			HAL_Delay(2000);
		}
		HAL_Delay(1000);
		
		
//		if(HAL_I2C_Mem_Write(&hi2c1, 0x55, reg_addr, I2C_MEMADD_SIZE_8BIT, buf, 5, 1000) != HAL_OK)
//		{
//			HAL_Delay(2000);
//		}
//		HAL_Delay(1000);
//		
//		if(HAL_I2C_Mem_Read(&hi2c1, 0x55, reg_addr, I2C_MEMADD_SIZE_8BIT, buf, 5, 1000) != HAL_OK)
//		{
//			HAL_Delay(2000);
//		}
//		HAL_Delay(1000);
		
  }

这里简单说下

HAL_I2C_Master_Transmit

HAL_I2C_Master_Receive

这两个函数相当于是直接发一包数据过去,如果想要单独读取某一个寄存器的数据的话得在填入得buf第一个字节写上寄存器地址,或者直接使用下面的函数

HAL_I2C_Mem_Write

HAL_I2C_Mem_Read

参考了以下代码:STM32L031F6 LL库硬件I2C使用,中断模式_51CTO博客_stm32硬件i2c

你可能感兴趣的:(stm32,单片机,mcu,嵌入式硬件)