Actually there is a dedicated PWM input mode for advanced timer like TIM1/8, you can find the description in STM reference manual. Its implementation resembles yours, but easier to configure.
Thx alot for this video! Best way of learning something is by doing it. This gave me a grasp on all the concepts that eluded me when I tried to understand it only through documentation and PDF's.
Thanks for the helpful tutorial. If you use uint16_t instead of uint32_t for those variables, you don't need to reset the timer to zero, and you don't need to check if val2 > val1 before doing the subtraction. Not needing to reset the timer is very important, because then you can run one of these PWM inputs on each channel of the timer. If one channel is allowed to reset the timer to zero, you can't really do anything useful with the other 3 channels. uint16_t pwmVal1 = 0; uint16_t pwmVal2 = 0; uint16_t pwmLength = 0; uint8_t whichEdge = 0; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if ( htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3 ) { if ( whichEdge == 0 ) { pwmVal1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_FALLING); whichEdge = 1; } else { pwmVal2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_RISING); pwmLength = pwmVal2 - pwmVal1; whichEdge = 0; } } }
Another great example that demonstrates how to use timers to measure pulse width. In case someone also wants to measure signal frequency you can do so using the formula: frequency (in Hertz) = 1 / period (in seconds) frequency(Hz) = 1 * 1000 * 1000 / 5000(us) = 200 Hetz
No it won't work. That's how the registers are designed. If you input the value 0, it will be assumed as 1. That's why we need to set the value 1 less than what we actallu want.
awesome video. thanks for posting. I also use AC6, how do you enable the predictive text in the editor? of are you just using a combination of keys to do that? Thanks
What compiler version are you using? the __HAL_TIM_SET_CAPTUREPOLARITY just give me errors, say that the definition of that macro is messed up "../Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim.h:1745:106: error: expected ':' before ')' token" I have the 1.8.0 "STM32CUBE MCU Package for STM32F1 Series"
The __HAL_TIM_SET_CAPTUREPOLARITY macro calls for another two macros. In order to set a new Capture Polarity, the first one must be erased, so first calls for TIM_RESET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__)); then for TIM_SET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__), (__POLARITY__)); BUT the reset macro had a ')' in a wrong place, so it wouldn't work until I erase it. Originaly: (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP))) :\ just ereasing the extra ')' (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\ I don't know why, I started 3 different projects and It was always the same problem so I fixed it manually
I am dooing same thing on kiel, initialized through stm32cubeMX using timer 3-channel-1, but code showing error on __HAL_TIM_SET_CAPTUREPOLARIT(........);
I have tried and followed same method which you are doing above but it didnot wokring . IM using stm32GX series - generating PWM output with 10Khz output freq , Dutycycle -50% and in another channel doing Input capture with 1us time.
what I found is when im changing dutycycle of pwm, the Difference is not changing for any dutycycle, it is showing same DIfference value for all the dutycycle (Difference = IC_val2- IC_val1). how to figure out this? @Controllers Tech
Do u connected GND to GND and just one signal pin to PB3? Because now i'm capturing 100% of duty cycle because i'm reading just rissing edge, how i can read falling edge?
Hi we don't measured period here. We need period to calculate duty. (IC_Val2 - IC_Val1)/ period is duty cycle. duty cycle = ton/T. T = ton + toff if you measure between 2 rising edge then this is period.
Not very clear what you're asking. Are you asking how to split one PWM value (timer channel) into three signals? Which doesn't make sense unless your PWM signal is somehow encoded. I suspect you're asking how to read multiple PWM values (timer channels). (I haven't tried but) It should be straight forward by selecting more than one channel to capture the input (each timer offers four channels). Then in your main start capturing like so: HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // TIM2 Channel 1 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2); // TIM2 Channel 2 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3); // TIM2 Channel 3 As each signal goes HIGH microcontroller will set an interrupt. You just need to add appropriate logic inside HAL_TIM_IC_CaptureCallback() function to distinguish between multiple channels and that should be it. Of course, if that doesn't work then you set up three single-channel captures just like this example demonstrate. You have four times at your disposal (assuming that you're using STMF103C8).
I guess yes. In the interrupt callback, i am checking for the active channel. You just write another if statement and check for another channel. I don't know if there is some restriction about IC selection within the channels. That depends on the timer and your MCU.
The range of values starts with "0". "0" means: divide by "1" (aka "no division"). So if we enter "72", it will mean: divide by 73. Thus in order to divide by 72 we need to enter "71", aka "72-1".
@@ControllersTech but "void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)" function is only one. now, i am student, i don't know how to use 2 timer for 1 function.
@@ControllersTech i did try to copy the code but when i set it on stm studio all the ic value and difference got the same address (0x00) but i dont know why, btw im using stm32f4