cancel
Showing results for 
Search instead for 
Did you mean: 

Where can I read more about the syntax of callback function (or just about any function)?

Anh Tran
Associate II

I have been trying to learn the STM32 for the past week. As someone started with Arduino, this is quite frankly overwhelming to me.

Anyways, what I couldn't wrap my head around is where do people find all the reference for the callback function.

I'm currently follow the book Mastering STM32. It seems like after generate the skeleton code from CubeMx, the author write some callback function in the main() and for some reason, these function will just be used when an event happened. Can someone explain to me why in layman terms?

Another section of STM32 I felt quite overwhelming is the Timers. I'm working through the Input Capture function of a General Purpose Timer. I (think) I understand the gist of it. And as a way for me to evaluate my knowledge, I would like to measure the frequency of a square wave signal generated from a signal generator. However, different tutorial are using different way (for example the Mastering STM32 are using DMA, which added another level of complexity) and I just couldn't really understand why so and so.

My current understanding is if we enable one of the timer's channel (let's say channel 1), and enable the interrupt in NVIC settings, we can detect the rising edge of each pulse to calculate the period T of the signal. But how do we actually do so, in term of coding? Does the timer call a callback function (I'm guessing in this case HAL_TIM_IC_CaptureCallback) everytime an edge is detect? Can someone explain this concept to me?

Thank you so much!

8 REPLIES 8
Anh Tran
Associate II

So I have been trying a bit more and here's the current code I wrote (it didn't work as expected). Can someone point out my mistake, or no mistake at all and I'm having some other errors in hardware setup. Thanks!

RomainR.
ST Employee

Hello Anh Tran.

Can you specify which family of STM32 do you use, which board Nucleo, Discovery ?

Since you are using STM32CubeMX, take a look at the Timer examples and especially

C: \ Users \ yourlogin \ STM32Cube \ Repository \ STM32Cube_FW_F4_V1.24.1 \ Projects \ STM32F401RE-Nucleo \ Templates \ TIM \ TIM_PWMInput

The Timer is used in PWN In Mode and several interrupt are generated by the edge of input signal applied on the dedicated Tim Channel.

The main.c code shows you how to use a HAL_TIM_IC_CaptureCallback to read the value of the Timer on the rising edge and the falling edge in order to compute the period and the duty cycle of input signal.

Let me know.

BR

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

RomainR.
ST Employee

After review your code, it seems you don't set a period value for the TIM4 structure, htim4.Init.Period = 0; ?

See below

/**
  * @brief TIM4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM4_Init(void)
{
 
  /* USER CODE BEGIN TIM4_Init 0 */
 
  /* USER CODE END TIM4_Init 0 */
 
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
 
  /* USER CODE BEGIN TIM4_Init 1 */
 
  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 0;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_IC_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi, I'm currently using a Nucleo board, STM32F411RE.

Thanks for pointing out the Period, I didn't realised it would be set to zero since I thought Cubemx would handle that.

Now, when I set Period to be 65535, it does produce some numbers. The "pulse_width" value is anywhere around 1500 to 2500. So, is this the value of the clock tick, which means I have to use the frequency of the STM32F411 to calculate pulse_width in ms? Also, since I'm using a square wave with 3.3Vpp, 1.65Vdc offset, 100Hz as an input for PB6. I would thought that "pulse_width" would be more consistent.

One more question, I found another function called __HAL_TIM_SET_COMPARE, which I didn't use. And since I'm using __HAL_TIM_GET_COMPARE, I would have thought I might need to use __HAL_TIM_SET_COMPARE, no? Can you explain what these 2 functions do?

Anyways, this is a big result for me, so thank you again!

RomainR.
ST Employee

To compute pulse width into ms, if STM32F411RE run at 84MHz, the APB Timer bus is also clocked at the same frequency. So as you don't divide (by using prescaler field) APB frequency applied to TIMER4, the frequency tick resolution of your setup is 84MHz (ie 12ns).

In fact if your input signal is 100Hz (ie 10ms) yous Timer resolution doesn't match. Because TIMER4 count every 12ns and generate an oferflow at 65535 * 12ns = 733µs.

And it's under your signal period.

Best way is to divide TIMER4 input clock to 84 to obtain 1µs of tick resolution (SYSCLK = 84MHz).

htim4.Init.Prescaler = 83;    /* Timer start from 0 to 0XFFFF so need Prescaler Value - 1, divide APB bus frequency by 84 - 1 to reach timer tick = 1µs */

And maintain Period at the same value

htim4.Init.Period = 65535;       /* In this case at 1µs Tick, overflow is 65535µs */

With these settings, the pulse width value are reflected directly in µs.

Computation is now easy.

Concerning __HAL_TIM_SET_COMPARE function, it used for PWM output generation (defined into stm32f4xx_tim.h HAL API)

It used to change on run time the Capture Copare register without changing the setup of the Timer peripheral.

You don't need it for your case.

Yes you must use __HAL_TIM_GET_COMPARE to read Capture compare register.

BR

rrom

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi,

Since STM32F411RE runs at 100MHz, I set the Prescaler as (10000-1), which give the resolution of 100 us. So if my signal is running at 100Hz, it should give 100 ticks but instead it gives 86 ticks, weird. Can you explain this phenomenon?

But it is consistent so that's an improvement. Thanks!

Edit: So I figured out that by looking at the clock config in CubeMX, HCLK is set to be 84Mhz, which might explain why you said STM32F411RE running at 84MHz. Can you explain why it is that way, especially since the CPU clock is 100MHz in the datasheet. I think I read somewhere that the CPU clock is only the maximum value of the peripheral's clock, but not the actual value. So where in the user manual/datasheet can I refer to? If you could give me a link that would be a great help. Thanks!

Edit2: Ok, so after playing around with the nucleo board and the signal generator a bit more, I find that the calculated frequency is off by a few hertz (if I set the square signal to be 100Hz, the actual calculated frequency is 98Hz).

Note: I want to change the attach file for this comment but I can't, so I make another reply with another attached file :p

Hi,

Since STM32F411RE runs at 100MHz, I set the Prescaler as (10000-1), which give the resolution of 100 us. So if my signal is running at 100Hz, it should give 100 ticks but instead it gives 86 ticks, weird. Can you explain this phenomenon?

But it is consistent so that's an improvement. Thanks!

Edit: So I figured out that by looking at the clock config in CubeMX, HCLK is set to be 84Mhz, which might explain why you said STM32F411RE running at 84MHz. Can you explain why it is that way, especially since the CPU clock is 100MHz in the datasheet. I think I read somewhere that the CPU clock is only the maximum value of the peripheral's clock, but not the actual value. So where in the user manual/datasheet can I refer to? If you could give me a link that would be a great help. Thanks!

Edit2: Ok, so after playing around with the nucleo board and the signal generator a bit more, I find that the calculated frequency is off by a few hertz (if I set the square signal to be 100Hz, the actual calculated frequency is 98Hz).

RomainR.
ST Employee

Of course STM32F411RE can reach 100MHz.

If your intention is that your CPU works at 100MHz, you must change your SystemClock_Config () function. Change your PLLN = 400.

Because currently, according to your code, your SYSCLK is at 84MHz and was probably generated by default by CubeMX. This explains why your TIM4 resolution is not exactly 100μs, so you get values of 84.

If however a SYSCLK frequency of 84MHz is suitable for your application, simply change your TIM4 Prescaler to 8399, and you should get your value of 100.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.