Estoy aprendiendo el desarrollo integrado en la placa STM3220G-EVAL con el microcontrolador STM32F207. Estoy probando la interfaz I2C conectando los dos módulos I2C2 e I2C3 en el mismo chip y enviando / recibiendo un personaje. Aquí está el código que he escrito actualmente:
#include <stm32f2xx.h>
volatile uint8_t data = 'a', recv = 'x';
void i2c_init(void);
// Master handler
void I2C2_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C2->SR1;
switch(stat)
{
// SB set; read SR1 and write slave address in DR to clear
case 0x01:
dummy = I2C2->SR1;
// Send address of slave
I2C2->DR = 0x40;
break;
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C2->SR1;
dummy = I2C2->SR2;
break;
// TxE set; write to DR to clear
case 0x80:
I2C2->DR = data;
break;
// TxE and BTF set; generate stop condition to clear
case 0x84:
// Generate stop
I2C2->CR1 |= (1 << 9);
break;
}
}
// Slave handler
void I2C3_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C3->SR1;
switch(stat)
{
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C3->SR1;
dummy = I2C3->SR2;
break;
// STOPF set; read SR1 and write CR1 to clear
case 0x10:
dummy = I2C3->SR1;
I2C3->CR1 &= ~(1 << 0);
break;
// RxNE set; read DR to clear
case 0x40:
recv = I2C3->DR;
break;
}
}
int main()
{
i2c_init();
// Generate START condition
I2C2->CR1 |= (1 << 8);
while(1)
{
if(!(I2C2->OAR1 & (1 << 14)))
I2C2->OAR1 |= (1 << 14);
if(!(I2C3->OAR1 & (1 << 14)))
I2C3->OAR1 |= (1 << 14);
if(recv != 'x')
break;
}
return 0;
}
void i2c_init(void)
{
// Enable GPIOA, GPIOC, GPIOF, I2C2 and I2C3 peripherals
RCC->AHB1ENR |= (1 << 0);
RCC->AHB1ENR |= (1 << 2);
RCC->AHB1ENR |= (1 << 5);
RCC->APB1ENR |= (1 << 22);
RCC->APB1ENR |= (1 << 23);
// Set GPIO mode to AF
GPIOA->MODER |= (1 << 17);
GPIOC->MODER |= (1 << 19);
GPIOF->MODER |= (1 << 1);
GPIOF->MODER |= (1 << 3);
// Set GPIO type to OD
GPIOA->OTYPER |= (1 << 8);
GPIOC->OTYPER |= (1 << 9);
GPIOF->OTYPER |= (1 << 0);
GPIOF->OTYPER |= (1 << 1);
// Set GPIO speed to 50MHz
GPIOA->OSPEEDR |= (1 << 17);
GPIOC->OSPEEDR |= (1 << 19);
GPIOF->OSPEEDR |= (1 << 1);
GPIOF->OSPEEDR |= (1 << 3);
// Link to I2C AF
GPIOA->AFR[1] |= (1 << 2);
GPIOC->AFR[1] |= (1 << 6);
GPIOF->AFR[0] |= (1 << 2);
GPIOF->AFR[0] |= (1 << 6);
// Enable interrupts
I2C2->CR2 |= (1 << 9);
I2C2->CR2 |= (1 << 10);
I2C3->CR2 |= (1 << 9);
I2C3->CR2 |= (1 << 10);
NVIC_EnableIRQ(I2C2_EV_IRQn);
NVIC_EnableIRQ(I2C3_EV_IRQn);
// Must set bit 14 in OAR1 to 1
I2C2->OAR1 |= (1 << 14);
I2C3->OAR1 |= (1 << 14);
// Set addresses
I2C2->OAR1 = 0x40;
I2C3->OAR1 = 0x40;
// Set peripheral clock frequency
I2C2->CR2 |= 0x08;
I2C3->CR2 |= 0x08;
I2C2->CCR |= 0x28;
I2C3->CCR |= 0x28;
I2C2->TRISE = 0x09;
I2C3->TRISE = 0x09;
// Enable ACK
I2C2->CR1 |= (1 << 10);
I2C3->CR1 |= (1 << 10);
// Enable I2C peripherals
I2C2->CR1 |= (1 << 0);
I2C3->CR1 |= (1 << 0);
}
Estoy usando un pullup de 13K en SDA y 10K en SCL. Los números de pines utilizados son PF0, PF1 (I2C2 SDA, SCL) y PA8, PC9 (I2C3 SCL, SDA). No he habilitado I2C2 e I2C3 en RTE_Device.h. Simplemente parece proporcionar typedefs de conveniencia. ( EDITAR: Intenté habilitarlos, no ayuda)
El controlador de eventos maestro se está llamando con éxito. Pero aún persisten algunos problemas. El bit de error de confirmación se está configurando y no se llama al controlador esclavo. Las líneas de autobús se han verificado como ALTAS cuando están inactivas.
¿Alguien podría ayudarme a resolver este problema? Parece que he llegado a un callejón sin salida.