麻烦,费劲,但是胜在效率高,可读性也不差.为了方便,备份一份代码.
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; }