cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103C8T6: I2C Master does not generate START bit

DPosv.1
Associate II

I am programming Blue Pill stm32f103c8t6 mcu, and I am having troubles implementing I2C driver for it. I have tried one I2C example from one site, then tried to implement it on my own by datasheet, yet it does not work - it does not generate START.

I know this I2C and I2C device work, because I have tried using STM32Duino software and the device with address 72 replied, but I have troubles reimplementing it on my own. I use CMSIS, no HAL and the minimal code is as follows:

void i2c_init() {
 
  I2C_InitTypeDef i2c_initstruct;
  I2C_StructInit(&i2c_initstruct);
 
  // Initialize I2C
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
  i2c_initstruct.I2C_ClockSpeed = 100e3;
  i2c_initstruct.I2C_Mode = I2C_Mode_I2C;
  i2c_initstruct.I2C_DutyCycle = I2C_DutyCycle_2;
  i2c_initstruct.I2C_OwnAddress1 = 0;
  i2c_initstruct.I2C_Ack = I2C_Ack_Disable;
  i2c_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_Init(I2C2, &i2c_initstruct);
  I2C_Cmd(I2C2, ENABLE);
 
  // Initialize GPIO as open drain alternate function
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}
 
void i2c_start2(uint8_t addr_with_mode) {
nlio_print("(0");
 
  // Wait until no longer busy
  while((I2C2->SR2 & I2C_SR2_BUSY) != 0);
  // Send start bit
  I2C2->CR1 |= I2C_CR1_START;
 
  // Wait until no longer busy
  while((I2C2->SR2 & I2C_SR2_BUSY) != 0);
 
  //while((I2C2->SR2 & I2C_SR2_MSL) == 0);
 
nlio_print("(1");
  // Wait until START bit is actually sent
  while((I2C2->SR1 & I2C_SR1_SB) == 0);
 
nlio_print("(2");
  // Write address
  I2C2->DR = addr_with_mode;
 
nlio_print("(3");
  // Wait for ACK (address match)
  while((I2C2->SR1 & I2C_SR1_ADDR) == 0);
 
nlio_print("(4");
  // Read SR1 followerd by SR2 to clear (I2C->SR1 & ADDR)
  (void) I2C2->SR2;
}
 
void i2c_send(uint8_t byte) {
  // Wait until Data register is empty
  while((I2C2->SR1 & I2C_SR1_TXE) == 0);
 
  // Send byte
  I2C2->DR = byte;
}
 
void i2c_end() {
  // Wait until Data register is empty
  while((I2C2->SR1 & I2C_SR1_TXE) == 0);
 
  // Wait until Byte transfer finished
  while((I2C2->SR1 & I2C_SR1_BTF) == 0);
 
  // Send stop
  I2C2->CR1 |= I2C_CR1_STOP;
}
 
#define WRITE 0
 
void i2c_test() {
  i2c_init();
 
  nlio_print("Hello\r\n");
  i2c_start2((72 << 1) | WRITE);
  nlio_println("Chp1");
  i2c_send(0);
  nlio_println("Chp2");
  i2c_end();
  // i2c_write(72, 0);
 
  nlio_println("Chp4");
  uint8_t rec;
  i2c_read(72, &rec);
  nlio_println("Chp5");
 
  // uart_println("Wait busy");
  // i2c_wait_busy();
  // uart_println("Wait done");
 
  // info();
  while(1);
 
 
  // uart_println("Sending STOP");
  // i2c_read(72);
 
  // uart_println("DONE\n");
 
  // while(1) {
  //   info();
  // }
}
 
int main() {
  // ...
  nlio_print("NLIO\r\n");
  i2c_test();
  while(1);
}

and it hangs when waiting for START condition, so the output is as follows:

NLIO
Hello
(0(1

I have also soldered two pull-up 5k1 resistors connecting SDL and SCL to 3.3V, yet it still hangs.

I have no clue what I am doing wrong. Any help is appreciated.

7 REPLIES 7

Observe SDA/SCL pins, using oscilloscope/logic analyzer.

Read out the I2C registers and check/compare to working example.

JW

DPosv.1
Associate II

Thanks for your answer. It ***** that I currently I don't have an oscilloscope, even though I have recently ordered low speed one. I will try the register reading at least, and if it won't help I guess I will have to wait until it arrives.

Thanks for your answer. I currently I don't have an oscilloscope, even though I have recently ordered low speed one. I will try the register reading at least, and if it won't help I guess I will have to wait until it arrives.

Try initializing GPIO first, and I2C afterwards. Print the control and status registers at every step.

Tried initializing GPIO first, didn't help. Looking at the registers, even though I don't really know what exactly I should look for.

DPosv.1
Associate II

The content of the registers immediately after printing "(0" is following

         CR1 0001
         CR2 0024
        OAR1 4000
        OAR2 0000
          DR 0000
         SR1 0000
         SR2 0000
        TRIS 0025

and immediately after printing "(1" the registers change and SR2 indicates I2C is busy:

         CR1 0101
         CR2 0024
        OAR1 4000
        OAR2 0000
          DR 0000
         SR1 0000
         SR2 0002
        TRIS 0025

 and since then nothing changes, the registers remaing with those values.

TEMAN.1
Associate II

Did you check "anolog function" init?

AFIO->MAPR &=~ 0x00000002; // GPIOB 6 and 7 AF

if you wanna use 8.and 9. pins, then

AFIO->MAPR =| 0x00000002; // GPIOB 8 VE 9 AF

and if i am not wrong, your pins cant be 10 and 11