2016-12-21 2 views
1

Je souhaite mesurer la fréquence d'un signal PWM. Pour ce faire, j'utilise STM-F401RE et sa fonction Timer_Input_Capture.stm32F4 pwm saisie d'entrée de signal haute fréquence env. 2 MHz?

Le problème est:

  • le signal d'entrée a une fréquence assez élevée (environ 2MHz.) Et,
  • le contrôleur STM-F401RE ne dispose que d'une horloge de 80 MHz

Par conséquent, lorsque en utilisant une routine d'interruption pour compter le nombre de fronts montants du signal d'entrée, il manque de nombreux fronts montants (en fonction de la fréquence du signal d'entrée). En utilisant un oscilloscope et en basculant une broche I/O, j'ai vu qu'il ne peut capturer tout le front montant que lorsque la fréquence est inférieure à 400kHz. La question est: Comment résoudre ce problème? ou existe-t-il une autre façon de mesurer un signal d'entrée pwm avec une fréquence élevée?

Merci

+0

Si vous avez un compteur dans votre matériel, surveillez son nombre à intervalles fixes. – linuxfan

Répondre

4

Vous devez configurer votre minuterie en entrée PWM et non capture entrée (TIM1 par exemple, peut le faire). De cette façon, 2 canaux sont utilisés (mais vous n'avez qu'une seule connexion physique). Fondamentalement, le premier canal vous donnera la période et le deuxième canal vous donnera le pouls. Les compteurs sont automatiquement réinitialisés.

La fonction init:

void tim_init() 
{ 
    TIM_SlaveConfigTypeDef sSlaveConfig; 
    TIM_IC_InitTypeDef sConfigIC; 
    TIM_MasterConfigTypeDef sMasterConfig; 

    htim1.Instance = TIM1; 
    htim1.Init.Prescaler = 0; 
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP; 
    htim1.Init.Period = 65535; 
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 
    htim1.Init.RepetitionCounter = 0; 
    HAL_TIM_IC_Init(&htim1); 

    sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; 
    sSlaveConfig.InputTrigger = TIM_TS_TI2FP2; 
    sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING; 
    sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1; 
    sSlaveConfig.TriggerFilter = 0; 
    HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig); 

    sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING; 
    sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI; 
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; 
    sConfigIC.ICFilter = 0; 
    HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1); 

    sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; 
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; 
    HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2); 

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 
    HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig); 

    //Enable interrupt 
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2); 
    HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1); 
} 

Et le gestionnaire d'interruption

void tim_irq() 
{ 
    period = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2); 
    pulse = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1); 

    //First irq to be ignored 
} 
1

Vous pouvez calculer les cycles que votre code prend dans votre interruption et ajoutez les cycles supplémentaires pour la latence d'interruption (10-20 ?). Ensuite, vous pouvez voir quelle sera votre fréquence de capture maximale. Je parie que ce sera près de 400Khz.

Je pense qu'il n'y a aucun moyen que cela puisse être fait avec STM-F401RE fonctionnant à 80Mhz.

+0

Salut, dans mon interruption-rountine il n'y a qu'une seule variable incrémentée. 'void HAL_TIM_IC_CaptureCallback (* htim) { edgeCounter ++; } ' Je ne pense pas que cela prenne trop de cycles pour cela. Je laisse le programme tourner pendant environ 100ms puis je calcule la fréquence en fonction du nombre de 'edgeCounter'. Il est capable de détecter la fréquence de 2.9MHz, mais il y a toujours une incertitude autour de 5kHz. Comme je l'ai vu du code, le nombre d'arêtes détectées a une grande variation. – bienle