Guten Morge Leute! Mit meinem STM32F411RE NUCLEO Board habe ich mein Projekt gestartet. Jede Peripherie die ich für die Umsetzung benötige habe ich erfolgreich unter Kontrolle! Nun hat sich ein kleines Zeitproblem eingestellt, da ich meine Werte nicht Gleichzeitig über 3 Schnittstellen bekomme(2* SPI,1*i2c). Um die beste genauigkeit zu erzielen wäre eine gleichzeitige Ansteuerung der Schnittstellen nötig. Ich könnte natürlich mehrere µC auf meiner Prototypen Platine plazieren und die Schnittstellen somit gleichzeitig auf verschiedenen µC's laufen lassen . Ist natürlich nicht die besonders elegante Lösung.... Wie sieht es aus mit multi core µC's aus? Sind diese genau für diesen Zweck da? Dennoch erscheint mir es irgendwie ein bisschen überdimensioniert, wie sieht der Programmieraufwand aus wenn ich mich jetzt als fortgeschrittener Programmierer der STM32 µC Welt bezeichnen würde :O? In freeRTOS habe ich mich eingelesen und festgestellt das man es nicht mal auf die schnelle lernt. Hat hier jemand vielleicht einen Tipp wie ich mich da am besten reinarbeite? Sonst schonmal im vorraus danke für die Hilfe!
Walt N. schrieb: > da > ich meine Werte nicht Gleichzeitig über 3 Schnittstellen bekomme Was bedeuetet für dich "Gleichzeitig"? Wenn dir 1ms und kleiner "gleichzeitig" genug ist, dann sollte es doch auch so gehen...sonst hol dir die Daten per DMA, da erfolgt die Ansteuerung "gleichzeitig".
Gast
#6183405
"Gleichzeitig" ist natürlich ein (zeitlich) dehnbarer Begriff bei nur einem Core... Wie hattest Du Dir vorgestellt, dass das funktioniert? (Free)RTOS löst das Problem auch nicht wenn nur eine Recheneinheit da ist... VG, Stephan
Stephan schrieb: > "Gleichzeitig" ist natürlich ein (zeitlich) dehnbarer Begriff bei nur > einem Core... > Wie hattest Du Dir vorgestellt, dass das funktioniert? Zum meinem bedauern musste ich festellen dass ich mein Signal kontinuierlich senden muss, nur ein gesendetes Signal reicht leider nicht aus um es auf Empfängerseite mit nötigem Erfolg zu entschlüsseln.
Adam P. schrieb: > Was bedeuetet für dich "Gleichzeitig"? Damit meine ich eigentlich das ich meine Signale Kontinuierlich ohne Unterbrechung senden muss.
Walt N. schrieb: > Zum meinem bedauern musste ich festellen dass ich mein Signal > kontinuierlich senden muss, nur ein gesendetes Signal reicht leider > nicht aus um es auf Empfängerseite mit nötigem Erfolg zu entschlüsseln. - Was für ein Signal? - Entschlüsseln? Also wenn dir deine SPI / I²C Peripherie auf eine Anfrage nicht antwortet, dann hast du wohl ein anderes Problem... Leider verstehe ich jetzt noch weniger, nach diesem Beitrag von dir :-/ Zu wenig Infos und etwas verwirrend. "Kontinuierlich": Ist auch (zeitlich) nicht direkt spezifiziert. Oder läuft dein µC in sich zu langsam (Taktfrequenz), dass du nicht hinterher kommst?
Walt N. schrieb: > da > ich meine Werte nicht Gleichzeitig über 3 Schnittstellen bekomme(2* > SPI,1*i2c). Die Übertragung selbst dürfte kein größeres Problem sein, die drei Hardwareeinheiten arbeiten ja eigenständig und wenn man die DMA-Kanäle richtig gewählt hat auch nahezu unabhängig voneinander (auf Teilen des Bus sind sie aber auch wieder nacheinander). Aber du wirst es nicht schaffen alle drei wirklich "Zeitgleich" zu starten, dass sind nunmal drei Kommandos die nur nacheinander ausgeführt werden können. Selbst mit mehreren Core ist es arg schwierig die Taktgenau gleichzeitig dieses Kommando ausführen zu lassen. Spätestens beim Speicherzugriff müssen auch die sich wieder schön der Reihen nach anstellen. Du solltest vielleicht nochmal dein Konzept überdenken oder aber in Richtung FPGA überlegen, die können sowas eher.
Adam P. schrieb: > - Was für ein Signal? > - Entschlüsseln? Meine I2C/SPI Verbindung funktioniert einwandfrei! Ich sende eine Signal über Ultraschall. Damit muss meine SPI Schnittstelle ohne unterbrechung senden. Dazwischen befindet sich natürlich noch ein bisschen Elektronik und aufgrund analoger Aktoren muss ich mein Signal ohne unterbrechung senden.
Gast
#6183425
Walt N. schrieb: > Zum meinem bedauern musste ich festellen dass ich mein Signal > kontinuierlich senden muss Wobei jetzt GLEICHZEITIG und KONTINUIERLICH Begriffe aus unterschiedlichen Domänen sind... Wenn ich Dich trotzdem zu verstehen versuche: Du willst von einem System (1x Core) GEICHZEITIG über 2 Interfaces (SPI/I2C) Daten rausschicken... (die Empfängerseite mal ganz aussen vor). Das wird nicht funktionieren, wenn Du mit GLEICHZEITG tatsächlich ein dt von 0 vorgibst...
Walt N. schrieb: > aufgrund analoger Aktoren muss ich mein Signal ohne unterbrechung > senden. Dann nimm DMA mit double Buffer. Der sendet dir dann "ohne" µC Last die ganze Zeit, lediglich die Neuinitialisierung nach jedem DMA Block muss dann kurz im Interrupt stattfinden (in dieser Zeit versendet er ja den zweiten Buffer / keine Unterbrechung)
Gast
#6183429
Walt N. schrieb: > Wie sieht es aus mit multi core µC's aus? Sind diese genau für diesen > Zweck da? Nein eher nicht. Die Kerne teilen sich gewisse Ressourcen deswegen hast du da noch weniger unter Kontrolle, wann genau was passiert. Möglicherweise ist noch nicht klar, was du machen willst. Es könnte die synchrone Übertragung von Daten auf unterschiedlichen Schnittstellen sein oder auch die parallele kontinuierliche Übertragung (aber nicht zwingend Synchron). Höre mal mit den Geheimnissen auf und lege die Karten offen auf den Tisch. Was hast du vor zu erreichen und wozu ist das gut? > Meine I2C/SPI Verbindung funktioniert einwandfrei! Und doch wohl nicht so, wie du es brauchst. Deswegen ist dieser Hinweis vollkommen wertlos. Wenn wir wüssten, was du brauchst und eine Vorstellung von deinem bestehenden Lösungsansatz haben, der angeblich "einwandfrei" funktioniert, könnten wir Dir vielleicht hilfreiche Tipps geben. Aber so sagst du nur: Ich habe alles richtig aber aber es geht nicht. Sagt mir nicht, was ich falsch gemacht habe, denn es ist ja alles richtig. Hä?
Adam P. schrieb: > Dann nimm DMA Ok das probiere ich mal! Danke
Stefan ⛄ F. schrieb: > Höre mal mit den Geheimnissen auf und lege die Karten offen auf den > Tisch. --> Walt N. schrieb: > Adam P. schrieb: >> Dann nimm DMA > > Ok das probiere ich mal! Danke Da hat meine Klaskugel heute wohl einen guten Tag :-D
Gast
#6183456
Adam P. schrieb: > Da hat meine Klaskugel heute wohl einen guten Tag Ja, vermute ich auch. Wir müssen abwarten, was der TO dazu sagt.
Was ich machen möchte ist ein Phasenmoduliertes Signal über einen DAC (MCP4922) an einen Piezo schicken der mir dann ein Ultraschallsignal erzeugt. Daher muss ich aber nun eine statische Wertetabelle erzeugen um den DMA modus zu nutzen? Oder kann ich die während dem DMA auch ändern?
Walt N. schrieb: > Oder kann ich die während dem DMA auch ändern? Kannst du auch...je nachdem wie lange du dafür brauchst.
Gast
#6183485
Walt N. schrieb: > Was ich machen möchte ist ein Phasenmoduliertes Signal über einen DAC > (MCP4922) an einen Piezo schicken der mir dann ein Ultraschallsignal > erzeugt. Daher muss ich aber nun eine statische Wertetabelle erzeugen um > den DMA modus zu nutzen? Oder kann ich die während dem DMA auch ändern? Natürlich.
Gast
#6183557
SPI und I^2C sind aus Core Sicht ja langsame Ereignisse mit DMA, Interrupts, Timer kann man sehr viele Dinge parallel machen. nur eine geht gar nicht: busy waiting Multicore macht die Sache übrigens nicht einfacher da man auch noch die Cores synchronisieren muss
Gast
#6183601
Zeig doch mal, wie deine I2C Kommunikation funktioniert. "Funktioniert" ist erstmal nicht viel wert, denn es gibt unterschiedliche Ansätze wie es funktionieren kann. Wenn du etwas blockierend schickst, was in vielen Tutorials der erste und schnellste Schritt zum ersten Erfolg ist, kannst du in der Zeit eben nix anderes machen, der µC wartet. Es gibt aber viele Methoden, Sachen quasiparallel zu machen. Komplett analog kann das Ganze ja eh nicht sein, weil dein ADC ja auch nur diskrete Werte zu diskreten Zeitpunkten bekommt. Klar mittelt/interpoliert der das dann, aber erstmal kannst du nichts wirklich kontinuierlich erzeugen. Die Frage ist, welcher Minimalabstand zwischen den neuen Werten erlaubt ist und ab wann es Probleme im Ultraschall gibt. Glaube mir, du möchtest keinen Multicore.
Ich wette zu 99% benötigst du für deinen Anwendungsfall garantiert kein besseres Echtzeit. Beschreibe dein Vorhaben doch mal genauer.
Gast
#6183781
Walt N. schrieb: > Adam P. schrieb: >> - Was für ein Signal? >> - Entschlüsseln? > > Meine I2C/SPI Verbindung funktioniert einwandfrei! Ich sende eine Signal > über Ultraschall. Damit muss meine SPI Schnittstelle ohne unterbrechung > senden. Dazwischen befindet sich natürlich noch ein bisschen Elektronik > und aufgrund analoger Aktoren muss ich mein Signal ohne unterbrechung > senden. Für Audioanwendungen wird gewöhnlich der I2S Bus, mit 192KS wäre US vermutlich kontinuierlich machbar.
Gast
#6183799
NichtWichtig schrieb: > Für Audioanwendungen wird gewöhnlich der I2S Bus, mit 192KS wäre US > vermutlich kontinuierlich machbar. Was bedeutet "US"?
Stefan ⛄ F. schrieb: > NichtWichtig schrieb: >> Für Audioanwendungen wird gewöhnlich der I2S Bus, mit 192KS wäre US >> vermutlich kontinuierlich machbar. > > Was bedeutet "US"? Ultraschall. Siehe Walt N. schrieb: > Was ich machen möchte ist ein Phasenmoduliertes Signal über einen DAC > (MCP4922) an einen Piezo schicken der mir dann ein Ultraschallsignal > erzeugt.
Wie erstelle ich mein Chipselect Signal wenn ich die SPI Schnittstelle im DMA Modus benutze? Der MCP4922 übernimmt die Daten nur wenn ich mit dem Chipselect Signal. In der
1 | |
Funktion kann ich nach der Übertragung mein Chipselect Signal wieder auf HIGH schalten. Aber wo ziehe ich das CS Signal am besten auf LOW?
Gast
#6183989
Walt N. schrieb: > Aber wo ziehe ich das CS Signal am besten auf LOW? Ich würde mal sagen, direkt vor dem Start der DMA Übertragung.
Stefan ⛄ F. schrieb: > Ich würde mal sagen, direkt vor dem Start der DMA Übertragung. Wenn ich mit meiner DMA Übertragung eine Wertetabelle übertrage kann ich ja nicht nach jeden 16 bit ( wie es das Datenblatt vom MCP4922 verlangt) das Chipselect Signal dazwischen schalten. Der überträgt ja die Ganze Wertetabelle auf einmal.
Gast
#6184526
Stefan ⛄ F. schrieb: > Ich würde mal sagen, direkt vor dem Start der DMA Übertragung. Walt N. schrieb: > Wenn ich mit meiner DMA Übertragung eine Wertetabelle übertrage kann ich > ja nicht nach jeden 16 bit ( wie es das Datenblatt vom MCP4922 verlangt) > das Chipselect Signal dazwischen schalten. Der überträgt ja die Ganze > Wertetabelle auf einmal. Kannst du nicht und sollst du nicht. Warum willst du es denn tun?
Stefan ⛄ F. schrieb: > Kannst du nicht und sollst du nicht. Warum willst du es denn tun? Sieht im Datenblatt irgendwie echt danach aus :-/
Gast
#6184535
Adam P. schrieb: > Sieht im Datenblatt irgendwie echt danach aus Was steht wo in welchem Datenblatt? Zitiere es bitte. Wenn dein Peripherie-Chip alle 16 bit so einen Impuls braucht, dann taugt er nicht für DMA.
MCP4902/4912/4922 Datenblatt Seite 23: "The write command is initiated by driving the CS pin low, followed by clocking the four Configuration bits and the 12 data bits into the SDI pin on the rising edge of SCK. The CS pin is then raised, causing the data to be latched into the selected DAC’s input registers." "Any clocks past the 16th clock will be ignored."
Gast
#6184541
Ja Kacke, dann geht DMA halt nicht.
Stefan ⛄ F. schrieb: > Ja Kacke, dann geht DMA halt nicht. Oder zumindest halt nur für die 2 Byte :-) Da weiß ich aber nicht ob sich das zeitlich überhaupt lohnt...
Stefan ⛄ F. schrieb: > Warum willst du es denn tun? Ich erzeuge mit dem mcp4922 ein 40Khz Signal und an ihn sende ich entweder 0x3fff oder 0x3000 mit der SPI Schnittstelle. Nach 20 Schwingungen kommt ein Phasenwechsel (0x3fff, 0x3000 ...0x3fff, 0x3000 (Phasenwechsel), 0x3000, 0x3fff). Dadurch wird meine Wertetabelle ziemlich groß obwohl die Werte sich eigentlich die ganze Zeit wiederholen, aber dadurch das ich nun DMA benutze muss ich sie halt so in den speicher schreiben. Und im Anhang der write command für meinen DAC, an dem CS Signal komme ich nicht dran vorbei.
Gast
#6184560
Da wäre ein Wandler mit I²S Schnittstelle wohl besser geeignet gewesen. DMA scheint mir hier inzwischen sinnlos. Ich würde die Kommunikation mit einem Timer-Interrupt machen und dafür sorgen, dass dieser niemals gestört (unterbrochen) wird.
Stefan ⛄ F. schrieb: > Ich würde die Kommunikation mit einem Timer-Interrupt machen Seh ich das dann richtig...? Walt N. schrieb: > entweder 0x3fff oder 0x3000 1Hz hat dann 2 Zustände (Werte). 40kHz => T=25µs Also 1 Wert alle 12,5µs Meinst dass alles passt zeitlich in dieses Zeitfenster?
Gast
#6184576
Adam P. schrieb: > Meinst dass alles passt zeitlich in dieses Zeitfenster? Wenn du ein Rechteck-Signal mit 40kHz ausgeben willst, dann brauchst du 80.000 Werte pro Sekunde, also Intervalle von 12,5 Mikrosekunden. Aber Rechteck-Signale gibt es in der Natur nicht, dein Signal wird durch die Übertragungsstrecke mit mehreren Oberwellen stark verzerrt. Ich hoffe, du hast das bedacht.
Adam P. schrieb: > Meinst dass alles passt zeitlich in dieses Zeitfenster? Dafür muss halt die Schnittstelle schnell genug sein. Mit SPI habe ich es hinbekommen. Wegen der slew rate vom DAC sieht es nach einem Trapezsignal aus. Ist aber auch noch ok.
Gast
#6184580
Wenn das CS Signal vom SPI erzeugt wird und nicht als DIO kann man i.d.R es auch über DMA erzeugen. ( Ich hab zumindest noch kein µC gesehen bei dem das nicht geht) Sonst muss man einen Interrupt verwenden der vom SPI ausgelöst wird wenn sein Sendebuffer leer ist. Der Interrupt kann Daten direkt in die Senderegister schreiben oder den DMA neu aufsetzen. Und auch Pins setzten.
Gast
#6184586
@Volle: Guter Hinweis!
Ich habe gerade mal ins Datenblatt des STM32F303 geschaut, der scheint
das zu können. Man kann die Größe des Frames auf 4 bis 16 bit einstellen
und die NSS Einheit erzeugt automatisch Impulse alle n Bits.
Interessant, das Feature kannte ich noch nicht.
Dann ist mein Kommentar
> Ja Kacke, dann geht DMA halt nicht.
wohl nicht richtig gewesen.
Dann verusche ich mich mal da dran!
Adam P. schrieb: > lediglich die Neuinitialisierung nach jedem DMA Block muss dann kurz im > Interrupt stattfinden Das bedeutet ich muss die Funktion HAL_SPI_Transmit(); nochmal in void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) ausführen?
Gast
#6194914
Walt N. schrieb: > mcp4922 ein 40Khz Signal und an ihn sende ich entweder 0x3fff oder > 0x3000 Das bedeutet, du erzeugst mit dem DAC ein binäres Signal bestehend aus den beiden Spannungswerten 1. Vref * 4095/4096 ~= Vref * 100% = Vref 2. Vref * 0/4096 = Vref * 0% = 0V Warum benötigst du für diese Aufgabe einen DAC? Das kann ein Portpin von deinem uC doch auch. Ein passend gesetzter Timerausgang erzeugt dir auch so ein PWM Signal mit 50% duty und den Phasenwechsel bekommst du, wenn du den Timerausgang invertierst.
void schrieb: > den > Phasenwechsel bekommst du, wenn du den Timerausgang invertierst. Den Phasenwechsel bekomme ich dann aber nicht unabhängig von den anderen Prozessen hin oder?
Stefan ⛄ F. schrieb: > Man kann die Größe des Frames auf 4 bis 16 bit einstellen > und die NSS Einheit erzeugt automatisch Impulse alle n Bits. Wie im Anhang zu sehen funktioniert das NSS Signal leider nicht so wie ich es benötige. Wie ich es einstelle dass es nach 16 Bit einen Impuls erzeugt habe ich nicht herausgefunden.... Meine 40 Datensätze werden richtig übertragen, anschließend kommen aber noch ein andere Werte die so nicht in meinem Array drin stehen. Meine SPI3 Schnittstelle habe ich wie folgt initialisiert:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
Im File stm32f4xx_hal_msp.c wird die Initialisierung so generiert. Die einzige Änderung die ich vorgenommen habe war, GPIO_NOPULL -> GPIO_PULLUP für Pin PA15.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
Den Neustart der DMA Übertragung mache ich wie folgt in main.c
1 | |
2 | |
3 | |
4 | |
5 | |
Der Versuch das CS Signal hier selber zu erzeugen hat leider nur eine Flanke nach allen 40 Werten hervorgerufen..
Walt N. schrieb: > Wie im Anhang zu sehen Anhang verschwunden...
Gast
#6201099
Walt N. schrieb: > Den Phasenwechsel bekomme ich dann aber nicht unabhängig von den anderen > Prozessen hin oder? In dem Punkt unterscheidet sich die Nutzung von einem per SPI angebunden DAC und einem Timerausgang nicht. Den Timer stellst du auf 50% duty, passende Periode und Erzeugung von Timer overflow Interrupt. In jeder ISR zählst du mit, wie oft diese schon aufgerufen wurde. Beim 20. Aufruf der ISR investiert du den Timerausgang. (Zum Register update des Timers basierend auf dem Timer overflow interrupt könnte man natürlich noch den DMA nehmen, aber das würde ich nicht ohne Not machen.) Die Unabhängigkeit von anderen Prozessen ergibt sich durch die Bearbeitung dieser Aufgabe vollständig innerhalb der ISR.
Gast
#6201652
void schrieb: > Die Unabhängigkeit von anderen Prozessen ergibt sich durch die > Bearbeitung dieser Aufgabe vollständig innerhalb der ISR. Hallo Walt, hier noch einmal etwas anschaulicher mit Pseudo-Code für Atmega328P (Arduino Nano).
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
Wie gesagt, in der ISR liegt hier die komplette Arbeit für die CPU. Die ISR wird zwar verhältnismäßig oft aufgerufen, ist aber sehr kurz. Das unterbricht andere laufende Prozesse daher nur minimal. Im Anhang ein Oszillogram - gelb: Timerausgang mit 8kHz PWM und Phasen-Wechsel wie gewünscht nach 20 Perioden (40kHz passte hier vom Vorteiler nicht, 64kHz ging und lief auch problemlos) - blau: Ein anderer Prozess (schickt das Wort "task" per Uart) Der Trick ist eben in der ISR nur zwischen invertiertem und nicht-invertiertem PWM mode(output compare) hin und her zu schalten. > /* switch PWM on OC0A between inverting and non-inverting mode */ > TCCR0A ^=0b01000000; // (toggle bit COM0A0 0<->1) Bei deinem STM32F411xC/E bietet sich da z.B. der General-purpose Timer (TIM2..TIM5) an. Das äquivalente Register-Bit ist dann TIMx_CCMR1.OC1M. siehe RM0383 Kapitel 13.4.7 > TIMx capture/compare mode register 1 (TIMx_CCMR1) > > bits 6:4 OC1M: Output compare 1 mode > 110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1 else inactive. (..) > 111: PWM mode 2 - In upcounting, channel 1 is inactive as long as TIMx_CNT<TIMx_CCR1 else active. (..)
Beitrag #6211580 wurde von einem Moderator gelöscht.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.


