Uso de interrupción de STM32 I2S

Estaba probando un experimento de sonido, comenzando con un código de muestra que enviaba datos al códec de audio del Discovery F4 usando I2S. El código de muestra usó sondeo en el bucle principal y envió datos cuando el búfer de transmisión estaba vacío.

Configuré un controlador de interrupciones para SPI (en modo I2S) para hacer lo mismo. Establecí un indicador cuando se generó la interrupción y luego este indicador activó la transmisión de datos en el bucle principal. El problema es que las interrupciones se generaron demasiado rápido y el código del bucle principal nunca se ejecutó. Tuve que deshabilitar y habilitar las interrupciones para que esto funcione.

void SPI3_IRQHandler ( void )
 {
    STM_EVAL_LEDToggle(LED3); // NC
    if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_TXE) != RESET) {
        SPI_I2S_ClearITPendingBit(SPI3, SPI_I2S_IT_TXE);

        if (SPI_I2S_GetFlagStatus(CODEC_I2S, SPI_I2S_FLAG_TXE)) {
            STM_EVAL_LEDToggle(LED4);
            transferFlag = true;
            ready = false;
                    __disable_irq();    
        }
    }
}

Bucle principal:

   while(1)
    {
        STM_EVAL_LEDToggle(LED6);
        if (transferFlag){
            STM_EVAL_LEDToggle(LED5);
                //generate the sound
        SPI_I2S_SendData(CODEC_I2S, value);
            transferFlag = false;
            __enable_irq();
        }
    }

Incluso hice la generación de sonido muy simple (como valor = 1000), y todavía no funcionó, sin habilitar y deshabilitar las interrupciones. De hecho, LED5 y LED6 nunca se encendieron, lo que indica que no se ingresó al bucle principal. Además, coloqué el código de "generación de sonido y transmisión a SPI" en el controlador de interrupciones. Esto funcionó, pero el sonido era más suave que el código actual que se muestra arriba.

El Cortex M4 en el STM definitivamente no es tan lento, la FPU también está encendida. Planeo hacer una versión DMA de esto, pero no creo que activar y desactivar las interrupciones sea una buena solución.

se transferFlagdeclara volatile?
@TurboJ Sí lo es. De cualquier manera, dado que transferFlag se establece inicialmente en True, el ciclo principal debería haberse ejecutado al menos una vez, lo que haría que los LED se encendieran

Respuestas (2)

las interrupciones se generaron demasiado rápido y el código en el ciclo principal nunca se ejecutó

Este es siempre el caso cuando se olvidó de borrar un indicador de interrupción: el controlador se ejecuta una y otra vez.

El código anterior no borra la SPI_I2S_FLAG_TXEbandera en el CODEC_I2Sregistro. Puede haber otras banderas que deba borrar: consulte la hoja de datos/manual.

Gracias, investigaré esto. Borré el indicador SPI_I2S_IT_TXE, pero buscaré los demás más tarde hoy.

Borró el indicador SPI_I2S_IT_TXE, pero este indicador solo significa "Búfer de transmisión vacío", y dado que no escribió nada en el búfer de transmisión en su interrupción, el hardware vuelve a establecer el indicador inmediatamente después de borrarlo.

Es por eso que la línea SPI_I2S_SendData(CODEC_I2S, value);debe estar en su interrupción, no en su bucle principal. Como efecto secundario, la escritura de datos en el búfer de transmisión borra el indicador TXE, por lo que no tiene que borrarlo manualmente.