Estoy programando un maestro I2C en una placa de núcleo STM32F401. Lo programo sin HAL, solo usando registros.
Estoy interconectando un periférico, que debe leerse como el siguiente:
- Iniciar
- escriba la dirección con R / W 0
- escriba la dirección de registro
- Enviar condición de inicio repetido
- escriba la dirección con R / W 1
- Leer datos desde el periférico
Los primeros 3 pasos funcionan totalmente bien, pero no puedo enviar la dirección con R / W 1 después de la condición de reinicio.
Aquí puede ver el diagrama de tiempo utilizando un analizador lógico. Se envía la condición de reinicio, pero luego SCL y SDA son bajos.
Aquí está mi código
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);
Y las funciones llamadas
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)));
}
El bit TXE es alto antes de configurar el DR después del reinicio, luego es bajo, pero el I2C no transmite nada. Por favor, señale lo que me perdí.
También he comprobado la línea SDA con un osciloscopio y no hay problemas técnicos o similares.