STM32 I2S Interupt Usage

1

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

Configuré un controlador de interrupción para que SPI (en modo I2S) haga lo mismo. Puse una bandera cuando se generó la interrupción y luego esta bandera 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 en el 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 que el sonido de generación fuera muy simple (como valor = 1000), y aún así 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 interrupción. 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 es una buena solución.

    
pregunta user929404

2 respuestas

4
  

las interrupciones se generaron demasiado rápido y el código en el bucle 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 el indicador SPI_I2S_FLAG_TXE en el registro CODEC_I2S . Es posible que haya otros indicadores que deba borrar: consulte la hoja de datos / manual.

    
respondido por el Turbo J
0

Borraste el indicador SPI_I2S_IT_TXE, pero este indicador solo significa "Transmit Buffer Empty", y como no escribiste nada en el buffer de transmisión en tu 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 tanto, no tiene que borrarlo manualmente.

    
respondido por el Étienne

Lea otras preguntas en las etiquetas