2021-08-23 09:03 AM
Hello,
I know that has been asked a lot of times but i cannot get i2c work on my original stm32f103c6t6 mcu on a blue pill board.
I tried to read a lot on internet but anything let me come out.
I modified HAL_I2C_MspInit() as i read that i2c clk enable needed to be before the gpio clk enable, added also the reset.
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
__HAL_RCC_I2C1_CLK_ENABLE(); //ADDED BEFORE GPIO CLK
__HAL_RCC_I2C1_FORCE_RESET(); //RESET
__HAL_RCC_I2C1_RELEASE_RESET(); //RESET
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
//__HAL_RCC_I2C1_CLK_ENABLE(); //REMOVED
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
I tried as STM sais on errdata their workaroud about analog filter adding those functions that i hope are corrects.
void test(void){
HAL_I2C_DeInit(&hi2c1);
//1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 &= ~(1 << 0);
//2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
GPIOB->CRL |= 3 << 24;
GPIOB->CRL |= 3 << 28;
GPIOB->CRL |= 1 << 26;
GPIOB->CRL |= 1 << 30;
GPIOB->BSRR |= 1 << 6;
GPIOB->BSRR |= 1 << 7;
//3. Check SCL and SDA High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
}
//4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
GPIOB->BSRR |= 1 << 23;
//5. Check SDA Low level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){
}
//6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
GPIOB->BSRR |= 1 << 22;
//7. Check SCL Low level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET){
}
//8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
GPIOB->BSRR |= 1 << 6;
//9. Check SCL High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET){
}
//10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
GPIOB->BSRR |= 1 << 7;
//11. Check SDA High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
}
//12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
GPIOB->CRL |= 3 << 26;
GPIOB->CRL |= 3 << 30;
//13. Set SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 |= 1 << 15;
//14. Clear SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 &= ~(1 << 15);
//15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
hi2c1.Instance->CR1 |= 1 << 0;
HAL_I2C_Init(&hi2c1);
}
Also tried in an other way as i saw.
void test_1(void){
GPIO_InitTypeDef strutturaGPIO = {0};
//1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 &= ~(1 << 0);
//2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
HAL_I2C_DeInit(&hi2c1);
strutturaGPIO.Pin = GPIO_PIN_6|GPIO_PIN_7;
strutturaGPIO.Mode = GPIO_MODE_OUTPUT_OD;
strutturaGPIO.Pull = GPIO_PULLUP;
strutturaGPIO.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &strutturaGPIO);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
//3. Check SCL and SDA High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
}
//4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
//5. Check SDA Low level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){
}
//6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
//7. Check SCL Low level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET){
}
//8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
//9. Check SCL High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET){
}
//10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
//11. Check SDA High level in GPIOx_IDR.
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
}
//12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
strutturaGPIO.Pin = GPIO_PIN_6|GPIO_PIN_7;
strutturaGPIO.Mode = GPIO_MODE_AF_OD;
strutturaGPIO.Pull = GPIO_PULLUP;
strutturaGPIO.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &strutturaGPIO);
//13. Set SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 |= 1 << 15;
//14. Clear SWRST bit in I2Cx_CR1 register.
hi2c1.Instance->CR1 &= ~(1 << 15);
//15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
hi2c1.Instance->CR1 |= 1 << 0;
HAL_I2C_Init(&hi2c1);
}
I have my 4.7k pull up resistors on 3.3 V , i cannot get it work on both original STM MCU.
By the way i was working with i2c on a fake MCU CSK and it was working fine.
I use cubemx so i let it generate everything.
Debugging it seem that HAL_GPIO_Init(GPIOB, &GPIO_InitStruct) in HAL_I2C_MspInit() put Bus busy high.
I tried with nothing on the line or also with a ads1115.
Thanks a lot
Solved! Go to Solution.
2021-08-24 02:09 AM
Well thanks,
I found out that it was not setting up the speed of the gpio in the structure sent to the gpio init, so it was set up as input and not as output OD.
By the way it's generated by stmcube so is it missing while generating or i missed something in cube?
Thanks again
2021-08-23 10:02 AM
Yeah, got bad memories about the F1 / I2C
Seem to remember I needed to ENABLE the I2C via CR, before initializing, at least in SPL days
Would double check the AFIO, GPIO and I2C clocks.
Make sure I2C is properly mapped, and perhaps conflicting peripherals are remapped off those pins.
Check Errata
Make sure structure is properly cleared/initialized.
2021-08-23 12:17 PM
Hello Thanks,
I tried to enable in the CR1 register but i keep getting error before initializing.
About AFIO i don't see anything of strange i would check it better tomorrow.
I checked in the register if was mapped at 0 for pin 6 7 and its fine, i have nothing over i2c1 its an empty project with just swd debug.
Errata was saying what i did (maybe i did it wrong).
Is fine that in GPIO_INIT set pin 6 and 7 as INPUT?
I'm getting MODE 00 and CNF 11 on the table configuration is "reserved".
It doesnt match with what i set up on stmcube that was output open drain with no pullup.
I'll check more tomorrow.
Thanks a lot.
2021-08-24 02:09 AM
Well thanks,
I found out that it was not setting up the speed of the gpio in the structure sent to the gpio init, so it was set up as input and not as output OD.
By the way it's generated by stmcube so is it missing while generating or i missed something in cube?
Thanks again
2022-11-14 08:32 AM
Thank you a lot I was desperatly trying to understand why the I2C didn't work and your solution worked for me. In 2022 MxCube is still generating the I2C the wrong way.
2022-11-16 11:03 PM
Hi,
I am also facing similar issue with I2C not working when used from STMcubeMx and STM32cubeID...we should just change the GPIO_Initstruct.Speed ??
can we still use HAL_I2C_Transmit and Rx??
should we use the same code of bitbang and then change the code..
Kindly suggest as we are working with STM32TC6T6 here...
Thanks
regards
Ravi
2022-11-17 12:06 AM
2022-11-17 07:44 AM
Hi,
any update kindly let me know so that I can try the I2C changes and see whether this works..
You have defined GPIO as well as I2C ..wanted to know how you compiled and how this was run..
regards
Ravi
2022-11-17 07:36 PM
Hi ,
Any update here on how I2C can be worked out from updated CUbeMX such that I can use for STM32F103C6T6...we are using SCD30 sensor..kindly let me know if you have any suggestion or code which you can share..thanks
Ravi
2022-11-22 12:51 AM
HI,@RShiv.1
I have also a stm32c6t6, the i2c code generated by the stm32cubeMX didn't works.
The solution is in the answer of this post.
The i2c initialization tree is:
You have to do:
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;