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
Freilaufender Timer. GPIO Interrupts. Im Interrupt Timer auslesen und Zeiten berechnen?
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?
Es ist eigentlich ein 3-Level Siganl was an zwei Komperatoren geht was mir je nach Pegel die oberen Siganel ausgibt
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.
Falls dass Signal auf einem Timercapture des benutzten Timers liegt, dann kannst Du auch den Zeitpunkt der Flanke erfassen. Braucht auch keinen EXTI.
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?
Da das Eingangssignal asynchron ist, mußt Du auch damit rechnen, daß nur GPIO1 oder nur GPIO2 für eine Abtastperiode aktiv sind.
maximal werden 40 bit übertragen. Das ist ein Sensor Interface für ein Drucksensor.
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.
Danke für die Hilfe. Ich werde es ausprobieren und mich dann wieder melden.
Ich habe ein Problem mit DMA, es wird immer der transfer error interrupt flag "CTEIF0" ausgelöst.
1 | HAL_DMA_Start_IT(&hdma_tim3_ch4_up, (uint32_t)&GPIOC->IDR, uint32_t)&gSamples[0], GSAMPLES_SIZE); |
2 | |
3 | __HAL_TIM_ENABLE_DMA(&htim3, TIM_DMA_UPDATE); |
4 | |
5 | /* DMA: Clear Interrupt FLAG */
|
6 | __HAL_DMA_CLEAR_FLAG(&hdma_tim3_ch4_up, DMA_FLAG_TCIF0_4); |
7 | |
8 | HAL_TIM_Base_Start_IT(&htim3); |
Nee, mit HAL setzte ich mich nicht auseinander. Bei HAL muss man nicht nur die Registerbelegung kennen, sondern auch noch was HAL macht.
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?
Ist es somit garnicht möglich mit den anderen Timern und DMA1 von GPIOC->IDR auf gSamples zuschreiben? gibt es vielleicht eine andere Möglichkeit?
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.
VielenDank, ich werde es mir morgen genauer anschauen und versuchen es umzusetzen.
Ich denke, Dein bisheriger Code wird auch gehen, wenn Du einem DMA2 Timer nimmst...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.