mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 Frequenz Messung (>10MHz)


Autor: Mark Wer (mark_wer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute :)

Bin seit kurzem im Besitz eines STM32F4 Discovery Boards. Hab nun 
versucht - mit Hilfe von Beiträge hier - mit Capture Interrupt 
Frequenzen zu messen. Leider funktioniert mein Programm nur bis 
Frequenzen <700KHz und sonderlich genau ist es auch noch nicht. Habe 
jetzt schon seit Stunden alles mögliche im Internet durchforstet, aber 
komme auf keine Lösung. Ich würde mich freuen, wenn jemand von euch 
einen Tipp hat oder mir sagen könnte, was ich ändern müsste. Durch den 
Prescaler von 1 sollten Frequenzen bis 10MHz ja kein Problem sein und 
Frequenzen unter 1kHz brauche ich auch nicht. Würde es Sinn machen einen 
anderen Timer+Channel zu nutzen? Habe es schon mal mit Tim2 ausprobiert, 
aber da funktioniert dann gar nichts.. Vielen Dank schon mal im Vorraus 
und noch einen schönen Abend.
#include "stm32f4xx_conf.h"

static uint32_t messwert=0;
static float frequenz=0;

void init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_ICInitTypeDef TIM_ICInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  // Clock Enable
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  // Clock enable
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  // Config des Pins als AF-Input
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  // Alternative-Funktion mit dem IO-Pin verbinden
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3);

  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  // Vorteiler einstellen (83 => 1MHz)
  TIM_PrescalerConfig(TIM3, 1, TIM_PSCReloadMode_Immediate);

  // Channel 4
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);

  // Timer enable
  TIM_Cmd(TIM3, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);
}

void TIM3_IRQHandler(void)
{
  static uint16_t pos=0;
  static uint32_t t1=0;
  static uint32_t t2=0;


  if(TIM_GetITStatus(TIM3, TIM_IT_CC4) == SET) {
    // Interrupt Flags loeschen
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);

    if(pos==0) {
      pos=1;
      t1=TIM_GetCapture4(TIM3);
    }
    else {
      t2=TIM_GetCapture4(TIM3);

      if(t2>=t1) {
        messwert=t2-t1;

      }
      else {
        messwert=(0xFFFF - t1) + t2;
      }
      t1 = t2;
    }
  }
}

int main(void)
{
  init();
  SystemInit();

    while(1)
    {
      frequenz = 42000000/messwert;
    }
}

Autor: Jim Meba (turboj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde da mal spontan DMA in den Raum werfen...

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist auch schon eine Menge (relativ) in der ISR. Stutz die mal 
zusammen und sauge nur den Capturewert, setze ein Flag und mach den Rest 
ausserhalb.

Autor: Lurchi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Frequenzmessung mit der Capture-funktion ist zu hohen Frequenzen 
begrenzt durch die Laufzeit der ISR. Ein wenig code könnte man da ggf. 
noch kürzen (beim Löschen der Flags), ganz viel aber nicht. Je nach Takt 
für den µC ist da halt irgendwo Schluss. Ich hätte etwas mehr erwartet 
bei 42 MHz Takt. Per DMA könnte es auch schneller gehen die Daten 
auszulesen. Wenn man will kann man da auch Werte Überspringen / 
ignorieren, wenn sie sehr schnell kommen.

Für eine bessere Auflösung kann man die Zeit für mehr als eine Periode 
messen. Dazu werden neben der Zeitmessung auch noch die Interrupts 
gezählt und eine passende Zahl von Perioden ausgewählt.

Für deutlich höhere Frequenzen sollte man das Signal vor dem µC Teilen, 
ggf. geht das auch mit der µC internen Hardware, etwa indem nicht jede 
Flanke an capture event auslöst, sondern nur etwa jede 8. oder so. Wenn 
man keine niedrigen Frequenzen braucht kann der Teiler (z.B. 128) auch 
immer drin bleiben.

Autor: Mark Wer (mark_wer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal schon mal Danke, für eure Hilfe. Habe die ISR jetzt gekürzt, 
aber es gab leider keine merkbare Verbesserung. Ich würde gern jede 
Flanke erkennen, deshalb fällt diese Möglichkeit leider weg.. Das mit 
dem DMA hört sich nicht schlecht an, hab mich auch schon ein bisschen 
eingelesen, aber so richtig drauf gekommen, wie ich das mit DMA lösen 
kann, bin ich noch nicht.  Würde mich über Tipps freuen.

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Löst jetzt nicht das Problem, aber ich fand schon immer das ein volatile 
bei bestimmten Variablen gut kommt. Besonders wenn sie in einer ISR 
modifiziert werden.

Ein STM32F4 kann 168MHz, use the force Luke!

Autor: Jonas Biensack (jibi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ein STM32F4 kann 168MHz, use the force Luke!

Jo aber nicht auf den IO's soviel zur force junge...

Gruß J

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt hier Beiträge im Forum "Projekte & Code". Allerdings ist die 
Suchfunktion gestört, sodaß ich diese nicht finden kann.

Ein Beispiel mit QVGA-Display findest Du hier: 
http://mino-elektronik.de/fmeter/neue_versionen.htm#a13
Die direkte Messung geht bis 2,5 MHz und mit internem Vorteiler bis 20 
MHz.
Dann gibt es noch eine fertige Lösung für das STM32F429 Discovery Board: 
http://mino-elektronik.de/FM_407/fmeter_407.htm#c1
Hier wird ein interner Timer als Vorteiler für die automatische 
Bereichsumschaltung benutzt.

Autor: Norbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jonas B. schrieb:
>>Ein STM32F4 kann 168MHz, use the force Luke!
>
> Jo aber nicht auf den IO's soviel zur force junge...


Ja, aber wenn man sich über evtl. zu lange Sequenzen in der ISR 
unterhält, könnte der vierfache Takt zu einer Laufzeitverringerung 
beitragen.
Habe nur noch nicht berechnet um wieviel Prozent. ;-)

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: dasrotemopped (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Ein STM32F4 kann 168MHz, use the force Luke!
>Jo aber nicht auf den IO's soviel zur force junge...

Aber auf den externen Timer Eingängen. Ein paar 16bit-Timer kaskadieren, 
ein Zähler mit absoluter Genauigkeit ...

Gruß,

dasrotemopped.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.