cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 holding I2C

Ryan-SmartIR
Associate II

I am trying to use the F103 as a I2C master but it is holding the I2C pins low, there is nothing else on the bus 5k1 pullups, when I hold the device in reset the lines are 5V. 

Because the lines are low, SB is never being set, so the first while statement of the transmit function is blocking. 

Any suggestions as to what could be causing this? I have no ideas left. 

 

/* USER CODE BEGIN */ 

 

 

 

//----------------------------------------------------------------------
//                                      I2C init
//----------------------------------------------------------------------
 

 

void ll_i2c1_init(void){
 
RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;
 
I2C1->CR1 &= ~I2C_CR1_PE;
 
I2C1->CR1 |= I2C_CR1_SWRST;
I2C1->CR1 &= ~I2C_CR1_SWRST;
 
ll_clocks_enable_i2c1(); 
 
ll_gpio_remap_i2c1();
 
I2C1->CR2 |= 16;
I2C1->CCR |= 0x50;
I2C1->TRISE = 0x10;
 
I2C1->OAR1 |= (0x14 << 1); 
 
I2C1->CR1 |= I2C_CR1_PE; //Peripheral Enable
 
}
 
//----------------------------------------------------------------------
//                                      Transmit
//----------------------------------------------------------------------
 
 
void ll_i2c1_transmit(uint8_t address, uint8_t message){
 
uint16_t status_register_1_read = 0;
 
address = (address << 1);
address &= ~(0x01); // clear LSB 0 = write
 
I2C1->CR1 |= (I2C_CR1_START | I2C_CR1_ACK);
 
while (!(I2C2->SR1 & I2C_SR1_SB)); // wait for start condition to be generated
 
I2C1->DR = address; //address is just sent on the line as data, after a start bit MSB first
//I2C1->CR1 |= (I2C_CR1_START);
 
while (!(I2C2->SR1 & I2C_SR1_ADDR));
 
status_register_1_read = I2C1->SR1; // these two reads clear addr
status_register_1_read = I2C1->SR2;
 
while (!(I2C2->SR1 & I2C_SR1_TXE));
 
I2C1->DR = message;
//I2C1->CR1 |= (I2C_CR1_START);
 
while (!(I2C2->SR1 & I2C_SR1_BTF));
 
I2C1->CR1 |= (I2C_CR1_STOP);
 
}
 
//----------------------------------------------------------------------
//                             Call of Transmit
//----------------------------------------------------------------------
 
ll_i2c1_transmit(0x55, 0x33);
 
/* USER CODE END */ 
 
 
 
/* USER CODE BEGIN 2 */
//----------------------------------------------------------------------
//                                      Clocks
//----------------------------------------------------------------------
 
//---------- Port for the LED and I2C --------------------------
 
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
 
RCC->APB2ENR |= (RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN);
 
//----------------------------------------------------------------------------------------
 
void ll_clocks_enable_i2c1(void){
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
}
 
 
//----------------------------------------------------------------------
//                                      GPIO
//----------------------------------------------------------------------
 
 
//I2C1 Alternate functions
 
GPIOB->CRH &= ~GPIO_CRH_CNF8;
GPIOB->CRH |= (GPIO_CRH_CNF8); //set 10 of the config bits
GPIOB->CRH |= GPIO_CRH_MODE8; // 50MHz output
 
GPIOB->CRH &= ~GPIO_CRH_CNF9;
GPIOB->CRH |= (GPIO_CRH_CNF9); //set 10 of the config bits
GPIOB->CRH |= GPIO_CRH_MODE9; // 50MHz output

 //----------------------------------------------------------------------------------------------------

void ll_gpio_remap_i2c1(void){
 
AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
 
}

 /* USER CODE END 2*/  

3 REPLIES 3
Imen.D
ST Employee

Hello @Ryan-SmartIR ,

Have a look at the Errata sheet related to the STM32F103 devices and check if you have the same conditions as described in the I2C limitations.

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Ryan-SmartIR
Associate II
Never figured out what was going wrong with the above, copy and pasted the code into i2c2, that didn't work, wrote it from scratch without any while delays and it worked fine, added the whiles back in and it it still works fine. Here is the working code. 
 
P.s. I didn't meet any of the conditions for the issues outlined in the errata
 
void ll_i2c2_init(void){
 
ll_clocks_enable_i2c2();
 
ll_gpio_remap_i2c2();
 
I2C2->CR1 |= 16; // bottom 5 bits are frequency 16MHz
 
I2C2->CCR = 50;
I2C2->TRISE = 9;
 
I2C2->CR1 |= I2C_CR1_PE;
 
}
 
void ll_i2c2_transmit(uint8_t address, uint8_t message){
 
uint16_t register_reader = 0;
 
address <<= 1;
address &= ~0x01; //7 bit address, LSB 0 = write
 
I2C2->CR1 &= ~I2C_CR1_STOP;
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
I2C2->CR1 |= I2C_CR1_START;
 
while(!(I2C2->SR1 & I2C_SR1_SB));
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
I2C2->DR = address;
 
 
while(!(I2C2->SR1 & I2C_SR1_ADDR));
//The ADDR bit is only set after the ACK is received
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
//I2C2->CR1 |= I2C_CR1_START;
 
I2C2->DR = message;
 
//I2C2->CR1 |= I2C_CR1_START;
 
I2C2->CR1 |= I2C_CR1_STOP;
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
}
 
 
uint16_t ll_i2c2_read(uint8_t address){
 
uint16_t register_reader = 0;
uint16_t received_data = 0;
 
address <<= 1;
address |= 0x01; //7 bit address, LSB 1 = read
 
I2C2->CR1 &= ~I2C_CR1_STOP;
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
I2C2->CR1 |= (I2C_CR1_START | I2C_CR1_ACK);
 
while(!(I2C2->SR1 & I2C_SR1_SB));
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
I2C2->DR = address;
 
 
while(!(I2C2->SR1 & I2C_SR1_ADDR));
//The ADDR bit is only set after the ACK is received
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
 
//I2C2->CR1 |= I2C_CR1_START;
while(!(I2C2->SR1 & I2C_SR1_RXNE));
 
received_data = I2C2->DR;
received_data <<= 8;
 
while(!(I2C2->SR1 & I2C_SR1_RXNE));
 
received_data |= I2C2->DR;
 
//I2C2->CR1 |= I2C_CR1_START;
 
I2C2->CR1 |= I2C_CR1_STOP;
 
register_reader = I2C2->SR1;
register_reader = I2C2->SR2;
 
I2C2->CR1 &= ~I2C_CR1_ACK;
 
return received_data;
}
Ryan-SmartIR
Associate II

Also note, from my original post, the while loop conditions are checking the I2C2 registers instead of the I2C1 registers so that would never work. I did fix this after posting and it still didn't work.