Forum: Mikrocontroller und Digitale Elektronik stm32f4discovery PWM InputMode (DutyCycle und Frequenz)


von Kevin M. (kevin_mc)


Lesenswert?

Hallo zusammen,

ich versuche gerade PWM Signal(Frequenzbereich 100-1000 HZ) auszuwerten. 
Um zu testen, schließe ich ein Signalgenerator an. Ich benutze das 
offizielle Beispiel(PWM-Input),im Debugmode versuchte ich Schritt für 
Schritt, aber habe leider nicht die richtigen Werte von DutyCycle und 
Frequenz ermittelt. Jeder Versuch bekam ich ein verschiedenes Ergebnis. 
Ich habe schon viel Zeit damit verbracht, um den Fehler zu finden. Aber 
zur Zeit noch keine Ahnung, wo der Fehler liegt. Ich weiss nicht, ob ich 
irgendwo nicht richtig programmierte. Kann mir jemand helfen? Ich 
bedanke mich im Voraus.

Mfg
Kevin

int main(void)
{
  /* TIM Configuration */
  TIM_Config();
/* TIM4 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM4 CH2 pin (PB.07),
     The Rising edge is used as active edge,
     The TIM4 CCR2 is used to compute the frequency value
     The TIM4 CCR1 is used to compute the duty cycle value
  ------------------------------------------------------------ */
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);

  /* Select the TIM4 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
  TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);

  /* TIM enable counter */
  TIM_Cmd(TIM4, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);

  while (1);
}

void TIM_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM4 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  /* GPIOB clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  /* TIM4 chennel2 configuration : PB.07 */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;
  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_UP ;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Connect TIM pin to AF2 */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);

  /* Enable the TIM4 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}


void TIM4_IRQHandler(void)
{
  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);

  /* Clear TIM4 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);

  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM4);

  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM4) * 100) / IC2Value;

    /* Frequency computation
       TIM4 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */

    Frequency = (RCC_Clocks.HCLK_Frequency)/2 / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

von Hans (Gast)


Lesenswert?

Ob das while so läuft....  nimm lieber while(1) {;}

Welche Entwicklungsumgebung?

system_init(); fehlt auch. Dein F4 läuft mit irgendeiner Frequenz.

Deine HSE Quarz Konfiguration stimmt sicher auch nicht.

von flix (Gast)


Lesenswert?

Bist Du Dir sicher, dass es nicht geht ?
Wenn Du mit dem Debugger Schritt für Schritt durchgehst, dann hältst Du 
den Timer ja immer an, und damit stimmt die Messung nicht mehr.

Geht auch dann noch schief, wenn Du den Debugger laufen lässt, dann auf 
Pause drückst und dann die Ergebnisse anschaust ?

von holger (Gast)


Lesenswert?

>Wenn Du mit dem Debugger Schritt für Schritt durchgehst, dann hältst Du
>den Timer ja immer an,

Oder noch schlimmer, der Timer läuft einfach weiter.

von Kevin M. (kevin_mc)


Lesenswert?

Hallo Hans,

Dank für Deine Antwort. Ich benutze Coocox unter WindowsXP. Habe 
system_init() versucht, aber geht's auch nicht. Mein F4 läuft mit 168M 
Hz Frequenz, ich habe Frequenz des Timers nicht eingesetzt. Dann läuft 
Counter mit 84M Hz. Ich versuche die Frequenz des Signals mit 100 bis 
1000 Hz auszumessen.
könntest du mir sagen, wie kann ich "HSE Quarz" konfigurieren? Ich habe 
das offizielle Beispiel gesehen, aber diese Konfiguration wurde nicht 
macht. Sollte man selbst noch mal einsetzen?

MfG
Kevin

von Hans (Gast)


Angehängte Dateien:

Lesenswert?

Sieh dir die Datei "system_stm32f4xx.c" im coocox "cmsis.boot/startup" 
Ordner an. Am Anfang stehen die verwendeten Einstellungen.
Mit dem angehängten Excel sheet mußt du dir deinen Sys Clock unbedingt
konfigurieren. Dieses sheet erzeigt dir diese Datei mit deinen 
Einstellungen. Dann musst du diese mit der von Coocox verwendeten 
austauschen.

"The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" 
definein "stm32f4xx.h" file. When HSE is used as system clock source, 
directly or through PLL, and you are using different crystal you have to 
adapt the HSE value to your own configuration."

HSE musst du aber trotzdem noch händisch in "stm32f4xx.h" ändern (dein 
verw. Quarz ( 8 MHZ ! hoffentlich)


Grüße Hans

von Kevin M. (kevin_mc)


Angehängte Dateien:

Lesenswert?

Hallo Hans,
ich habe gerade die Einstellung in der Datei "system_stm32f4xx.c" 
gesehen.
System Clock source: PLL (HSE)
SYSCLK(Hz): 64000000
HSE Frequency(Hz): 8000000
und in der Datei"stm32f4xx.h" schreibt auch
"#if !defined  (HSE_VALUE)
 #define HSE_VALUE    ((uint32_t)8000000)"
Es ist schon richtig konfiguriert, oder?

Kann es sein, dass Counter Frequenz so hoch ist, dass jedes Mal CCR1 und 
CCR2 überläufen?

von Josef (Gast)


Lesenswert?

kann gut sein...

von Kevin M. (kevin_mc)


Lesenswert?

Hallo Flix und Holger,

ja, ich bin ganz sicher, ich habe viel mal versucht. Aber ich machte so, 
setzte ein Breakpoint hinter dem Befehl " Frequency = 
(RCC_Clocks.HCLK_Frequency)/2 / IC2Value;" Ich glaube, wenn ich hier 
setzte, wird das Ergebnis nicht beeinflusst, oder? naja, vermute ich, 
bin nicht sicher.

MgG
Kevin

von Hans (Gast)


Lesenswert?

Dein Timer 4 läüft zu schnell. Der schafft nur 36 MHz! Und lass das 
debuggen
über Coocox. Debugge lieber über die Uart. Und schau, ob dein Interrupt 
aufgerufen wird (ZB Byte setzen und dann über Uart Variable ausgeben)Und 
behalte dein PWM Signal mit einem Osci im Auge, ob es konstant läuft.


Gruß

von Kevin M. (kevin_mc)


Lesenswert?

Hallo Josef,

meinten Sie auch CCR1 und CCR2 Überlaufen, oder?

MfG
Kevin

von Josef (Gast)


Lesenswert?

Kann ich so leider nicht so sagen.

Bräuchte Infos über den Code und das System. Schreibe dir ein kleines
Betriebssystemchen, dass dich über den Status deines F4 informiert (beim 
booten, RCC Flags ausgeben. ZB LSE,LSI,HSI,HSE, Clock Fr. usw.)

Lass dir die Frequenz deines Timers auf einem Pin ausgeben um sie zu 
messen.

von Kevin M. (kevin_mc)


Lesenswert?

Hallo Hans,

meinten Sie so, dass Frequenz von Timer4 kann nicht hier gleich wie 
systemclock/2 einstellen. d.h. muss ich das  "Prescaler value" im "the 
Timebaseunit" konfigurieren, oder?

MfG
Kevin

von Kevin M. (kevin_mc)


Lesenswert?

Hallo Josef,

Dank für die Antwort. Aber verstehe ich noch nicht, welche Code brauchen 
Sie?

MfG
Kevin

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
Noch kein Account? Hier anmelden.