2016-11-22 08:57 PM
Hello All,
I'm struggling with I2C communication with L476 using LL libraries. In my custom board, a OV5642 camera is connected with I2C1 and a LSM6DS3 IMU with I2C3. Previously I've configured I2C RTC with L151 (by waiting for events) using Std Peripheral libraries. But, I'm missing some flags in L476. Also, L476 doesn't have support for SPL. I successfully ran the example I2C Polling code (provided in L4cube library) between two L476 Nucleo boards. I followed the same code here, but, I'm not receiving any value or seeing any clock (oscilloscope) in I2C SCL lines. I'm wondering what I am doing wrong here. In board, I2C lines are connected directly to devices without any external pull-ups. I request your kind suggestion. I'm not much sure about set timing things, I took the value from Cube Tool for PLCK clock and I2C fast mode. My configurations as follows: //LSM6DS3_ADDRESS = 0x6B void LSM6DS3_I2C_Init(void){ // SCL on PC.0, SDA on PC.1 LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); /* Configure SCL Pin as : Alternate function, High Speed, Open drain, Pull up */ LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_0, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_0, LL_GPIO_AF_4); LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_0, LL_GPIO_SPEED_FREQ_VERY_HIGH); LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_0, LL_GPIO_OUTPUT_OPENDRAIN); LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_0, LL_GPIO_PULL_UP); /* Configure SDA Pin as : Alternate function, High Speed, Open drain, Pull up */ LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_1, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_1, LL_GPIO_AF_4); LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_1, LL_GPIO_SPEED_FREQ_VERY_HIGH); LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_1, LL_GPIO_OUTPUT_OPENDRAIN); LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_1, LL_GPIO_PULL_UP); /* Enable the peripheral clock for I2C3 */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3); LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1); LL_I2C_Disable(I2C3); /* Configure the SDA setup, hold time and the SCL high, low period */ LL_I2C_SetTiming(I2C3, 0x0040131E); // Time found from Cube Tool for Fast mode, 400 KHz, 100ns Rise time, 10ns Fall time LL_I2C_SetOwnAddress2(I2C3, 0x00, LL_I2C_OWNADDRESS2_NOMASK); // Default LL_I2C_Enable(I2C3); } // Same for I2C1 camera void LSM6DS3_I2C_Write(uint8_t Addr, uint8_t Data) { uint8_t TxBuffer[] = {Addr,Data}; uint8_t TxIndex; uint8_t ubNbDataToTransmit_I2c=2; LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2c, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_STOP(I2C3)) // Loop until end of transfer received (STOP flag raised) { /* Check TXIS flag value in ISR register */ if(LL_I2C_IsActiveFlag_TXIS(I2C3)) { /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */ LL_I2C_TransmitData8(I2C3, TxBuffer[TxIndex]); TxIndex++; } } /* End of I2C_SlaveReceiver_MasterTransmitter Process */ LL_I2C_ClearFlag_STOP(I2C3); } void LSM6DS3_I2C_Read(uint8_t Addr) { uint8_t ubNbDataToTransmit_I2C=1; LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_STOP(I2C3)) // Loop until end of transfer received (STOP flag raised) { /* Check TXIS flag value in ISR register */ if(LL_I2C_IsActiveFlag_TXIS(I2C3)) { /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */ LL_I2C_TransmitData8(I2C3, Addr); } } LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ); while(!LL_I2C_IsActiveFlag_STOP(I2C3)) // Loop until end of transfer received (STOP flag raised) { /* Check RXNE flag value in ISR register */ if(LL_I2C_IsActiveFlag_RXNE(I2C3)) { /* Read character in Receive Data register. RXNE flag is cleared by reading data in RXDR register */ RxBuffer[BufferIndex++] = LL_I2C_ReceiveData8(I2C3); } } LL_I2C_ClearFlag_STOP(I2C3); } // For Camera I2C communication void DCMI_SingleRandomWrite(uint16_t Addr, uint8_t Data) { uint8_t TxBuffer[] = {(uint8_t)(Addr>>8),(uint8_t)(Addr),Data}; uint8_t TxIndex; uint8_t ubNbDataToTransmit_I2C=3; LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_WRITE_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_STOP(I2C1)) // Loop until end of transfer received (STOP flag raised) { /* Check TXIS flag value in ISR register */ while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); { /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */ LL_I2C_TransmitData8(I2C1, TxBuffer[TxIndex]); TxIndex++; } } /* End of I2C_SlaveReceiver_MasterTransmitter Process */ LL_I2C_ClearFlag_STOP(I2C1); } void DCMI_SingleRandomRead(uint16_t Addr) { uint8_t TxBuffer[] = {(uint8_t)(Addr>>8),(uint8_t)(Addr)}; uint8_t TxIndex; uint8_t ubNbDataToTransmit_I2C=2; LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_WRITE_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); while(!LL_I2C_IsActiveFlag_STOP(I2C1)) // Loop until end of transfer received (STOP flag raised) { /* Check TXIS flag value in ISR register */ while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); { /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */ LL_I2C_TransmitData8(I2C1, TxBuffer[TxIndex]); TxIndex++; } } /* End of I2C_SlaveReceiver_MasterTransmitter Process */ LL_I2C_ClearFlag_STOP(I2C1); } LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_READ_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ); while(!LL_I2C_IsActiveFlag_STOP(I2C1)) // Loop until end of transfer received (STOP flag raised) { /* Check RXNE flag value in ISR register */ if(LL_I2C_IsActiveFlag_RXNE(I2C1)) { /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */ Camera_Reg_Value = LL_I2C_ReceiveData8(I2C1); } } LL_I2C_ClearFlag_STOP(I2C1); }2016-11-27 07:31 AM
Kindly anyone can help with an idea/advice ?
I've checked left shifted slave address and read/write bit but not seeing any acknowledgement from slave after sending writing address. What might be the impact of I2C timing value here? I've took the timing value from Cube Tool by putting fast mode with 100ns and 10ns rise and fall time (from examples provided in L4 library). Not much details I found in OV5642 datasheet about these timing values. Thank you in advance for your reply.2016-12-10 11:30 AM
2016-12-12 05:48 AM
As far as i know you need to use pullups for 12c to work. But you said you got the demo code to work ?
2017-09-26 09:54 AM
hi
Lyen.Rum
Hi , . I am also trying to communicate with i2c slave with nucleo-l476 controller. i'm not familier with using LL libraries. I think you successfully worked on it . Can you please share me the working code base.Thanks and regards,
Madhu R
2017-09-27 02:57 AM
Hello
madhu.r
,Have a look to the I2C examplebased on LL driver with STM32CubeL4:
STM32Cube_FW_L4_V1.9.0\Projects\STM32L476RG-Nucleo\Examples_LL\I2C
Best Regards
Imen