TaterLi's LazyBlog

自言自语,不喜绕路,科学上网,远离天国.

@TaterLi5月前

09/15
20:07
技术控

STM32F4 LL 库 I2C 初始化读取写入函数.

麻烦,费劲,但是胜在效率高,可读性也不差.为了方便,备份一份代码.

void I2C_HW_Init(void)
{
    LL_RCC_ClocksTypeDef rcc_clocks;
    LL_GPIO_InitTypeDef GPIO_Initstruct;

	/* 1.初始化对应IO. */
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);

    GPIO_Initstruct.Pin        = LL_GPIO_PIN_6 | LL_GPIO_PIN_9;
    GPIO_Initstruct.Mode       = LL_GPIO_MODE_ALTERNATE;
    GPIO_Initstruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
    GPIO_Initstruct.Pull       = LL_GPIO_PULL_UP;
    GPIO_Initstruct.Alternate	 = LL_GPIO_AF_4;

    LL_GPIO_Init(GPIOB, &GPIO_Initstruct);
	
    RCC->APB1RSTR |= (RCC_APB1RSTR_I2C1RST);
    RCC->APB1RSTR &= ~(RCC_APB1RSTR_I2C1RST);

	/* 2.开启I2C时钟. */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

	/* 3.先禁止I2C外设,这样才能设置寄存器. */
    LL_I2C_Disable(I2C1);

	/* 4.设置I2C速度为100kHz. */
    LL_RCC_GetSystemClocksFreq(&rcc_clocks);
    LL_I2C_ConfigSpeed(I2C1, rcc_clocks.PCLK1_Frequency, 100000, LL_I2C_DUTYCYCLE_2);

	/* 5.使能I2C外设. */
    LL_I2C_Enable(I2C1);

}

void I2C_HW_Write(uint8_t Addr, uint8_t Reg, uint8_t Value)
{
	/* 1.保证I2C外设不在使用中. */
    while(LL_I2C_IsActiveFlag_BUSY(I2C1))
    {
    }
	
	/* 2.发送START信号 */
    LL_I2C_GenerateStartCondition(I2C1);
    while(!LL_I2C_IsActiveFlag_SB(I2C1))
    {
    }
	
	/* 2.写器件地址 */
    LL_I2C_TransmitData8(I2C1, Addr);
    while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
    {
    }
    LL_I2C_ClearFlag_ADDR(I2C1);

	/* 3.地址位已经置位,通常TXE也会完成,为了谨慎,再查一下. */
    while(!LL_I2C_IsActiveFlag_TXE(I2C1))
    {
    }
	
	/* 4.发送器件寄存器地址. */
    LL_I2C_TransmitData8(I2C1, Reg);
    while(!LL_I2C_IsActiveFlag_TXE(I2C1))
    {
    }
	
	/* 5.写入寄存器内容 */
    LL_I2C_TransmitData8(I2C1, Value);
    while(!LL_I2C_IsActiveFlag_BTF(I2C1))
    {
    }

	/* 6.传送结束条件. */
    LL_I2C_GenerateStopCondition(I2C1);
}

uint8_t I2C_HW_Read(uint8_t Addr, uint8_t Reg)
{
    uint8_t Value = 0x00;
	/* 1.保证I2C外设不在使用中. */
    while(LL_I2C_IsActiveFlag_BUSY(I2C1))
    {
    }

	/* 2.发送START信号 */
    LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
    LL_I2C_GenerateStartCondition(I2C1);
    while(!LL_I2C_IsActiveFlag_SB(I2C1))
    {
    }
	
	/* 2.写器件地址 */
    LL_I2C_TransmitData8(I2C1, Addr);
    while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
    {
    }
    LL_I2C_ClearFlag_ADDR(I2C1);

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

	/* 4.发送器件寄存器地址. */
    LL_I2C_TransmitData8(I2C1, Reg);
    while(!LL_I2C_IsActiveFlag_TXE(I2C1))
    {
    }
	
	/* 5.提供RESTART信号. */
    LL_I2C_GenerateStopCondition(I2C1);
    LL_I2C_GenerateStartCondition(I2C1);
    while(!LL_I2C_IsActiveFlag_SB(I2C1))
    {
    }

	/* 6.重新发送地址,并附带读标记. */
    LL_I2C_TransmitData8(I2C1, Addr | 0x01);
    while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
    {
    }

	/* 7.标记读完就STOP. */
    LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
    LL_I2C_ClearFlag_ADDR(I2C1);
    LL_I2C_GenerateStopCondition(I2C1);

    while(!LL_I2C_IsActiveFlag_RXNE(I2C1))
    {
    }
	
	/* 8.数据已读取. */
    Value = LL_I2C_ReceiveData8(I2C1);
    return Value;
}

 

STM32F4 LL 库 I2C 初始化读取写入函数.