Forum: Mikrocontroller und Digitale Elektronik Problem mit STM32 CubeMX I2S DMA


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Rene B. (themason) Benutzerseite


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leuts ....

ich habe mal wieder ne Ecke an der ich momentan etwas hänge und nicht so 
recht weiß warum ...
Ich habe ein STM32F407 Board welches ich mit System Workbench for STM32 
und CubeMX programmiere.
Ich möchte I2S (erstmal nur TX) nutzen und auf einem Audio DAC per DMA 
ausgeben. Die Konfiguration von CubeMX passt soweit, Clocks passen, 
Daten kommen raus und Audio ist auf dem Wandler auch zu hören.
Ich benutze einen PCM5102A DAC, da ich bei dem keinen Master Clock 
benötige.
Ich gebe fürs erste einfach nur mal nen Sinus aus den ich auf beiden 
Kanälen hören möchte.
Es kommt auch auf dem einen Kanal ein Sinus raus. Auf dem anderen zwar 
auch, aber da sind Spikes zu sehen. Die Spikes treten (hab ich mit nem 
Scope gemessen) immer entsprechend der Blocklänge auf (also in dem Falle 
alle 64 Samples * 48kHz = 1,32ms).
Was mich etwas stutzig macht ist das nur der eine Kanal betroffen ist. 
Der andere klingt (und ist aufm Scope) sauber.
Ich verwende den Circular DMA Buffer. Ich habe 2 Buffer angelegt und bei 
jedem DMA Transfer schalte ich zwischen den Buffern um, sodass während 
der eine Wiedergegeben wird, der andere befüllt wird.
Ich habe mal das Projekt als Export angehängt. Die Umschaltung der 
Buffer findet in der Datei audio_buffer.c statt und wird von 
"HAL_I2S_TxCpltCallback" aufgerufen.
Hat irgendjemand vllt ne Idee warum das letzte Sample immer "falsch" ist 
und warum nur auf einem Kanal, und (die Gretchenfrage) was ich dagegen 
machen kann ?

von Martin B. (ratazong)


Bewertung
1 lesenswert
nicht lesenswert
Du benutzt ja den HAL_I2S_TxHalfCompleteCallback() des Circular DMA gar 
nicht. Warum?

Im Circular Mode gibt es zwei Callbacks. Der Halfcomplete kommt, wenn 
die erste Hälfte des DMA Buffers gesendet wurde. Dann kannst Du die 
erste Hälfte neu füllen. Wenn der Complete kommt kannst Du die zweite 
Hälfte füllen u.s.w.

Du füllst den kompletten Buffer der DMA nach dem Complete Callback. Der 
Complete Callback muss jetzt allerschnellstens die untere Hälfte des DMA 
Buffers füllen, denn die circular DMA arbeitet ja schon in dem Bereich.

Wenn bei Dir nur ein Kanal betroffen ist, müsste es der rechte sein.

von Rene B. (themason) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ah oki ...
Also die beiden Callbacks sind quasi für 50% und 100% des Buffers 
übertragen gedacht ? Das war mir nicht ganz klar.
Ich hatte das irgendwie mit Full und Halfduplex verwechselt ... aber so 
im Nachhinein ist das natürlich Quäse.

Also demnach müsste ich bei TxHalf die erste Hälfte des Buffers befüllen 
(weil diese gerade übertragen worden ist und nun die zweite hälfte 
angefangen wird), und bei TxCplt die zweite Hälfte (weil diese gerade 
übertragen worden ist und der Buffer wieder mit der ersten Hälfte 
anfängt) befüllen ?

von Bülent C. (mirki)


Bewertung
0 lesenswert
nicht lesenswert
Wähle einen möglichst kleinen dma buffer

von Rene B. (themason) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Bülent ... schon klar ;-)

Ich wollte erstmal mit 64 Samples anfangen. Später werden es dann sicher 
32 Samples werden. Sollte für nen Synthie ausreichend sein :-)

von Martin B. (ratazong)


Bewertung
1 lesenswert
nicht lesenswert
Rene B. schrieb:
> Ah oki ...
> Also die beiden Callbacks sind quasi für 50% und 100% des Buffers
> übertragen gedacht ? Das war mir nicht ganz klar.
> Ich hatte das irgendwie mit Full und Halfduplex verwechselt ... aber so
> im Nachhinein ist das natürlich Quäse.
>
> Also demnach müsste ich bei TxHalf die erste Hälfte des Buffers befüllen
> (weil diese gerade übertragen worden ist und nun die zweite hälfte
> angefangen wird), und bei TxCplt die zweite Hälfte (weil diese gerade
> übertragen worden ist und der Buffer wieder mit der ersten Hälfte
> anfängt) befüllen ?

Ja genau.
Und wenn Du es richtig schnell haben willst musst Du von CubeMX runter, 
sonst ist mit kleinen Buffern nichts. Da ist zu viel overhead drin.

von Rene B. (themason) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Na ja ... ich würde später CubeMX als "Rahmen" nutzen und mich dann 
direkt an die Interrupts hängen. Die Initialisierung ist ja schon recht 
schick gelöst. Aber ich denke fürs erste reicht das erstmal.

Ich setz deinen Tipp mal um. Erstmal vielen Dank.
Wenn ich fragen hab nerv ich euch wieder ;-)

von Rene B. (themason) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ok ...

Habs mal umgesetzt und nu funzt es. Vielen Dank nochmal.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.