Moin Leute,
ich habe mir einen Sinus Generator zur Aufgabe gemacht. Umgesetzt wird
das auf einem STM32 NUCLEO Board L053R8. Meine Werte für den Sinus
speichere ich in einem Array und gebe die Werte per DMA auf den DAC. Der
Sinus hat eine Frequenz von 1.4kHz und Sp-Sp 3.3V. Soweit so gut, nun
möchte ich aber gerne die Frequenz erhöhen, 40kHz wäre das Ziel. Als
Trigger Source benutzt der DAC den DAC_TRIGGER_T6_TRGO vom Timer6.
Dennoch bekomme ich durch Änderung des prescalers und der Periode keine
Frequenz höher als 1.4kHz generiert. Habe ich die SysClock richtig
eingestellt? Vielleicht hat ja jemand ein Tip?
1
/* Includes ------------------------------------------------------------------*/
Walt N. schrieb:> nun> möchte ich aber gerne die Frequenz erhöhen, 40kHz wäre das Ziel.
Kleinere Tabelle benutzen. Mit 25 Stellen statt 1024 wärst du schon fast
am Ziel.
Muss das unbedingt ein Controller sein? Für eine Sinusausgabe braucht
man einen Taktgenerator, einen Adresszähler, einen Speicher für die
Amplitudenwerte und einen DAC, das kann man für fast beliebige
Frequenzen aus wenigen Standard-ICs konstruieren. Nur der Lerneffekt ist
dann natürlich ein anderer.
Georg
>das kann man für fast beliebige>Frequenzen aus wenigen Standard-ICs konstruieren.
Warum sollte man das wollen, wenn ein einziges Standard-IC, nämlich ein
µC es auch tun würde...
required schrieb:> Warum sollte man das wollen, wenn ein einziges Standard-IC, nämlich ein> µC es auch tun würde...
Eben weil man damit sehr viel höhere Frequenzen erreichen kann. Thread
gelesen?
Georg
Georg schrieb:> Eben weil man damit sehr viel höhere Frequenzen erreichen kann. Thread> gelesen?
Also der STM schafft ja wohl locker mehr als 1.4kHz .....
Eric B. schrieb:> Kleinere Tabelle benutzen. Mit 25 Stellen statt 1024 wärst du schon fast> am Ziel.
Das hat funktioniert, danke! Wenn ich die anzahl der Werte nicht
verringern möchte, ist der andere weg doch die Systemclock zu erhöhen,
oder? Kann ich das durch hinzufügen eines externen oscillators
erreichen?
Für 1024 Stufen und 1.4kHz müsste dein Timer auf knapp 700ns Interrupts
generieren :-)
1.4k * 1024 = ~1.5MHz -> 698ns
Das wird eng, daher: Stufen runter.
Du könntest das ganze dynamisch gestalten, alle x kHz nimmst du nur noch
die Hälfte der Werte des arrays, also counter +1, +2, +4, +8, ...
Ggf. Mittelwert aus den übersprungenen Werten bilden (decimation).
Die 25 Werte entsprechen der positiven Halbwelle meines Sinus Signal.
Die Frequenz ist bei 40 kHz, also genau so wie ich sie benötige. Der
oben genannte befehl übergibt einmal die 25 Werte an meinen DAC, wenn
ich das richtig verstanden habe. Nun möchte ich aber bestimmen wie oft
ich diese positive Halbwelle ausgebe. Funktioniert das im DMA modus?
Guest schrieb:> Also der STM schafft ja wohl locker mehr als 1.4kHz .....
Aber nicht mit so hoher zeitlicher Auflösung.
Walt N. schrieb:> Wenn ich die anzahl der Werte nicht verringern möchte, ist der> andere weg doch die Systemclock zu erhöhen, oder?
Erstmal müsstest du nur den Takt für den DAC erhöhen. Viel mehr als 1MHz
schafft der Analogteil aber nicht, siehe Bild. Also reichen die 16MHz
aus dem HSI locker.
> Kann ich das durch hinzufügen eines externen oscillators erreichen?
Das lohnt sich nicht, selbst wenn der DAC mehr könnte. Es ist egal, ob
der Takt extern oder intern per PLL und HSI erzeugt wird, Systemtakt
bleibt Systemtakt. Einen externen Takt brauchst du (nur), wenn der HSI
nicht stabil genug ist, z.B. für CAN oder weil es bei -40°C
funktionieren muss. Oder wenn du unbedingt eine krumme Frequenz
brauchst.
Bauform B. schrieb:
...
> Erstmal müsstest du nur den Takt für den DAC erhöhen. Viel mehr als 1MHz> schafft der Analogteil aber nicht, siehe Bild. Also reichen die 16MHz> aus dem HSI locker.
Der verlinkte Ausschnitt aus dem Datenblatt zeigt die Crux des
STM32-DAC:
- full-scale Sprungantworten brauchen bis zu 12µs für Einschwingen auf 1
LSB
- eine Änderung um 1 LSB geht in 1µs
Das sind einige der Limitierungen dieser eingebauten Peripherie (für
weitere Überraschungen das komplette Kapitel genau lesen, siehe auch
min/max-Werte).
Schon bei moderaten Anforderungen ist mit einem externen Wandler
deutlich besser bedient.
Marcus H. schrieb:> Schon bei moderaten Anforderungen ist mit einem externen Wandler> deutlich besser bedient.
Ich habe nun einen externen Wandler angeschlossen. Per SPI sende ich
meine Daten an den mcp4922. Funktioniert einwandfrei! Meine SPI
Schnittstelle habe ich wie folgt initialisiert:
Die Wertetabelle für den Sinus habe ich so aufgestellt:
1
uint16_tsine_wave[]=
2
{
3
0x800,0xcb3,0xf9b,0xf9b,0xcb3,0x800,0x34c,0x64,
4
0x64,0x34c,0x800,
5
};
Und die Funktion für die Übertragung an den mcp4922 ist diese hier:
1
voidMCP4922_SendByte(uint16_tdac_data)
2
{
3
data[1]=((dac_data>>8)&0x0F)|0x30;
4
5
data[0]=dac_data;
6
7
HAL_GPIO_WritePin(GPIOA,SPI1_CS_Pin,0);
8
9
HAL_SPI_Transmit(&hspi1,data,1,HAL_MAX_DELAY);
10
11
HAL_GPIO_WritePin(GPIOA,SPI1_CS_Pin,1);
12
}
Das Problem besteht immer noch darin dass ich den Sinus mit 40KHz
generieren möchte. Mit dieser kleinen Wertetabelle komme ich auf einen
recht kantigen Sinus von 4,2KHz. Bekomme ich die SPI übertragung noch
schneller hin? Kann ich vielleicht dieses
1
HAL_MAX_DELAY
noch ändern um etwas an geschwindigkeit zu gewinnen? Bin über jeden
Tipp und Hinweis dankbar!
Walt N. schrieb:> Marcus H. schrieb:>> Schon bei moderaten Anforderungen ist mit einem externen Wandler>> deutlich besser bedient.>> Ich habe nun einen externen Wandler angeschlossen. Per SPI sende ich> meine Daten an den mcp4922. Funktioniert einwandfrei!
...
Freut mich, Danke für die Rückmeldung.
Eine eigene Frage?
Dieser Thread ist über 6 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.