I am programming an I2C master on a STM32F401 nucleo board. I program it without HAL, just using registers.
I am interfacing a peripheral, that has to be read like the following:
- Start
- Write Address with R/W 0
- Write register address
- Send repeated start condition
- Write Address with R/W 1
- Read data from peripheral
The first 3 steps work totally fine, but I can't send the address with R/W 1 after the restart condition.
Here you can see the timing diagram using a logic analyser. The restart condition is sent, but afterwards SCL and SDA are just low.
Here is my code
i2c_start();
if (i2c_sendAddr(TLC2991_ADDR)) { //returns != 0 if NACK
fault = true;
i2c_end();
I2C1->SR1 &= ~I2C_SR1_AF;
return -1;
}
i2c_sendByte(VOLTAGE_REG_OFFS + 2 * ch);
i2c_wfw();
i2c_start();
i2c_sendByte(TLC2991_ADDR | 1); //tried i2c_sendAddr too
u8 msb = i2c_recvByte(1);
u8 lsb = i2c_recvByte(0);
And the functions called
void i2c_start() {
I2C1->CR1 |= I2C_CR1_START;
while (!I2C1->SR1 & I2C_SR1_SB);
}
int i2c_sendAddr(u8 addr) {
I2C1->DR = addr;
while (!(I2C1->SR1 & I2C_SR1_ADDR))
if (I2C1->SR1 & I2C_SR1_AF)
return -1;
I2C1->SR2; //generates a read, clears ADDR
return 0;
}
int i2c_sendByte(u8 data) {
while (!(I2C1->SR1 & (I2C_SR1_TXE | I2C_SR1_AF)));
I2C1->DR = data;
return I2C1->SR1 & I2C_SR1_AF ? -1 : 0;
}
//wait for byte transfer
void i2c_wfw() {
while (!(I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_AF)));
}
The TXE bit is high before setting the DR after the restart, afterwards it is low, but the I2C does not transmit anything. Please point out what I missed.
I have also checked the SDA line with an oscilloscope and there are no glitches or similar.