STM32F207 errores I2C

0

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.

    
pregunta hl2gordon

1 respuesta

1

Lo siento por la demora en mencionar esto, pero resolví exitosamente este problema usando la biblioteca CPAL STM32 disponible en ST. He probado esta biblioteca con el acelerómetro a bordo leyendo el registro 'WHO_AM_I' en el acelerómetro. El código para esto es:

#include "cpal_i2c.h"

int main()
{
    // Configuration
    CPAL_TransferTypeDef RxStruct;
    uint8_t RxBuf;
    RxStruct.pbBuffer = &RxBuf;
    RxStruct.wAddr1 = 0x39;
    // Initialization
    CPAL_I2C_StructInit(&I2C1_DevStructure);
    I2C1_DevStructure.CPAL_Mode = CPAL_MODE_MASTER;
    I2C1_DevStructure.CPAL_ProgModel = CPAL_PROGMODEL_DMA;
    I2C1_DevStructure.pCPAL_I2C_Struct->I2C_ClockSpeed = 100000;
    I2C1_DevStructure.pCPAL_TransferRx = &RxStruct;
    I2C1_DevStructure.pCPAL_TransferTx = pNULL;
    CPAL_I2C_Init(&I2C1_DevStructure);
    // Communication
    RxStruct.wNumData = 1;
    RxStruct.wAddr2 = 0x0F;
    if(CPAL_I2C_Read(&I2C1_DevStructure) != CPAL_PASS)
    {
        // Error
    }
    while(I2C1_DevStructure.CPAL_State != CPAL_STATE_READY);
    while(1);
    return 0;
}
    
respondido por el hl2gordon

Lea otras preguntas en las etiquetas