cancel
Showing results for 
Search instead for 
Did you mean: 

I2C / SMBus Communication using a STM32F105 on a smart battery

mstm32
Associate

Hi everyone,

I'm currently working on an STM32 project where I want to communicate with an SMBus-compliant battery (address 0x0B) using I2C. I'm using an STM32F105 microcontroller and I'm setting up I2C on GPIO pins B6 (SCL) and B7 (SDA). I've encountered some issues and would appreciate some help.

  • I am using OpenDrain for SDA and SCL with a 1k external Pullup
  • The I2C address is being sent out, but the slave device (battery) doesn't respond correctly.
  • I have observed that the device is trying to pull down the SDA signal for an ACK, but it fails to do so consistently. This makes me suspect an issue with the pin configuration or the electrical setup.
  • Consequently, the error Interrupt throws Acknowledge Failure (AF),.

I2C Initialization:

 

// Enable the I2C1 peripheral clock
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;

// Configure GPIOB pins 6 (SCL) and 7 (SDA) for I2C (Alternate function open-drain)
GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6 | GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
GPIOB->CRL |= (GPIO_CRL_MODE6_0 | GPIO_CRL_CNF6_1 | // SCL: Open-drain output
GPIO_CRL_MODE7_0 | GPIO_CRL_CNF7_1); // SDA: Open-drain output

// Reset I2C1
I2C1->CR1 |= I2C_CR1_SWRST;
I2C1->CR1 &= ~I2C_CR1_SWRST;

// Configure I2C1 for SMBus communication
I2C1->CR1 |= I2C_CR1_SMBUS; // Enable SMBus mode

// Set own address to 0x09
I2C1->OAR1 = (0x09 << 1);
I2C1->OAR2 = (0x09 << 1) | I2C_OAR2_ENDUAL;

// Set clock frequency (50 MHz PCLK1)
I2C1->CR2 |= 50; // PCLK1 frequency in MHz

// Configure clock control register (assuming 100 kHz standard mode)
I2C1->CCR = 180; // Clock control value

// Configure rise time register
I2C1->TRISE = 51; // Max rise time in master mode

// Enable I2C1 and its interrupts
I2C1->CR1 |= I2C_CR1_PE; // Enable I2C1
I2C1->CR1 |= I2C_CR1_ACK; // Enable ACK

// Enable event and error interrupts
I2C1->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITERREN;
NVIC_EnableIRQ(I2C1_EV_IRQn);
NVIC_EnableIRQ(I2C1_ER_IRQn);

 

  • I observe that the battery attempts to pull down the SDA line, but it fails. 
  • SCR0001.PNG
  • Note the tiny drop in voltage where the ACK signal should be sent. 
  • Also note, that this drop is not present when I send to another address. So seems to be a response attempt by the battery.

 

The STM32's errata sheet mentions a potential issue with the BUSY flag due to the analog filter providing incorrect values. But I am not sure I am running into this issue.

Nevertheless, I've attempted the workaround suggested by the errata, but the problem persists.

https://www.st.com/resource/en/errata_sheet/es022-stm32f105xx-stm32f107xx-device-errata-stmicroelectronics.pdf 

see 2.8.7.

 

Any help is appreciated

Best regards!

1 REPLY 1
Karl Yamashita
Lead III

1k pull-up seems too low. Maybe the slave can't pull SDA line low?

Try using a 4.7k instead.

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.