cancel
Showing results for 
Search instead for 
Did you mean: 

I2C start condition not generates ( SB flag is never set )

ASeyo
Associate II

I'm working on stm32f103 I2C peripheral. I've one stm32f103 master and another stm32f103 slave. The master should send some text to the slave, but start condition never generates. The BUSY flag is set as soon as the peripheral is enable and the program hangs on a loop that waits until start condition is generated.

( i.e
 // Wait until start condition is generated
	while(!(I2C1->SR1 & I2C_SR1_S){}
)
 
#include "stm32f10x.h"         // Device header
void clockConfig(void);
void I2C1Init(void);
void I2C1Send(uint8_t* MSG);
int main(void)
{
	clockConfig();
	I2C1Init();
	I2C1Send((uint8_t*)"Hello, I2C1!");
while(1)
	{
	}
}
 
void I2C1Send(uint8_t* MSG)
{
	// Generate start bit
	I2C1->CR1 |= I2C_CR1_START;
	// Wait until start condition is generated
	while(!(I2C1->SR1 & I2C_SR1_SB)){} /* the program stops here*/
	// clear start condition flag
	uint32_t dummyRead = I2C1->SR1;
	// Write slave address, and master transmitter mode
	I2C1->DR = 0x72; 
	// Wait until address phase is complete
	while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
	// Clear ADDR
 dummyRead = I2C1->SR1;
	dummyRead = I2C1->SR2;	
 
	while(*MSG)
	{
 
  // Wait until TXE flag is set
 while(!(I2C1->SR1 & I2C_SR1_TXE)){}
 I2C1->DR = *MSG;
 MSG++;
	}
 
	// Wait unitl byte trasfer finished flag
	while(!(I2C1->SR1 & I2C_SR1_BTF)){}
	// program stop condition
	I2C1->CR1 |= I2C_CR1_STOP;
	// BTF flag is cleared by hardware 
 
}
 
void I2C1Init(void)
{	
	// Enable clock access for port B
	RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
 
	// Configure Gpios as af open drain
	GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_MODE6;
	// Enable internal pull up
	GPIOB->ODR |= GPIO_ODR_ODR6;
	GPIOB->CRL |= GPIO_CRL_CNF7 | GPIO_CRL_MODE7;
	// Enable internal pull up
	GPIOB->ODR |= GPIO_ODR_ODR7;
	// Configure I2C1
	// Enable clock access for I2C1
	RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
	// Configure APB1 frequency
	I2C1->CR2 |= 36;
	// configure CCR
	I2C1->CCR |= 180; // 100KHz standard mode
	// Configure the rise time register
	I2C1->TRISE |= 37;
	// Enable I2C1
	I2C1->CR1 |= I2C_CR1_PE;
	// Enable ACK 
	I2C1->CR1 |= I2C_CR1_ACK;	
}
 
 /* This sets all peripherals to their maximum speed.*/
void clockConfig(void)
{
	// HSE ON
	RCC->CR |= 0x1<<16;
 // wait unit HSE is ready
	while(!(RCC->CR & (0x1<<17))){}
 
	// PLL OFF
	RCC->CR &= ~(0x1<<24);
	//HSE clock not divided
	RCC->CFGR &= ~(0x1<<17);
	// PLL SRC = HSE 
	RCC->CFGR |= 0x1<<16;
	// PLL MUL, x9
	RCC->CFGR &= ~(0xF<<18);
	RCC->CFGR |= 0x7<<18;
 
 	// PLL ON
	RCC->CR |= 0x1<<24;
	// wait until PLL is ready
	while(!(RCC->CR & (0x1 << 25))){}
 
	// choose PLL as Sys clock 
	RCC->CFGR &= ~(0x3);
	RCC->CFGR |= 0x2;
 
	// AHB prescaler x1
	RCC->CFGR &= ~(0xF<<4);
	
 // APB1 (36MHz max ) prescaler /2
	RCC->CFGR &= ~(0x7<<8);
	RCC->CFGR |= (0x4<<8);
 
 // APB2(72MHz) prescaler x1
	RCC->CFGR &= ~(0x7<<11);
}

1 ACCEPTED SOLUTION

Accepted Solutions
Amel NASRI
ST Employee

Hi @ASeyo​ ,

Please make sure that the sequence recommended in the product errata sheet (I2C analog filter may provide wrong value, locking BUSY flag and preventing master mode entry) is well applied.

Here the link to the errata sheet document.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

1 REPLY 1
Amel NASRI
ST Employee

Hi @ASeyo​ ,

Please make sure that the sequence recommended in the product errata sheet (I2C analog filter may provide wrong value, locking BUSY flag and preventing master mode entry) is well applied.

Here the link to the errata sheet document.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.