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.
2022-11-22 01:42 AM
Hi,
Thanks for your suggestion...currently we are using cubeMx to generate the code..instead of C6 our code worked on C8.
but as you suggested Core/Src/stm32f1xx_hal_msp.c this file itself is not generated now..
Inside HAL_I2C_Init function itself we have HAL_I2C_MspInit(hi2c);...if I flow through this we get one more function like this...
*/
__weak void HAL_MspInit(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_MspInit could be implemented in the user file
*/
}
can we modify the GPIO.speed here..for C6 ???...kindly let me know..so that we need not change to C8
thanks
Ravi
2022-11-22 02:51 AM
I just tried to generate the stm32f103C8T6 code from stm32cubeMX.
In the ./Core/Src, the file stm32f1xx_hal_msp.c is generated with:
```c
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
```
which have SPEED set. This is the missing line/param in the generated c6t6 code by stm32cubeMX.
ps: HAL_I2C_MspInit in the Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c have __weak attribute, which means, if there are two function with the same name, the __weak one will not be chosen. (e.g replaced by the same function in the ./Core/Src/stmf1xx_hal_msp.c: line 85, HAL_I2C_MspInit() )