STM32 I2S-Interrupt-Nutzung

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.

Ist transferFlagdeklariert volatile?
@TurboJ Ja, das ist es. Da transferFlag anfangs auf True gesetzt ist, sollte die Hauptschleife in jedem Fall mindestens einmal ausgeführt worden sein, wodurch die LEDs aufleuchten würden

Antworten (2)

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_TXEDer 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.

Danke, ich werde dem nachgehen. Ich habe das SPI_I2S_IT_TXE-Flag gelöscht, aber ich werde später heute nach den anderen suchen.

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.