Ich habe ein Klangexperiment ausprobiert und mit Beispielcode begonnen, der Daten über I2S an den Audio-Codec des Discovery F4 sendet. Der Beispielcode verwendete Polling in der Hauptschleife und sendete Daten, wenn der Sendepuffer leer war.
Ich habe einen Interrupt-Handler für SPI (im I2S-Modus) eingerichtet, um dasselbe zu tun. Ich habe ein Flag gesetzt, als der Interrupt generiert wurde, und dieses Flag hat dann die Übertragung von Daten in der Hauptschleife ausgelöst. Das Problem ist, dass die Interrupts zu schnell generiert wurden und der Code in der Hauptschleife nie ausgeführt wurde. Ich musste Interrupts deaktivieren und aktivieren, damit dies funktioniert.
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();
}
}
}
Hauptschleife:
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();
}
}
Ich habe sogar die Tonerzeugung sehr einfach gemacht (wie Wert = 1000), und es hat immer noch nicht funktioniert, ohne die Interrupts zu aktivieren und zu deaktivieren. Tatsächlich wurden LED5 und LED6 überhaupt nicht eingeschaltet, was anzeigt, dass die Hauptschleife nicht betreten wurde. Außerdem habe ich den Code "Ton erzeugen und an SPI übertragen" in den Interrupt-Handler eingefügt. Dies funktionierte, aber der Ton war weicher als der oben gezeigte aktuelle Code.
Der Cortex M4 auf dem STM ist definitiv nicht so langsam, die FPU ist auch eingeschaltet. Ich plane, eine DMA-Version davon zu erstellen, aber ich denke nicht, dass das Ein- und Ausschalten von Interrupts eine gute Lösung ist.
Die Interrupts wurden zu schnell generiert und der Code in der Hauptschleife nie ausgeführt
Dies ist immer dann der Fall, wenn Sie vergessen haben, ein Interrupt-Flag zu löschen - der Handler wird immer wieder ausgeführt.
SPI_I2S_FLAG_TXE
Der obige Code löscht das Flag im Register nicht CODEC_I2S
. Möglicherweise müssen Sie andere Flags löschen - sehen Sie im Datenblatt / Handbuch nach.
Sie haben das SPI_I2S_IT_TXE-Flag gelöscht, aber dieses Flag bedeutet nur "Transmit Buffer Empty", und da Sie in Ihrem Interrupt nichts in den Sendepuffer geschrieben haben, wird das Flag sofort wieder von der Hardware gesetzt, nachdem Sie es gelöscht haben.
Deshalb SPI_I2S_SendData(CODEC_I2S, value);
muss sich die Leitung in Ihrem Interrupt befinden, nicht in Ihrer Hauptschleife. Als Nebeneffekt löscht das Schreiben von Daten in den Sendepuffer das TXE-Flag, daher müssen Sie es nicht manuell löschen.
TurboJ
transferFlag
deklariertvolatile
?Benutzer929404