STM32 使用 LL库进行I2C读写

为什么要使用LL库,因为生成的固件大小可以小很多很多,MCU贵呀,可以省很多成本了。


 

uint8_t i2c_read_len(I2C_TypeDef *I2Cx,  uint8_t Addr , uint8_t Reg, uint8_t len,uint8_t *buf);

uint8_t i2c_write_len(I2C_TypeDef *I2Cx,  uint8_t addr , uint8_t reg, uint8_t len,uint8_t *buf);

实现这两个函数,理论上全部写需求都好了,网上的例子不知道为什么不可用,同时网上的例子也不支持多字节读写,参考了HAL I2C的代码实现,调通可用,如下:


uint8_t i2c_read_len(I2C_TypeDef *I2Cx,  uint8_t Addr , uint8_t Reg, uint8_t len,uint8_t *buf)
{
   
	/* 1.保证I2C外设不在使用中. */
    while(LL_I2C_IsActiveFlag_BUSY(I2Cx));
	
	    /* Check if the I2C is already enabled */
    if ((I2Cx->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
    {
      /* Enable I2C peripheral */
      LL_I2C_Enable(I2Cx);
    }

    /* Disable Pos */
    CLEAR_BIT(I2Cx->CR1, I2C_CR1_POS);

		/* Enable Acknowledge */
		SET_BIT(I2Cx->CR1, I2C_CR1_ACK);
		
  /* 2.发送START信号 */
    LL_I2C_GenerateStartCondition(I2Cx);
    while(!LL_I2C_IsActiveFlag_SB(I2Cx));

  /* 2.写器件地址 */
    LL_I2C_TransmitData8(I2Cx, Addr);
		  /* Wait until ADDR flag is set */
   while(!LL_I2C_IsActiveFlag_ADDR(I2Cx)){};
		 
    /* Clear ADDR flag */
		 LL_I2C_ClearFlag_ADDR(I2Cx);
		 
		/* Wait until TXE flag is set */
    while(!LL_I2C_IsActiveFlag_TXE(I2Cx));

    /* 4.发送器件寄存器地址. */
    LL_I2C_TransmitData8(I2Cx, Reg);
    while(!LL_I2C_IsActiveFlag_TXE(I2Cx));

  /* 5.提供RESTART信号. */
   // LL_I2C_GenerateStopCondition(I2Cx);
    LL_I2C_GenerateStartCondition(I2Cx);
    while(!LL_I2C_IsActiveFlag_SB(I2Cx));

  /* 6.重新发送地址,并附带读标记. */
    LL_I2C_TransmitData8(I2Cx, Addr | 0x01);
		/* Wait until ADDR flag is set */
		while(!LL_I2C_IsActiveFlag_ADDR(I2Cx)){};
   // 


    
    if (len  == 0U)
    {
      /* Clear ADDR flag */
      LL_I2C_ClearFlag_ADDR(I2Cx);

      /* Generate Stop */
      LL_I2C_GenerateStopCondition(I2Cx);
    }
    else if (len == 1U)
    {
      /* Disable Acknowledge */
      CLEAR_BIT(I2Cx->CR1, I2C_CR1_ACK);

      /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
         software sequence must complete before the current byte end of transfer */
      __disable_irq();

      /* Clear ADDR flag */
      LL_I2C_ClearFlag_ADDR(I2Cx);

      /* Generate Stop */
      LL_I2C_GenerateStopCondition(I2Cx);

      /* Re-enable IRQs */
      __enable_irq();
    }
    else if (len == 2U)
    {
      /* Enable Pos */
      SET_BIT(I2Cx->CR1, I2C_CR1_POS);

      /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
         software sequence must complete before the current byte end of transfer */
      __disable_irq();

      /* Clear ADDR flag */
      LL_I2C_ClearFlag_ADDR(I2Cx);

      /* Disable Acknowledge */
      CLEAR_BIT(I2Cx->CR1, I2C_CR1_ACK);

      /* Re-enable IRQs */
      __enable_irq();
    }
    else
    {
      /* Enable Acknowledge */
      SET_BIT(I2Cx->CR1, I2C_CR1_ACK);
      /* Clear ADDR flag */
      LL_I2C_ClearFlag_ADDR(I2Cx);
    }

    while (len > 0U)
    {
      if (len <= 3U)
      {
        /* One byte */
        if (len == 1U)
        {
          /* Wait until RXNE flag is set */
					while(!LL_I2C_IsActiveFlag_RXNE(I2Cx)){};


          /* Read data from DR */
         *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
          buf++;

          /* Update counter */
          len--;
        }
        /* Two bytes */
        else if (len == 2U)
        {
          /* Wait until BTF flag is set */
         		while(!LL_I2C_IsActiveFlag_BTF(I2Cx)){}

          /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
             software sequence must complete before the current byte end of transfer */
          __disable_irq();

          /* Generate Stop */
           LL_I2C_GenerateStopCondition(I2Cx);


          /* Read data from DR */
           *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
          buf++;

          /* Update counter */
          len--;

          /* Re-enable IRQs */
          __enable_irq();

          /* Read data from DR */
          *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
          buf++;

          /* Update counter */
          len--;
        }
        /* 3 Last bytes */
        else
        {
          /* Wait until BTF flag is set */
           while(!LL_I2C_IsActiveFlag_BTF(I2Cx)){}


          /* Disable Acknowledge */
          CLEAR_BIT(I2Cx->CR1, I2C_CR1_ACK);

          /* Disable all active IRQs around ADDR clearing and STOP programming because the EV6_3
             software sequence must complete before the current byte end of transfer */
          __disable_irq();

          /* Read data from DR */
           *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
            buf++;

          /* Update counter */
          len--;

          /* Wait until BTF flag is set */
					while(!LL_I2C_IsActiveFlag_BTF(I2Cx)){}
		
          /* Generate Stop */
           LL_I2C_GenerateStopCondition(I2Cx);

          /* Read data from DR */
            *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
           buf++;

          /* Update counter */
					len--;


          /* Re-enable IRQs */
          __enable_irq();

          /* Read data from DR */
           *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);


          /* Increment Buffer pointer */
           buf++;

          /* Update counter */
         	len--;
        }
      }
      else
      {
        /* Wait until RXNE flag is set */
        while(!LL_I2C_IsActiveFlag_RXNE(I2Cx)){};
					
        /* Read data from DR */
            *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
           buf++;

         /* Update counter */
					len--;


        if (LL_I2C_IsActiveFlag_BTF(I2Cx))
        {
            /* Read data from DR */
            *buf  = (uint8_t)LL_I2C_ReceiveData8(I2Cx);

          /* Increment Buffer pointer */
           buf++;

         /* Update counter */
					len--;
        }
      }
    }

  return 0;
}


uint8_t i2c_write_len(I2C_TypeDef *I2Cx,  uint8_t addr , uint8_t reg, uint8_t len,uint8_t *buf)
{
    int i=0;
  /* 1.保证I2C外设不在使用中. */
    while(LL_I2C_IsActiveFlag_BUSY(I2Cx));

	
    /* Check if the I2C is already enabled */
    if ((I2Cx->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
    {
      /* Enable I2C peripheral */
      LL_I2C_Enable(I2Cx);
    }

    /* Disable Pos */
    CLEAR_BIT(I2Cx->CR1, I2C_CR1_POS);

		
  /* 2.发送START信号 */
    LL_I2C_GenerateStartCondition(I2Cx);
    while(!LL_I2C_IsActiveFlag_SB(I2Cx));

  /* 2.写器件地址 */
    LL_I2C_TransmitData8(I2Cx, addr);
		LL_mDelay(1);
    while(!LL_I2C_IsActiveFlag_ADDR(I2Cx));

    LL_I2C_ClearFlag_ADDR(I2Cx);

  /* 3.地址位已经置位,通常TXE也会完成,为了谨慎,再查一下. */
		while(!LL_I2C_IsActiveFlag_TXE(I2Cx)){}

  /* 4.发送器件寄存器地址. */
    LL_I2C_TransmitData8(I2Cx, reg);

		i = len;
    while(i>0)
    {
			while(!LL_I2C_IsActiveFlag_TXE(I2Cx)){};
      /* 5.写入寄存器内容 */
      LL_I2C_TransmitData8(I2Cx, *buf);
      buf++;
			i--;
				
			if(LL_I2C_IsActiveFlag_BTF(I2Cx)==SET && i!=0)
			{
				  LL_I2C_TransmitData8(I2Cx, *buf);
					buf++;
					i--;

			}
    }
		
		while(!LL_I2C_IsActiveFlag_BTF(I2Cx)){}
			

  /* 6.传送结束条件. */
    LL_I2C_GenerateStopCondition(I2Cx);
			
			
    return 0;

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值