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.
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_TXE
bandera en el CODEC_I2S
registro. Puede haber otras banderas que deba borrar: consulte la hoja de datos/manual.
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.
turbo j
transferFlag
declaravolatile
?usuario929404