说明:驱动基于STm32G031K6,其他型号需自行做改动。
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
IIC的初始化: CubeMX生成
void STM32LLI2C1_Init(void) { LL_I2C_InitTypeDef I2C_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); /**I2C1 GPIO Configuration PA9 ------> I2C1_SCL PA10 ------> I2C1_SDA */ GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; GPIO_InitStruct.Alternate = LL_GPIO_AF_6; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Peripheral clock enable */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); /** I2C Initialization */ I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; I2C_InitStruct.Timing = 0x00303D5B; I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; I2C_InitStruct.DigitalFilter = 0; I2C_InitStruct.OwnAddress1 = 0; I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK; I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; LL_I2C_Init(I2C1, &I2C_InitStruct); LL_I2C_EnableAutoEndMode(I2C1); LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK); LL_I2C_DisableOwnAddress2(I2C1); LL_I2C_DisableGeneralCall(I2C1); LL_I2C_EnableClockStretching(I2C1); LL_I2C_Enable(I2C1); }由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
I2C读多个数据:
void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length) { //等待iic空闲 while(LL_I2C_IsActiveFlag_BUSY(I2C1)); //确认iic是否使能 if(!LL_I2C_IsEnabled(I2C1)) { LL_I2C_Enable(I2C1); } //配置 LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); //写入从设备寄存器地址 ucBSP_I2C1_WriteMemAddr(mem_address,mem_size); while(!LL_I2C_IsActiveFlag_TC(I2C1)); //配置 LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ); //读取数据 ucBSP_I2C1_ReadMultipleData(pdata,length); //等待停止完成 while(!LL_I2C_IsActiveFlag_STOP(I2C1)); LL_I2C_ClearFlag_STOP(I2C1); }I2C写多个数据:
void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length) { //等待iic空闲 while(LL_I2C_IsActiveFlag_BUSY(I2C1)); //确认iic是否使能 if(!LL_I2C_IsEnabled(I2C1)) { LL_I2C_Enable(I2C1); } //配置为写 LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); //写入从设备寄存器地址 ucBSP_I2C1_WriteMemAddr(mem_address,mem_size); while(!LL_I2C_IsActiveFlag_TCR(I2C1)); //重新配置为自动停止模式 LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP); //写数据 ucBSP_I2C1_WriteMultipleData(pdata,length); //等待停止完成 while(!LL_I2C_IsActiveFlag_STOP(I2C1)); LL_I2C_ClearFlag_STOP(I2C1); }为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
写寄存器地址:
void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size) { uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);; uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);; //发送器件寄存器地址 if(mem_size == I2C_MEMADD_SIZE_8BIT) { LL_I2C_TransmitData8(I2C1, MemAddrLSB); }else{ LL_I2C_TransmitData8(I2C1, MemAddrMSB); //等待发送完成 while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); LL_I2C_TransmitData8(I2C1, MemAddrLSB); } }连续写入小于255个数据:
void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length) { uint8_t count; for(count=0;count<length; count++) { //等待发送完成 while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); LL_I2C_TransmitData8(I2C1, *(pdata+count)); } }连续读取小于255个数据:
void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length) { uint8_t count; for(count=0;count<length; count++) { //等待接收非空 while(!LL_I2C_IsActiveFlag_RXNE(I2C1)); *(pdata+count) = LL_I2C_ReceiveData8(I2C1); } }