stm32F4 pwm input capture of high frequency signal approx. 2MHz?

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

I want to measure the frequency of a PWM signal. To do that, I'm using STM-F401RE and its Timer_Input_Capture function.

The problem is:

  • the input signal has a quite high frequency (approx. 2MHz) and,
  • the STM-F401RE controller has only a 80MHz clock

Therefore when using an interrupt routine for counting the number of rising edge of the input signal, it misses many rising edges (depending on the frequency of the input signal). When using an Oscilloscope and toggling an I/O-pin, I saw that it can only capture all the rising edge when the frequency is lower than 400kHz.

Question is: How to overcome this problem? or is there another way to measure an input pwm signal with high frequency ?

Thanks

回答1:

You need to setup your timer as PWM input and not capture input (TIM1 for example can do it). This way, 2 channels are used (but you have only one physical connection). Basically, the first channel will give you the period and the second channel will give you the pulse. The counters are automatically reset.

The init function:

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); } 

And the interrupt handler

void tim_irq() {     period = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);     pulse = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);      //First irq to be ignored } 


回答2:

You can calculate the cycles that your code takes in your interrupt and add the extra cycles for interrupt latency (10-20 ?). Then you can see what your maximum capture frequency will be. I'll bet it will be close to 400Khz.

I think there is no way that this can be done with STM-F401RE running at 80Mhz.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!