Hallo zusammen,
ich muss an zwei GPIOs die Siagnale decodieren (siehe Bild).
Meine Idee wäre das mit einem Timer zu realisieren. Bei steigender
Flanke würde der Timer anfangen zu zählen und in der Mitte würde immer
ein Interrupt auslösen um die beiden GPIO-Werte zu holen. Die Daten
liegen mit einer Geschwindigkeit von 500kHz an den GPIOs an.
Die frage ist wie der Timer konfiguriert werden muss. Hat jemand eine
Idee?
Grüße Dennis
Vermutlich lauft der Takt des GPIO Signales asynchron zum Prozessortakt.
Nach Shannon musst Du dann mindestens 2 mal pro Takt abtasten. Also
setzt Du eine Timer, der Dir mindestens zwei Interrupts pro Takt erzeugt
und wertest in der Interruptroutine entsprechend aus.
Was erzeugt diese komischen Signale?
Dennis schrieb:> Kann man auch hier mit DMA arbeiten?
Nur falls beide GPIO am gleichen PORT haengen. Dann koenntest Du mit dem
DMA Signal vom Timer das GPIOx->IDR Register auslesen und wegschreiben.
Ich fasse mal zusammen:
-Ein freilaufender Timer der alle 666ns auslöst um die Siganel zweimal
abzutasten.
-Der Timer wird über einen externen Interrupt (EXTI#) gestartet.
Ist es möglich das alles in einem Timer zu vereinen, ohne den (EXTI#) zu
benutzen?
Fuer was brauchts Du den EXTI? Der Timer laeuft frei, du sampelst
kontinuierlich und wertest im Interrupt oder mit DMA aus. Die Flanken
muss die IRQ/DMA Routine durch Vergleich mit dem letzten gesampelten
Wert finden.
Ich muss aber irgendwann zu beginn bei der aller ersten Flanke den timer
starten, bzw den Counter reseten.
Es kann auch vorkommen, dass sich die Zeiten einwenig ändern. Dann wäre
es hilfreich irgendwie nach zu trimmen. Ich müsste ab und zu bei einem
Flankenwechsel den Timer reseten.
Meine Idee von 14:20 passt nicht! Vermutlich brauchts Du zwei Timer...
Zunaechst eine weitere Frage: Wie lange koennen den die Sequenzen
werden?
Und eine weitere neugierige Frage: Was erzeugt das 2-Stufensignal?
Gpio1 startet TimA. TimA->ARR gesetzt fuer Ueberlauf alle 666ns.
TimA->CNT vorbesetzt mit 333ns (Periode/2) . TimA UpdateEvent sampelt
GPIO1/2. DMA ist fuer 40 Samples gesetzt. Dma Full Transfer stoppt
Datenaufnahme, startet Auswertung und setzt TimA->CNT wieder auf
Periode/2.
Damit hast du den Samplepunkt in der Mitte des Taktpulsfensters und 335
ns Platz fuer Ablage zwischen Sensor- und Auslesetakt.
anbei befindet sich mein code und das STM32CubeMX project file.
Ich habe mir ein einfaches Programm geschrieben, das bei jeder
steigender Flanke am GPIO PA0 über DMA den Register Inhalt von
GPIOC->IDR in die Variable gSamples speichert.
Nur leider wird immer das transfer error interrupt flag "CTEIF0" bei
steigender Flanke ausgelöst.
Ich habe gerade herausgefunden, dass es mit DMA2 funktioniert aber mit
DMA1 nicht.
Nur leider wird DMA2 bei Timer1 und Timer8 eingesetzt.
Hat jemand eine Erklärung dafür?
Doch, das muss gehen!
Bist Du systematisch vorgegangen?
- Kannst Du Tim2 wie gewollt starten?
- Gehen andere DMA Transfers?
- Stimmen die tatsaechlichen Registerwerte mit den erwartetet Werte
ueberein?
Vielleicht finde ich Zeit mit Nut/OS SVN Trunk ein Beispiel zu
programmieren:
- Usr Taster (PA0) startet TIM2
- Tim2 UE sampelt GPIOC->IDR 100 mal
- DMA TC stoppt Timer.
Beim F4 liegen die GPIO auf dem AHB1 Bus. Nur DMA2 kann einen AHB1 <->
Memory (Memory-to-Memory) Transfer machen. Du brauchst also Timer, die
DMA2 benutzen, um GPIO DMA Transfers mit dem Timer zu triggern.
Das Programm oben läuft auf einem Nucleo-F411, mit einem Jumper von
PC13, dem blauen User Button nach PB10 ( TIM1_CH1, Arduino D7). Ich habe
4 Transfers programmiert. Ich benutze die fallende Flanke, da der
Userbutton mit einem Kondensator gebrückt ist, und unterschiedliche
Triggerpegel bei der steigenden Flanke eine Verzögerung zwischen Taster
und Logikanalysator vorgaukeln. Der Userbuttom ist Kanal 0, die
steigende Flanke ist der Abtastzeitpunkt fuer den GPIO und schaltet
PB11/TIM1_CH2 high. Mit jedem Tastendruck gibt es die angezeigte
Sequenz.