STM32F415 extraño comportamiento I2C

Estoy usando un STM32F415RGT6 integrado en la placa 1Bitsy. Quiero configurar el periférico I2C para leer algunos datos de un sensor. Estoy usando la biblioteca de periféricos estándar stm32f4.

Mi código de ejemplo:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 

GPIO_InitTypeDef gpioInit;

GPIO_StructInit(&gpioInit);

gpioInit.GPIO_Mode = GPIO_Mode_AF;

gpioInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

gpioInit.GPIO_PuPd = GPIO_PuPd_UP;

gpioInit.GPIO_Speed = GPIO_Speed_25MHz; 

GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); 

GPIO_Init(GPIOB, &gpioInit); 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 

I2C_DeInit(I2C1);

I2C_InitTypeDef I2C_InitStructure;

I2C_StructInit(&I2C_InitStructure);


/* I2C configuration */

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_ClockSpeed = 100000;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0x01;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C1, &I2C_InitStructure);

I2C_Cmd(I2C1, ENABLE);


while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));


/* Generate Start, send the address and wait for ACK */

I2C_GenerateSTART(I2C1, ENABLE);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

I2C_Send7bitAddress(I2C1, 0xE0, I2C_Direction_Transmitter);


while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

Después de eso, quiero escribir un 0x00, pero el código siempre se cuelga en la última línea, aparentemente el Maestro nunca lee el reconocimiento. Los registros de estado I2C siempre leen:

I2C1 -> SR1 = 1024

I2C1 -> SR2 = 3

lo que significa que el bit de falla de reconocimiento siempre está establecido. Si lo analizo usando mi Saleae obtengo lo siguiente:

Analizador lógico STM32F415

El Esclavo envía el ACK, pero el STM32F415 no puede leerlo.

Lo extraño: si pruebo el mismo código en mi F407 - Disco (solo con el reloj configurado en 400 khz, pero es el mismo comportamiento en ambas MCU independientemente de la velocidad), funciona perfectamente:

Analizador lógico STM32F407-DISCO

Todos los demás periféricos funcionan bien. Ya probé varias soluciones, pero el bit AF siempre está configurado, independientemente del método. Espero que puedas ayudarme.

PD: Lo he intentado con y sin pullups adicionales y la dirección esclava I2C está bien, porque funciona con STM32F0, STM32F4-DISCO y Atmel Mcus.

Saludos cordiales y gracias de antemano!

gpioInit.GPIO_PuPd = GPIO_PuPd_UP;debe ser gpioInit.GPIO_PuPd = GPIO_OType_OD; con pull-ups.
sí, de hecho, pero desafortunadamente lo edité, no sé por qué se deslizó al copiar el código de Eclipse aquí. Perdón por la confusion
Diría que la dirección esclava no es correcta, si la dirección esclava de 7 bits lo es, 0xE0entonces debe pasar la dirección de ocho bits a la API I2C_Send7bitAddress(I2C1, uint8_t(0xE0<<1), I2C_Direction_Transmitter);, pero supongo que es 0x70 y ya la cambió.
¿Tiene un osciloscopio que pueda probar en lugar del Saleae? Cuando tuve problemas con I2C, fue porque mi pullup era demasiado débil y la forma de onda era muy descuidada. Las Saleae no mostrarían eso, pero un visor sí.
@AbelTom, la función I2C Send7Bit lo convierte en formato de 8 bits.
@ammar.cma No sé de qué implementación está hablando, pero estaba hablando de la implementación de Std_Periph/CMSIS, la función no contiene operaciones de cambio. Y en realidad, se debe enviar la dirección de 7 bits + bit R.
El F407 no parece funcionar a la perfección. Falta la condición de parada (se indicaría como un punto rojo). Para la condición de parada, SCK debe pasar a nivel alto antes de que SDA pase a nivel alto.

Respuestas (1)

Gracias por todas las sugerencias. Encontré la solución y es un poco raro. Funciona correctamente en ambas placas, pero en la STM32F415 no funciona con el analizador lógico capturando los datos. En el F407 no importa. Es una especie de heisenbug, no pasa si no miro, pero tenía que mirar para saber si está funcionando.

Esto probablemente significa que sus resistencias pullup son demasiado débiles. Es parte de por qué mirar con un alcance es útil para ver el carácter de la señal, incluso si el analizador lógico es mejor para decodificar el protocolo (al menos una vez que obtiene una cantidad de datos no trivial que desafía la velocidad y la interfaz de usuario de un decodificador I2C integrado típico de osciloscopio moderno).
Y cuando su empresa compra un alcance, pero no compra la licencia para el decodificador I2C